Anabatic transient commit 11. Merge Katabatic into Anabatic.

* New: In Anabatic, merge in the Katabatic tool. The merge is not complete
    yet. Only basic capabilities have been moved.
This commit is contained in:
Jean-Paul Chaput 2016-07-18 14:48:37 +02:00
parent 6bc2c1b94d
commit 9114766129
36 changed files with 13464 additions and 258 deletions

View File

@ -21,6 +21,7 @@
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Cell.h"
#include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/GCell.h"
@ -39,11 +40,28 @@ namespace Anabatic {
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::Cell;
using Hurricane::DebugSession;
using Hurricane::UpdateSession;
using CRL::RoutingGauge;
using CRL::RoutingLayerGauge;
// -------------------------------------------------------------------
// Error messages.
const char* missingAnbt =
"%s :\n\n"
" Cell %s do not have any Anabatic (or not yet created).\n";
const char* badMethod =
"%s :\n\n"
" No method id %ud (Cell %s).\n";
const char* lookupFailed =
"Anabatic::Extension::getDatas(Segment*) :\n\n"
" Cannot find AutoSegment associated to %s (internal error).\n";
// -------------------------------------------------------------------
// Class : "Anabatic::AnabaticEngine".
@ -66,12 +84,16 @@ namespace Anabatic {
: Super(cell)
, _timer ()
, _configuration (new ConfigurationConcrete())
, _state (EngineCreation)
, _matrix ()
, _gcells ()
, _ovEdges ()
, _viewer (NULL)
, _flags (Flags::NoFlags)
, _flags (Flags::DestroyBaseContact)
, _stamp (-1)
, _densityMode (MaxDensity)
, _autoSegmentLut()
, _autoContactLut()
{
_matrix.setCell( cell, _configuration->getSliceHeight() );
Edge::unity = _configuration->getSliceHeight();
@ -108,19 +130,71 @@ namespace Anabatic {
void AnabaticEngine::_preDestroy ()
{
_clear();
cdebug_log(145,1) << "Anabatic::_preDestroy ()" << endl;
if (getState() < EngineGutted)
setState( EnginePreDestroying );
_gutAnabatic();
_state = EngineGutted;
cdebug_log(145,0) << "About to delete base class ToolEngine." << endl;
Super::_preDestroy();
//cmess2 << " - GCells := " << GCell::getAllocateds() << endl;
cmess2 << " - AutoContacts := " << AutoContact::getAllocateds() << endl;
cmess2 << " - AutoSegments := " << AutoSegment::getAllocateds() << endl;
cdebug_log(145,0) << "Exiting Anabatic::_preDestroy()." << endl;
cdebug_tabw(145,-1);
}
void AnabaticEngine::_clear ()
void AnabaticEngine::_gutAnabatic ()
{
_flags |= Flags::Destroy;
Session::open( this );
for ( GCell* gcell : _gcells ) gcell->_destroyEdges();
for ( GCell* gcell : _gcells ) gcell->destroy();
_gcells.clear();
_ovEdges.clear();
_flags.reset( Flags::DestroyBaseContact|Flags::DestroyBaseSegment );
if (_state == EngineDriving) {
cdebug_log(145,1) << "Saving AutoContacts/AutoSegments." << endl;
size_t fixedSegments = 0;
size_t sameLayerDoglegs = 0;
for ( auto isegment : _autoSegmentLut ) {
if (isegment.second->isFixed()) ++fixedSegments;
if (isegment.second->reduceDoglegLayer()) ++sameLayerDoglegs;
}
cmess1 << " o Driving Hurricane data-base." << endl;
cmess1 << Dots::asSizet(" - Active AutoSegments",AutoSegment::getAllocateds()-fixedSegments) << endl;
cmess1 << Dots::asSizet(" - Active AutoContacts",AutoContact::getAllocateds()-fixedSegments*2) << endl;
cmess1 << Dots::asSizet(" - AutoSegments" ,AutoSegment::getAllocateds()) << endl;
cmess1 << Dots::asSizet(" - AutoContacts" ,AutoContact::getAllocateds()) << endl;
cmess1 << Dots::asSizet(" - Same Layer doglegs" ,sameLayerDoglegs) << endl;
//for ( Net* net : _cell->getNets() ) _saveNet( net );
cdebug_tabw(145,-1);
}
if (_state < EngineGutted ) {
cdebug_log(145,0) << "Gutting Anabatic." << endl;
_state = EngineGutted;
_flags |= Flags::DestroyBaseContact;
_destroyAutoSegments();
_destroyAutoContacts();
_flags |= Flags::DestroyGCell;
for ( GCell* gcell : _gcells ) gcell->_destroyEdges();
for ( GCell* gcell : _gcells ) gcell->destroy();
_gcells.clear();
_ovEdges.clear();
}
Session::close();
}
@ -162,8 +236,9 @@ namespace Anabatic {
void AnabaticEngine::reset ()
{
_clear();
_flags.reset( Flags::Destroy );
_gutAnabatic();
_flags.reset( Flags::DestroyMask );
_state = EngineCreation;
UpdateSession::open();
GCell::create( this );
@ -204,6 +279,257 @@ namespace Anabatic {
}
void AnabaticEngine::cleanupGlobal ()
{
UpdateSession::open();
for ( GCell* gcell : _gcells ) gcell->cleanupGlobal();
UpdateSession::close();
}
void AnabaticEngine::loadGlobalRouting ( unsigned int method )
{
if (_state < EngineGlobalLoaded)
throw Error ("AnabaticEngine::loadGlobalRouting() : global routing not present yet.");
if (_state > EngineGlobalLoaded)
throw Error ("AnabaticEngine::loadGlobalRouting() : global routing already loaded.");
switch ( method ) {
case EngineLoadGrByNet: _loadGrByNet(); break;
case EngineLoadGrByGCell:
default:
throw Error( badMethod
, "Anabatic::loadGlobalRouting()"
, method
, getString(_cell).c_str()
);
}
cleanupGlobal();
_state = EngineActive;
}
void AnabaticEngine::updateNetTopology ( Net* net )
{
DebugSession::open( net, 140, 150 );
cdebug_log(149,0) << "Anabatic::updateNetTopology( " << net << " )" << endl;
cdebug_tabw(145,1);
vector<AutoContact*> contacts;
for ( Component* component : net->getComponents() ) {
Contact* contact = dynamic_cast<Contact*>( component );
if (contact) {
AutoContact* autoContact = Session::lookup( contact );
if (autoContact and autoContact->isInvalidatedCache())
contacts.push_back( autoContact );
}
}
for ( size_t i=0 ; i<contacts.size() ; ++i )
contacts[i]->updateTopology();
cdebug_tabw(145,-1);
DebugSession::close();
}
void AnabaticEngine::finalizeLayout ()
{
cdebug_log(145,0) << "Anabatic::finalizeLayout()" << endl;
if (_state > EngineDriving) return;
_state = EngineDriving;
startMeasures();
_gutAnabatic();
stopMeasures ();
printMeasures( "fin" );
_state = EngineGutted;
}
void AnabaticEngine::_alignate ( Net* net )
{
DebugSession::open( net, 140, 150 );
cdebug_log(149,0) << "Anabatic::_alignate( " << net << " )" << endl;
cdebug_tabw(145,1);
//cmess2 << " - " << getString(net) << endl;
set<Segment*> exploredSegments;
vector<AutoSegment*> unexploreds;
vector<AutoSegment*> aligneds;
for ( Component* component : net->getComponents() ) {
Segment* segment = dynamic_cast<Segment*>(component);
if (segment) {
AutoSegment* seedSegment = Session::lookup( segment );
if (seedSegment) unexploreds.push_back( seedSegment );
}
}
sort( unexploreds.begin(), unexploreds.end(), AutoSegment::CompareId() );
for ( size_t i=0 ; i<unexploreds.size() ; i++ ) {
AutoSegment* seedSegment = unexploreds[i];
if (exploredSegments.find(seedSegment->base()) == exploredSegments.end()) {
cdebug_log(145,0) << "New chunk from: " << seedSegment << endl;
aligneds.push_back( seedSegment );
for ( AutoSegment* collapsed : seedSegment->getAligneds() ) {
cdebug_log(145,0) << "Aligned: " << collapsed << endl;
aligneds.push_back( collapsed );
exploredSegments.insert( collapsed->base() );
}
cdebug_tabw(145,1);
sort( aligneds.begin(), aligneds.end(), AutoSegment::CompareId() );
cdebug_log(145,0) << "Seed: " << (void*)aligneds[0]->base() << " " << aligneds[0] << endl;
for ( size_t j=1 ; j<aligneds.size() ; j++ ) {
cdebug_log(145,0) << "Secondary: " << (void*)(aligneds[j]->base()) << " " << aligneds[j] << endl;
}
cdebug_log(149,0) << "Align on " << aligneds[0]
<< " " << DbU::toLambda(aligneds[0]->getAxis()) << endl;
aligneds[0]->setAxis( aligneds[0]->getAxis(), Flags::Realignate );
aligneds.clear();
cdebug_tabw(145,-1);
}
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AnabaticEngine::_computeNetTerminals ( Net* net )
{
DebugSession::open( net, 140, 150 );
cdebug_log(149,0) << "Anabatic::_computeNetTerminals( " << net << " )" << endl;
cdebug_tabw(145,1);
for ( Segment* segment : net->getSegments() ) {
AutoSegment* autoSegment = Session::lookup( segment );
if (autoSegment == NULL) continue;
if (autoSegment->isInvalidated()) autoSegment->computeTerminal();
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AnabaticEngine::_saveNet ( Net* net )
{
DebugSession::open( net, 140, 150 );
cdebug_log(145,0) << "Anabatic::_saveNet() " << net << endl;
cdebug_tabw(145,1);
#if 0
cdebug_log(145,0) << "Deleting zero-length segments." << endl;
vector<Segment*> nullSegments;
set<const Layer*> connectedLayers;
forEach ( Segment*, segment, net->getSegments() ) {
if (segment->getLength()) {
if (net->isExternal()) {
NetExternalComponents::setExternal( *segment );
}
continue;
}
if (Session::lookup(*segment) == NULL) {
cdebug_log(145,0) << "* Not associated to an AutoSegment: " << *segment << endl;
continue;
}
if (not isTopAndBottomConnected(*segment,connectedLayers)) {
nullSegments.push_back( *segment );
cdebug_log(145,0) << "* Null Length: " << *segment << endl;
}
}
setFlags( EngineDestroyBaseSegment );
for ( size_t i = 0 ; i < nullSegments.size() ; i++ ) {
Contact* source = dynamic_cast<Contact*>(nullSegments[i]->getSource());
Contact* target = dynamic_cast<Contact*>(nullSegments[i]->getTarget());
if ( (source == NULL) or (target == NULL) ) {
cerr << Error("Unconnected source/target on %s.",getString(nullSegments[i]).c_str()) << endl;
continue;
}
if (source->getAnchor()) {
if (target->getAnchor()) {
continue;
//cerr << Bug("Both source & target are anchored while deleting zero-length segment:\n"
// " %s.",getString(nullSegments[i]).c_str()) << endl;
} else
swap( source, target );
}
cdebug_log(145,0) << "Deleting: " << nullSegments[i] << endl;
if (isTopAndBottomConnected(nullSegments[i],connectedLayers)) {
cdebug_log(145,0) << "Deletion cancelled, no longer top or bottom connected." << endl;
continue;
}
cdebug_log(145,0) << "* Source: " << (void*)source << " " << source << endl;
cdebug_log(145,0) << "* Target: " << (void*)target << " " << target << endl;
const Layer* layer = DataBase::getDB()->getTechnology()
->getViaBetween( *connectedLayers.begin(), *connectedLayers.rbegin() );
cdebug_log(145,0) << *connectedLayers.begin() << " + " << *connectedLayers.rbegin() << endl;
cdebug_log(145,0) << "* Shrink layer: " << layer << endl;
if ( !layer ) {
cerr << Error("NULL contact layer while deleting %s."
,getString(nullSegments[i]).c_str()) << endl;
continue;
}
Session::lookup( nullSegments[i] )->destroy ();
vector<Hook*> slaveHooks;
Hook* masterHook = source->getBodyHook()->getPreviousMasterHook();
while ( masterHook->getNextHook() != source->getBodyHook() ) {
slaveHooks.push_back( masterHook->getNextHook() );
cdebug_log(145,0) << "* detach: "
<< (void*)masterHook->getNextHook()->getComponent()
<< " " << masterHook->getNextHook()->getComponent() << endl;
masterHook->getNextHook()->detach();
}
source->destroy();
masterHook = target->getBodyHook();
for ( size_t j=0 ; j < slaveHooks.size() ; j++ ) {
slaveHooks[j]->attach( masterHook );
}
cdebug_log(145,0) << (void*)target << " " << target << " setLayer: " << layer << endl;
target->setLayer( layer );
}
unsetFlags( EngineDestroyBaseSegment );
#endif
cdebug_tabw(145,-1);
DebugSession::close();
}
void AnabaticEngine::startMeasures ()
{
_timer.resetIncrease();
@ -231,6 +557,88 @@ namespace Anabatic {
}
void AnabaticEngine::updateDensity ()
{ for ( GCell* gcell : _gcells ) gcell->updateDensity(); }
AutoSegment* AnabaticEngine::_lookup ( Segment* segment ) const
{
AutoSegmentLut::const_iterator it = _autoSegmentLut.find( segment );
if (it == _autoSegmentLut.end()) return NULL;
return (*it).second;
}
void AnabaticEngine::_link ( AutoSegment* autoSegment )
{
if (_state > EngineActive) return;
_autoSegmentLut[ autoSegment->base() ] = autoSegment;
}
void AnabaticEngine::_unlink ( AutoSegment* autoSegment )
{
if (_state > EngineDriving) return;
AutoSegmentLut::iterator it = _autoSegmentLut.find( autoSegment->base() );
if (it != _autoSegmentLut.end())
_autoSegmentLut.erase( it );
}
AutoContact* AnabaticEngine::_lookup ( Contact* contact ) const
{
AutoContactLut::const_iterator it = _autoContactLut.find( contact );
if (it == _autoContactLut.end()) {
return NULL;
}
return (*it).second;
}
void AnabaticEngine::_link ( AutoContact* autoContact )
{
if (_state > EngineActive) return;
_autoContactLut [ autoContact->base() ] = autoContact;
}
void AnabaticEngine::_unlink ( AutoContact* autoContact )
{
if ( _state > EngineActive ) return;
AutoContactLut::iterator it = _autoContactLut.find( autoContact->base() );
if (it != _autoContactLut.end())
_autoContactLut.erase( it );
}
void AnabaticEngine::_destroyAutoSegments ()
{
cdebug_log(145,0) << "Anabatic::_destroyAutoSegments ()" << endl;
size_t expandeds = 0;
for ( auto sasp : _autoSegmentLut ) {
expandeds++;
sasp.second->destroy();
}
if (_state == EngineDriving)
cmess2 << " - Expandeds := " << expandeds << endl;
_autoSegmentLut.clear();
}
void AnabaticEngine::_destroyAutoContacts ()
{
cdebug_log(145,0) << "Anabatic::_destroyAutoContacts ()" << endl;
for ( auto cacp : _autoContactLut ) cacp.second->destroy();
_autoContactLut.clear();
}
string AnabaticEngine::_getTypeName () const
{ return getString(_toolName); }

View File

@ -0,0 +1,631 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoContact.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <climits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Layer.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/Plug.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/AnabaticEngine.h"
#include "anabatic/Session.h"
namespace Anabatic {
using std::ostringstream;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::DebugSession;
using Hurricane::ForEachIterator;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContact".
size_t AutoContact::_maxId = 0;
size_t AutoContact::_allocateds = 0;
const Name AutoContact::_goName = "Anabatic::AutoContact";
AutoContact::AutoContact ( GCell* gcell, Contact* contact )
: _id (contact->getId())
, _contact (contact)
, _gcell (gcell)
, _flags (CntInvalidatedCache|CntInCreationStage)
, _dxMin (0)
, _dxMax ((int)DbU::toLambda( _gcell->getXMax()-_gcell->getXMin() ))
, _dyMin (0)
, _dyMax ((int)DbU::toLambda( _gcell->getYMax()-_gcell->getYMin() ))
{
_allocateds++;
_gcell->addContact ( this );
}
void AutoContact::_preCreate ( GCell* gcell, Net* net, const Layer* layer )
{
if (not gcell) throw Error("AutoContact::_preCreate(): GCell* parameter must not be NULL.");
if (not net ) throw Error("AutoContact::_preCreate(): Net* parameter must not be NULL.");
if (not layer) throw Error("AutoContact::_preCreate(): const Layer* parameter must not be NULL.");
}
void AutoContact::_postCreate ()
{
restoreNativeConstraintBox();
cdebug_log(145,0) << "Native CBox: " << this
<< " <" << DbU::toLambda(getCBXMin())
<< " " << DbU::toLambda(getCBYMin())
<< " " << DbU::toLambda(getCBXMax())
<< " " << DbU::toLambda(getCBYMax()) << ">" << endl;
Session::link( this );
invalidate( Flags::Topology );
cdebug_log(145,0) << "AutoContact::_postCreate() - " << this << " in " << _gcell << endl;
}
void AutoContact::destroy ()
{
_preDestroy ();
delete this;
}
void AutoContact::_preDestroy ()
{
DebugSession::open( _contact->getNet(), 140, 150 );
cdebug_log(145,0) << "AutoContact::_preDestroy() - <AutoContact id:" << _id << ">" << endl;
#if 0
bool canDestroyBase = true;
if (not _contact->getSlaveComponents().isEmpty()) {
ostringstream message;
message << "Base contact still have slaves components, cancelled.\n"
<< " on: " << this;
forEach ( Component*, icomponent, _contact->getSlaveComponents() ) {
message << "\n | " << (*icomponent);
}
cerr << Error( message.str() ) << endl;
canDestroyBase = false;
}
#endif
if (not Session::doDestroyTool()) {
_gcell->removeContact( this );
Session::unlink( this );
}
#if 0
if (Session::doDestroyBaseContact() and canDestroyBase)
_contact->destroy();
#endif
DebugSession::close();
}
AutoContact::~AutoContact ()
{ _allocateds--; }
size_t AutoContact::getAllocateds ()
{ return _allocateds; }
const Name& AutoContact::getStaticName ()
{ return _goName; }
bool AutoContact::canDestroy ( unsigned int flags ) const
{
if (not _contact->getSlaveComponents().isEmpty()) {
if (flags & Flags::WarnOnError) {
cerr << Error("Base contact still have slaves components, cancelled.\n"
" (%s)"
,_getString().c_str()) << endl;
}
return false;
}
return true;
}
const Name& AutoContact::getName () const
{ return _goName; }
AutoSegments AutoContact::getAutoSegments ()
{ return new AutoSegments_CachedOnContact(this); }
AutoSegment* AutoContact::getPerpandicular ( const AutoSegment* ) const
{ return NULL; }
unsigned int AutoContact::getMinDepth () const
{
size_t minDepth = (size_t)-1;
Component* anchor = getAnchor ();
if (anchor) {
minDepth = std::min( minDepth, Session::getRoutingGauge()->getLayerDepth(anchor->getLayer()) );
//cdebug_log(149,0) << "Anchor:" << anchor << endl;
}
forEach ( AutoSegment*, isegment, const_cast<AutoContact*>(this)->getAutoSegments() ) {
minDepth = std::min( minDepth, Session::getRoutingGauge()->getLayerDepth(isegment->getLayer()) );
//cdebug_log(149,0) << "Slave:" << *icomponent << endl;
}
return (unsigned int)minDepth;
}
unsigned int AutoContact::getMaxDepth () const
{
size_t maxDepth = 0;
Component* anchor = getAnchor ();
if ( anchor ) {
maxDepth = std::max ( maxDepth, Session::getRoutingGauge()->getLayerDepth(anchor->getLayer()) );
//cdebug_log(149,0) << "Anchor:" << anchor << endl;
}
forEach ( AutoSegment*, isegment, const_cast<AutoContact*>(this)->getAutoSegments() ) {
maxDepth = std::max ( maxDepth, Session::getRoutingGauge()->getLayerDepth(isegment->getLayer()) );
//cdebug_log(149,0) << "Slave:" << *icomponent << endl;
}
return (unsigned int)maxDepth;
}
void AutoContact::getLengths ( DbU::Unit* lengths, AutoSegment::DepthLengthSet& processeds )
{
DbU::Unit hSideLength = getGCell()->getSide( Flags::Horizontal ).getSize();
DbU::Unit vSideLength = getGCell()->getSide( Flags::Vertical ).getSize();
forEach ( AutoSegment*, isegment, getAutoSegments() ) {
bool isSourceHook = (isegment->getAutoSource() == this);
if (processeds.find(*isegment) != processeds.end()) continue;
processeds.insert( *isegment );
size_t depth = Session::getRoutingGauge()->getLayerDepth(isegment->getLayer());
DbU::Unit length;
if (isegment->isLocal()) {
length = isegment->getLength();
lengths[depth] += length;
DbU::Unit sideLength = (isegment->isHorizontal()) ? hSideLength : vSideLength;
if ( not isegment->isUnbound() and (abs(length) > sideLength) )
cerr << Error("Suspicious length:%.2f of %s."
,DbU::toLambda(length),getString(*isegment).c_str()) << endl;
} else {
if ( isegment->isHorizontal() ) {
if (isSourceHook)
lengths[depth] += _gcell->getXMax() - isegment->getSourceX();
else
lengths[depth] += isegment->getTargetX() - _gcell->getXMin();
} else {
if (isSourceHook)
lengths[depth] += _gcell->getYMax() - isegment->getSourceY();
else
lengths[depth] += isegment->getTargetY() - _gcell->getYMin();
}
}
}
}
Box AutoContact::getNativeConstraintBox () const
{
if (isUserNativeConstraints()) return getConstraintBox();
if (isFixed()) return Box(_contact->getPosition());
return _gcell->getBoundingBox();
}
Interval AutoContact::getNativeUConstraints ( unsigned int direction ) const
{
Box nativeConstraints = getNativeConstraintBox();
Interval constraint;
if (direction & Flags::Horizontal) {
constraint = Interval( nativeConstraints.getXMin(), nativeConstraints.getXMax() );
} else {
constraint = Interval( nativeConstraints.getYMin(), nativeConstraints.getYMax() );
}
//if (direction & Flags::NoGCellShrink) constraint.inflate( 0, GCell::getTopRightShrink() );
return constraint;
}
Interval AutoContact::getUConstraints ( unsigned int direction ) const
{
Interval constraint;
if (direction & Flags::Horizontal) {
constraint = Interval( getCBXMin(), getCBXMax() );
} else {
constraint = Interval( getCBYMin(), getCBYMax() );
}
//if (direction & Flags::NoGCellShrink) constraint.inflate( 0, GCell::getTopRightShrink() );
return constraint;
}
void AutoContact::invalidate ( unsigned int flags )
{
if (not isInvalidated()) {
cdebug_log(145,1) << "AutoContact::invalidate() - " << this << endl;
setFlags( CntInvalidated );
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
Session::invalidate( this );
_invalidate( flags );
//forEach( AutoSegment*, isegment, getAutoSegments() )
// isegment->invalidate();
getGCell()->invalidate();
cdebug_tabw(145,-1);
}
}
void AutoContact::setGCell ( GCell* gcell )
{
invalidate();
if (_gcell) _gcell->removeContact( this );
_gcell = gcell;
if (_gcell) {
cdebug_log(145,0) << "AutoContact::setGCell() " << gcell << endl;
_gcell->addContact( this );
_contact->setPosition( _gcell->getCenter() );
_dxMin = 0;
_dyMin = 0;
_dxMax = (int)DbU::toLambda( _gcell->getXMax()-_gcell->getXMin() );
_dyMax = (int)DbU::toLambda( _gcell->getYMax()-_gcell->getYMin() );
cdebug_log(145,0) << "* deltas: [" << _dxMin << " " << _dyMin << " " << _dxMax << " " << _dyMax << "]" << endl;
} else {
cerr << Bug( "NULL GCell for %s.", _getString().c_str() ) << endl;
}
}
void AutoContact::_getTopology ( Contact* support, Component*& anchor, Horizontal**& horizontals, Vertical**& verticals, size_t size )
{
size_t hcount = 0;
size_t vcount = 0;
for ( size_t i=0 ; i<size ; ++i ) {
horizontals[i] = NULL;
verticals [i] = NULL;
}
anchor = support->getAnchor();
forEach ( Component*, icomponent, support->getSlaveComponents() ) {
Horizontal* h = dynamic_cast<Horizontal*>(*icomponent);
if (h != NULL) {
if (hcount < size) horizontals[hcount++] = h;
} else {
Vertical* v = dynamic_cast<Vertical*>(*icomponent);
if ( (v != NULL) and (vcount < size) ) verticals[vcount++] = v;
}
}
}
void AutoContact::showTopologyError ( const std::string& message, unsigned int flags )
{
Component* anchor = NULL;
Horizontal** horizontals = new Horizontal* [10];
Vertical** verticals = new Vertical* [10];
if (not (flags & Flags::CParanoid)) cparanoid.setStreamMask( mstream::PassThrough );
_getTopology ( base(), anchor, horizontals, verticals, 10 );
cparanoid << Error("In topology of %s",getString(this).c_str()) << endl;
if (anchor) cparanoid << " A: " << anchor << endl;
for ( size_t i=0 ; (i<10) and (horizontals[i] != NULL); ++i ) {
AutoSegment* autoSegment = Session::lookup ( horizontals[i] );
if (autoSegment != NULL)
cparanoid << " " << (autoSegment->isGlobal()?'G':'L') << ": " << autoSegment << endl;
else
cparanoid << " ?: " << horizontals[i] << endl;
}
for ( size_t i=0 ; (i<10) and (verticals[i] != NULL); ++i ) {
AutoSegment* autoSegment = Session::lookup ( verticals[i] );
if (autoSegment != NULL)
cparanoid << " " << (autoSegment->isGlobal()?'G':'L') << ": " << autoSegment << endl;
else
cparanoid << " ?: " << verticals[i] << endl;
}
cparanoid << " " << message << endl;
if (not (flags & Flags::CParanoid)) cparanoid.unsetStreamMask( mstream::PassThrough );
delete [] horizontals;
delete [] verticals;
}
void AutoContact::checkTopology ()
{
//cdebug_log(145,0) << "checkTopology() NOT RE-IMPLEMENTED YET " << this << endl;
}
bool AutoContact::isTee ( unsigned int direction ) const
{
return (isHTee() and (direction & Flags::Horizontal))
or (isVTee() and (direction & Flags::Vertical ));
}
bool AutoContact::canMoveUp ( const AutoSegment* moved ) const
{
cdebug_log(149,0) << "AutoContact::canMoveUp() " << this << endl;
size_t viaDepth = 100;
RoutingGauge* rg = Session::getRoutingGauge();
size_t movedDepth = rg->getLayerDepth(moved->getLayer());
Component* anchor = getAnchor();
if (anchor) {
viaDepth = rg->getLayerDepth( anchor->getLayer() );
cdebug_log(149,0) << "| Anchor depth: " << viaDepth << endl;
}
forEach ( AutoSegment*, isegment, const_cast<AutoContact*>(this)->getAutoSegments() ) {
if (*isegment == moved) continue;
size_t depth = rg->getLayerDepth(isegment->getLayer());
if (viaDepth == 100) viaDepth = depth;
else
if (viaDepth != depth) return false;
cdebug_log(149,0) << "| Segment depth: " << depth << endl;
}
return (movedDepth+1 == viaDepth);
}
void AutoContact::setConstraintBox ( const Box& box )
{
setCBXMin ( box.getXMin() );
setCBXMax ( box.getXMax() );
setCBYMin ( box.getYMin() );
setCBYMax ( box.getYMax() );
cdebug_log(149,0) << "setConstraintBox() - " << this << " " << getConstraintBox() << endl;
cdebug_log(149,0) << "* " << _gcell << endl;
}
bool AutoContact::restrictConstraintBox ( DbU::Unit constraintMin
, DbU::Unit constraintMax
, unsigned int flags
)
{
cdebug_log(149,0) << "restrictConstraintBox() - " << this << " " << getConstraintBox() << endl;
if (flags & Flags::Horizontal) {
if ( (constraintMin > getCBYMax()) or (constraintMax < getCBYMin()) ) {
if ( Session::isInDemoMode() or not (flags & Flags::WarnOnError) ) return false;
cerr << Error ( "Incompatible DY restriction on %s", _getString().c_str() ) << endl;
if ( constraintMin > getCBYMax() )
cerr << Error ( "(constraintMin > CBYMax : %.2lf > %.2lf)"
, DbU::toLambda(constraintMin)
, DbU::toLambda(getCBYMax()) )
<< endl;
if ( constraintMax < getCBYMin() )
cerr << Error ( "(constraintMax < CBYMin : %.2lf < %.2lf)"
, DbU::toLambda(constraintMax)
, DbU::toLambda(getCBYMin()) )
<< endl;
return false;
}
setCBYMin ( std::max(getCBYMin(),constraintMin) );
setCBYMax ( std::min(getCBYMax(),constraintMax) );
} else if (flags & Flags::Vertical) {
if ( (constraintMin > getCBXMax()) || (constraintMax < getCBXMin()) ) {
if ( Session::isInDemoMode() or not (flags & Flags::WarnOnError) ) return false;
cerr << Error ( "Incompatible DX restriction on %s", _getString().c_str() ) << endl;
if ( constraintMin > getCBXMax() )
cerr << Error ( "(constraintMin > CBXMax : %.2lf > %.2lf)"
, DbU::toLambda(constraintMin)
, DbU::toLambda(getCBXMax()) )
<< endl;
if ( constraintMax < getCBXMin() )
cerr << Error ( "(constraintMax < CBXMin : %.2lf < %.2lf)"
, DbU::toLambda(constraintMax)
, DbU::toLambda(getCBXMin()) )
<< endl;
return false;
}
setCBXMin ( std::max(getCBXMin(),constraintMin) );
setCBXMax ( std::min(getCBXMax(),constraintMax) );
}
cdebug_log(149,0) << "restrictConstraintBox() - " << this << " " << getConstraintBox() << endl;
return true;
}
void AutoContact::restoreNativeConstraintBox ()
{ setConstraintBox ( getNativeConstraintBox() ); }
Box& AutoContact::intersectConstraintBox ( Box& box ) const
{ return box = box.getIntersection ( getConstraintBox() ); }
void AutoContact::migrateConstraintBox ( AutoContact* other )
{
if (_gcell != other->_gcell) {
cerr << Error( "AutoContact::migrateConstraintBox(): AutoContacts do not belongs to the same GCell:\n"
" from: %s\n"
" to: %s"
, getString(other).c_str()
, getString(this ).c_str()
) << endl;
return;
}
setConstraintBox( other->getConstraintBox() );
other->restoreNativeConstraintBox();
}
Box AutoContact::getBoundingBox () const
{ return _gcell->getBoundingBox (); }
void AutoContact::translate ( const DbU::Unit& tx, const DbU::Unit& ty )
{
cerr << Warning("Calling AutoContact::translate() is likely a bug.") << endl;
_contact->translate ( tx, ty );
}
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::getAnabatic()->getGCellUnder( 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"; }
string AutoContact::_getString () const
{
string s = _contact->_getString();
size_t i = s.find(' ');
if (i != string::npos) {
s.erase ( i+1, 7 );
s.insert( i+1, _getTypeName() );
}
//s.insert( 1, "id: " );
//s.insert( 4, getString(_id) );
s.insert( s.size()-1, (isFixed ())?" F":" -" );
s.insert( s.size()-1, (isTerminal ())? "T": "-" );
s.insert( s.size()-1, (isHTee ())? "h": "-" );
s.insert( s.size()-1, (isVTee ())? "v": "-" );
s.insert( s.size()-1, (isInvalidated ())? "i": "-" );
s.insert( s.size()-1, (isInvalidatedCache())? "c": "-" );
//s.insert( s.size()-1, getString(getConstraintBox()));
return s;
}
Record* AutoContact::_getRecord () const
{
Record* record = _contact->_getRecord ();
record->add ( getSlot ( "_gcell" , _gcell ) );
record->add ( getSlot ( "_constraintBox", getConstraintBox() ) );
record->add ( getSlot ( "_flags" , _flags ) );
return record;
}
} // Anabatic namespace.

View File

@ -0,0 +1,340 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoContactHTee.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <climits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Layer.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/Plug.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/Session.h"
namespace Anabatic {
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::DebugSession;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactHTee".
AutoContactHTee* AutoContactHTee::create ( GCell* gcell, Net* net, const Layer* layer )
{
DbU::Unit viaSide = Session::getViaWidth( layer );
Contact* contact = Contact::create ( net
, layer
, gcell->getCenter().getX()
, gcell->getCenter().getY()
, viaSide
, viaSide
);
AutoContactHTee* autoContact = new AutoContactHTee ( gcell, contact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
cdebug_log(145,0) << "create(net*) " << autoContact << endl;
return autoContact;
}
AutoContactHTee::AutoContactHTee ( GCell* gcell, Contact* contact )
: AutoContact (gcell,contact)
, _horizontal1(NULL)
, _horizontal2(NULL)
, _vertical1 (NULL)
{
setFlags( CntHTee );
}
AutoContactHTee::~AutoContactHTee ()
{ }
AutoSegment* AutoContactHTee::getOpposite ( const AutoSegment* from ) const
{
if (from == _horizontal1) return _horizontal2;
if (from == _horizontal2) return _horizontal1;
return NULL;
}
AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactHTee::getSegment ( unsigned int index ) const
{
AutoSegment* segment = NULL;
switch ( index ) {
case 0: return _horizontal1;
case 1: return _horizontal2;
case 2: return _vertical1;
}
//if (not segment)
// cerr << Error( "In %s:\n No cached segment at index %d"
// , getString(this).c_str(), index ) << endl;
return segment;
}
void AutoContactHTee::_invalidate ( unsigned int )
{
unsigned int flags = Flags::Propagate;
if (_horizontal1 and _horizontal2) {
if (_horizontal1->isInvalidated() xor _horizontal2->isInvalidated())
flags = Flags::NoFlags;
}
if (_horizontal1) _horizontal1->invalidate( flags );
if (_horizontal2) _horizontal2->invalidate( flags );
if (_vertical1 ) _vertical1 ->invalidate();
}
void AutoContactHTee::cacheDetach ( AutoSegment* segment )
{
cdebug_log(145,0) << _getTypeName() << "::cacheDetach() " << this << endl;
cdebug_log(145,0) << "| h1:" << _horizontal1 << endl;
cdebug_log(145,0) << "| h2:" << _horizontal2 << endl;
cdebug_log(145,0) << "| v1:" << _vertical1 << endl;
if (segment == _horizontal1) _horizontal1 = NULL;
else if (segment == _horizontal2) _horizontal2 = NULL;
else if (segment == _vertical1) _vertical1 = NULL;
else {
if (_horizontal1 or _horizontal2 or _vertical1)
cerr << Bug( "%s::cacheDetach() On %s,\n"
" Cannot detach %s\n"
" because it *not* attached to this contact."
, _getTypeName().c_str()
, getString(this).c_str()
, getString(segment).c_str()
) << endl;
return;
}
setFlags( CntInvalidatedCache );
}
void AutoContactHTee::cacheAttach ( AutoSegment* segment )
{
cdebug_log(145,1) << _getTypeName() << "::cacheAttach() " << this << endl;
cdebug_log(145,0) << "Attaching: " << segment << endl;
if (segment->getDirection() == Flags::Horizontal) {
if (not _horizontal1) _horizontal1 = static_cast<AutoHorizontal*>(segment);
else if (not _horizontal2) _horizontal2 = static_cast<AutoHorizontal*>(segment);
else {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" h1 & h2 cache have not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
cdebug_tabw(145,-1);
return;
}
} else if (segment->getDirection() == Flags::Vertical) {
if (_vertical1) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" v1 cache has not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
cdebug_tabw(145,-1);
return;
}
_vertical1 = static_cast<AutoVertical*>(segment);
}
if (_horizontal1 and _horizontal2 and _vertical1)
unsetFlags( CntInvalidatedCache );
cdebug_log(145,0) << "| h1:" << _horizontal1 << endl;
cdebug_log(145,0) << "| h2:" << _horizontal2 << endl;
cdebug_log(145,0) << "| v1:" << _vertical1 << endl;
cdebug_tabw(145,-1);
}
void AutoContactHTee::updateCache ()
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
Component* anchor;
Horizontal** horizontals = new Horizontal* [3];
Vertical** verticals = new Vertical* [3];
_getTopology( base(), anchor, horizontals, verticals, 3 );
_horizontal1 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[0]) );
_horizontal2 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[1]) );
_vertical1 = static_cast<AutoVertical *>( Session::lookup(verticals [0]) );
string message;
if (horizontals[0] == NULL) message = "HTee has less than two horizontal segments.";
else if (horizontals[1] == NULL) message = "HTee has less than two horizontal segments.";
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";
message += " h1:" + getString(_horizontal1->getY());
message += " h2:" + getString(_horizontal2->getY());
}
if (not message.empty()) {
showTopologyError( message );
setFlags( CntBadTopology );
}
unsetFlags( CntInvalidatedCache );
cdebug_log(145,0) << "h1:" << _horizontal1 << endl;
cdebug_log(145,0) << "h2:" << _horizontal2 << endl;
cdebug_log(145,0) << "v1:" << _vertical1 << endl;
delete [] horizontals;
delete [] verticals;
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactHTee::updateGeometry ()
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
base()->invalidate( false );
unsetFlags( CntInvalidated );
if (not hasBadTopology()) {
setX( getVertical1 ()->getX() );
setY( getHorizontal1()->getY() );
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactHTee::updateTopology ()
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (not hasBadTopology()) {
RoutingGauge* rg = Session::getRoutingGauge();
size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() );
size_t depthH2 = rg->getLayerDepth( getHorizontal2()->getLayer() );
size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() );
size_t minDepth = std::min( depthV1, std::min(depthH1,depthH2) );
size_t maxDepth = std::max( depthV1, std::max(depthH1,depthH2) );
size_t delta = maxDepth - minDepth;
cdebug_log(145,0) << "delta:" << delta << endl;
unsetFlags( CntWeakTerminal );
if (maxDepth - minDepth > 3) {
showTopologyError( "Sheared HTee, layer delta exceed 3." );
setFlags( CntBadTopology );
} else {
if (depthH1 == depthH2) {
// Dogleg on the vertical.
switch ( delta ) {
case 0: setLayer( rg->getRoutingLayer(minDepth) ); break;
case 1: setLayer( rg->getContactLayer(minDepth) ); break;
default:
setLayer( rg->getContactLayer( depthH1 + ((depthH1==minDepth)?0:-1) ) );
_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
break;
}
} else {
// Dogleg on the horizontal with the greater gap (should be equal to +/-2).
int deltaH1 = (int)depthH1 - (int)depthV1;
int deltaH2 = (int)depthH2 - (int)depthV1;
if (std::abs(deltaH1) > std::abs(deltaH2)) {
setLayer( rg->getContactLayer( depthH2 + ((depthH2<depthV1)?0:-1) ) );
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
_horizontal1->makeDogleg(this);
cdebug_log(145,0) << "New h1:" << _horizontal1 << endl;
} else {
setLayer( rg->getContactLayer( depthH1 + ((depthH1<depthV1)?0:-1) ) );
//_horizontal2 = static_cast<AutoHorizontal*>( _horizontal2->makeDogleg(this) );
_horizontal2->makeDogleg(this);
cdebug_log(145,0) << "New h2:" << _horizontal2 << endl;
}
}
}
_horizontal1->invalidate( this );
_horizontal2->invalidate( this );
_vertical1 ->invalidate( this );
}
cdebug_tabw(145,-1);
DebugSession::close();
}
string AutoContactHTee::_getTypeName () const
{ return "ContactHTee"; }
} // Anabatic namespace.

View File

@ -0,0 +1,406 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoContactTerminal.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <climits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Layer.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/Plug.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/Session.h"
namespace Anabatic {
using std::ostringstream;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::DebugSession;
using Hurricane::Transformation;
using Hurricane::Entity;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactTerminal".
AutoContactTerminal* AutoContactTerminal::create ( GCell* gcell
, Component* anchor
, const Layer* layer
, Point point
, DbU::Unit width
, DbU::Unit height
)
{
cdebug_log(145,1) << "AutoContactTerminal::create(... Point, ...)" << endl;
cdebug_log(145,0) << "@" << point << endl;
anchor->getBodyHook()->detach();
AutoContactTerminal* autoContact = AutoContactTerminal::create( gcell
, anchor
, layer
, point.getX(), point.getY()
, width, height
);
cdebug_tabw(145,-1);
return autoContact;
}
AutoContactTerminal* AutoContactTerminal::create ( GCell* gcell
, Component* anchor
, const Layer* layer
, const DbU::Unit x
, const DbU::Unit y
, const DbU::Unit width
, const DbU::Unit height
)
{
cdebug_log(145,0) << "AutoContactTerminal::create(... x, y, ...)" << endl;
cdebug_log(145,0) << "@ x:" << DbU::getValueString(x) << " y:" << DbU::getValueString(y) << endl;
Point anchorPosition = anchor->getPosition();
Contact* contact = Contact::create( anchor
, layer
, x - anchorPosition.getX()
, y - anchorPosition.getY()
, width
, height
);
AutoContactTerminal* autoContact = new AutoContactTerminal( gcell, contact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
cdebug_log(145,0) << "create(Component*) " << autoContact << endl;
return autoContact;
}
AutoContactTerminal::AutoContactTerminal ( GCell* gcell, Contact* contact )
: AutoContact(gcell,contact)
, _segment (NULL)
{
setFlags( CntTerminal );
}
AutoContactTerminal::~AutoContactTerminal ()
{ }
AutoSegment* AutoContactTerminal::getOpposite ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactTerminal::getPerpandicular ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactTerminal::getSegment ( unsigned int index ) const
{
if (_segment) {
switch ( index ) {
case 0: return (_segment->isHorizontal()) ? _segment : NULL;
case 2: return (_segment->isVertical ()) ? _segment : NULL;
}
}
return NULL;
}
Box AutoContactTerminal::getNativeConstraintBox () const
{
cdebug_log(145,1) << "AutoContactTerminal::getNativeConstraintBox()" << endl;
Component* component = getAnchor();
if (component == NULL) {
cerr << Error( "%s is not anchored.", getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return _gcell->getBoundingBox ();
}
DbU::Unit xMin;
DbU::Unit xMax;
DbU::Unit yMin;
DbU::Unit yMax;
Vertical* vertical;
Horizontal* horizontal;
RoutingPad* routingPad;
if ( (horizontal = dynamic_cast<Horizontal*>(component)) ) {
cdebug_log(145,0) << "Anchor: " << horizontal << "@" << horizontal->getSourcePosition() << endl;
xMin = horizontal->getSourcePosition().getX();
xMax = horizontal->getTargetPosition().getX();
yMin = yMax
= horizontal->getTargetPosition().getY();
} else if ( (vertical = dynamic_cast<Vertical*>(component)) ) {
cdebug_log(145,0) << "Anchor: " << vertical << "@" << vertical->getSourcePosition() << endl;
yMin = vertical->getSourcePosition().getY();
yMax = vertical->getTargetPosition().getY();
xMin = xMax
= vertical->getTargetPosition().getX();
} else if ( (routingPad = dynamic_cast<RoutingPad*>(component)) ) {
Entity* entity = routingPad->getOccurrence().getEntity();
Transformation transf = routingPad->getOccurrence().getPath().getTransformation();
cdebug_log(145,0) << "Anchor: " << routingPad << endl;
int rpOrient = 1;
switch ( transf.getOrientation() ) {
case Transformation::Orientation::R1:
case Transformation::Orientation::R3:
case Transformation::Orientation::XR:
case Transformation::Orientation::YR:
rpOrient = 2;
break;
default:
break;
}
if (dynamic_cast<Horizontal*>(entity)) {
// rpOrient *is* the rotation.
} else if ( dynamic_cast<Vertical*>(entity) ) {
// rpOrient is the inverse rotation.
rpOrient = (rpOrient == 1) ? 2 : 1;
} else {
rpOrient = 0;
}
switch ( rpOrient ) {
case 1:
xMin = routingPad->getSourcePosition().getX();
xMax = routingPad->getTargetPosition().getX();
yMin = yMax
= routingPad->getTargetPosition().getY();
break;
case 2:
yMin = routingPad->getSourcePosition().getY();
yMax = routingPad->getTargetPosition().getY();
xMin = xMax
= routingPad->getTargetPosition().getX();
break;
default:
xMin = xMax = routingPad->getPosition().getX();
yMin = yMax = routingPad->getPosition().getY();
break;
}
} else {
xMin = xMax = component->getPosition().getX();
yMin = yMax = component->getPosition().getY();
}
order( xMin, xMax );
order( yMin, yMax );
cdebug_log(145,0) << "| Using (y): " << DbU::getValueString(yMin) << " "
<< DbU::getValueString(yMax) << endl;
cdebug_tabw(145,-1);
return Box( xMin, yMin, xMax, yMax );
}
void AutoContactTerminal::_invalidate ( unsigned int flags )
{
if (_segment) _segment->invalidate();
}
void AutoContactTerminal::cacheDetach ( AutoSegment* segment )
{
if (_segment == segment) {
_segment = NULL;
setFlags( CntInvalidatedCache );
}
}
void AutoContactTerminal::cacheAttach ( AutoSegment* segment )
{
if (_segment) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" cache has not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
return;
}
_segment = segment;
unsetFlags( CntInvalidatedCache );
}
void AutoContactTerminal::updateCache ()
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
Component* anchor;
Horizontal** horizontals = new Horizontal* [2];
Vertical** verticals = new Vertical* [2];
_getTopology( base(), anchor, horizontals, verticals, 2 );
if (anchor == NULL)
showTopologyError( "Terminal is missing an anchor (RoutingPad or Component)." );
size_t count = 0;
if (horizontals[0] != NULL) ++count;
if (horizontals[1] != NULL) ++count;
if (verticals [0] != NULL) ++count;
if (verticals [1] != NULL) ++count;
if (count > 1) {
showTopologyError( "Terminal has more than one segment." );
}
if (horizontals[0] != NULL ) {
_segment = Session::lookup( horizontals[0] );
} else {
_segment = Session::lookup( verticals[0] );
}
if (_segment == NULL) {
ostringstream os;
os << this << ", AutoSegment lookup failed for:"
<< "\n h1: " << horizontals[0]
<< "\n v1: " << verticals[0];
delete [] horizontals;
delete [] verticals;
showTopologyError( os.str() );
throw Error( os.str() );
}
unsetFlags( CntInvalidatedCache );
cdebug_log(145,0) << "seg:" << _segment << endl;
delete [] horizontals;
delete [] verticals;
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactTerminal::updateGeometry ()
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
base()->invalidate( false );
unsetFlags( CntInvalidated );
ostringstream message;
if (not hasBadTopology()) {
if (_segment->isHorizontal()) {
if (not getUConstraints(Flags::Vertical).contains(_segment->getY())) {
cdebug_log(145,0) << "Cached: " << _segment << endl;
message << "Terminal horizontal segment Y " << DbU::getValueString(_segment->getY())
<< " axis is outside RoutingPad " << getUConstraints(Flags::Vertical) << ".";
unsigned int flags = 0;
if (_segment->isCreated()) flags |= Flags::CParanoid;
showTopologyError( message.str(), flags );
} else
setY( _segment->getY() );
} else {
if (not getUConstraints(Flags::Horizontal).contains(_segment->getX())) {
cdebug_log(145,0) << "Cached: " << _segment << endl;
message << "Terminal vertical segment X" << DbU::getValueString(_segment->getX())
<< " axis is outside RoutingPad " << getUConstraints(Flags::Horizontal) << ".";
unsigned int flags = 0;
if (_segment->isCreated()) flags |= Flags::CParanoid;
showTopologyError( message.str(), flags );
} else
setX( _segment->getX() );
}
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactTerminal::updateTopology ()
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
RoutingGauge* rg = Session::getRoutingGauge();
size_t anchorDepth = rg->getLayerDepth( (_flags & CntIgnoreAnchor) ? getLayer()
: getAnchor()->getLayer() );
size_t segmentDepth = rg->getLayerDepth( _segment->getLayer() );
size_t delta = abssub( anchorDepth, segmentDepth );
if (delta > 3) {
showTopologyError( "Sheared Terminal, layer delta exceed 3." );
setFlags( CntBadTopology );
} else {
if (delta > 1) {
//_segment = _segment->makeDogleg( this );
_segment->makeDogleg( this );
cdebug_log(145,0) << "Update seg: " << _segment << endl;
delta = abssub( anchorDepth, rg->getLayerDepth( _segment->getLayer() ) );
}
else if (delta == 0) setLayer( rg->getRoutingLayer(anchorDepth) );
else if (delta == 1) setLayer( rg->getContactLayer(std::min(anchorDepth,segmentDepth)) );
}
_segment->invalidate( this );
cdebug_tabw(145,-1);
DebugSession::close();
}
string AutoContactTerminal::_getTypeName () const
{ return "ContactTerminal"; }
} // Anabatic namespace.

View File

@ -0,0 +1,273 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoContactTurn.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <climits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Layer.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/Plug.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/Session.h"
namespace Anabatic {
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::DebugSession;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactTurn".
AutoContactTurn* AutoContactTurn::create ( GCell* gcell, Net* net, const Layer* layer )
{
_preCreate( gcell, net, layer );
DbU::Unit viaSide = Session::getViaWidth( layer );
Contact* contact = Contact::create ( net
, layer
, gcell->getCenter().getX()
, gcell->getCenter().getY()
, viaSide
, viaSide
);
AutoContactTurn* autoContact = new AutoContactTurn ( gcell, contact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
cdebug_log(145,0) << "create(net*) " << autoContact << endl;
return autoContact;
}
AutoContactTurn::AutoContactTurn ( GCell* gcell, Contact* contact )
: AutoContact (gcell,contact)
, _horizontal1(NULL)
, _vertical1 (NULL)
{
setFlags( CntTurn );
}
AutoContactTurn::~AutoContactTurn ()
{ }
AutoSegment* AutoContactTurn::getOpposite ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactTurn::getPerpandicular ( const AutoSegment* reference ) const
{
if (reference == _horizontal1) return _vertical1;
if (reference == _vertical1 ) return _horizontal1;
return NULL;
}
AutoSegment* AutoContactTurn::getSegment ( unsigned int index ) const
{
switch ( index ) {
case 0: return _horizontal1;
case 2: return _vertical1;
}
return NULL;
}
void AutoContactTurn::_invalidate ( unsigned int flags )
{
if (_horizontal1) _horizontal1->invalidate();
if (_vertical1 ) _vertical1 ->invalidate();
}
void AutoContactTurn::cacheDetach ( AutoSegment* segment )
{
if (segment == _horizontal1) _horizontal1 = NULL;
else if (segment == _vertical1) _vertical1 = NULL;
else return;
setFlags( CntInvalidatedCache );
}
void AutoContactTurn::cacheAttach ( AutoSegment* segment )
{
if (segment->getDirection() == Flags::Horizontal) {
if (_horizontal1) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" h1 cache has not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
return;
}
_horizontal1 = static_cast<AutoHorizontal*>(segment);
} else if (segment->getDirection() == Flags::Vertical) {
if (_vertical1) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" v1 cache has not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
return;
}
_vertical1 = static_cast<AutoVertical*>(segment);
}
if (_horizontal1 and _vertical1) unsetFlags( CntInvalidatedCache );
}
void AutoContactTurn::updateCache ()
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
Component* anchor;
Horizontal** horizontals = new Horizontal* [2];
Vertical** verticals = new Vertical* [2];
_getTopology ( base(), anchor, horizontals, verticals, 2 );
_horizontal1 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[0]) );
_vertical1 = static_cast<AutoVertical *>( Session::lookup(verticals [0]) );
string message;
if (horizontals[0] == NULL) message = "Turn is missing mandatory horizontal segment.";
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 );
} else
unsetFlags( CntInvalidatedCache );
cdebug_log(145,0) << "h1:" << _horizontal1 << endl;
cdebug_log(145,0) << "v1:" << _vertical1 << endl;
delete [] horizontals;
delete [] verticals;
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactTurn::updateGeometry ()
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
base()->invalidate( false );
unsetFlags ( CntInvalidated );
if (not hasBadTopology()) {
setX( getVertical1 ()->getX() );
setY( getHorizontal1()->getY() );
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactTurn::updateTopology ()
{
DebugSession::open ( getNet(), 140, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (not hasBadTopology()) {
RoutingGauge* rg = Session::getRoutingGauge();
size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() );
size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() );
size_t depthContact = (depthH1 < depthV1) ? depthH1 : depthH1-1;
size_t delta = abssub ( depthH1, depthV1 );
unsetFlags( CntWeakTerminal );
if (delta > 3) {
showTopologyError( "Sheared Turn, layer delta exceed 3." );
setFlags( CntBadTopology );
} else {
if (delta == 3) {
if (_horizontal1->isInvalidatedLayer()) {
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
_horizontal1->makeDogleg(this);
depthH1 = rg->getLayerDepth( _horizontal1->getLayer() );
cdebug_log(145,0) << "Update h1: " << _horizontal1 << endl;
} else /*if (_vertical1->isInvalidatedLayer())*/ {
//_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
_vertical1->makeDogleg(this);
depthV1 = rg->getLayerDepth( _vertical1->getLayer() );
cdebug_log(145,0) << "Update v1: " << _vertical1 << endl;
}
delta = abssub ( depthH1, depthV1 );
}
setLayer ( (delta == 0) ? rg->getRoutingLayer(depthContact) : rg->getContactLayer(depthContact) );
}
_horizontal1->invalidate( this );
_vertical1 ->invalidate( this );
}
cdebug_tabw(145,-1);
DebugSession::close ();
}
string AutoContactTurn::_getTypeName () const
{ return "ContactTurn"; }
} // Anabatic namespace.

View File

@ -0,0 +1,309 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoContactVTee.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <climits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Layer.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/Plug.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/Session.h"
namespace Anabatic {
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::DebugSession;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactVTee".
AutoContactVTee* AutoContactVTee::create ( GCell* gcell, Net* net, const Layer* layer )
{
DbU::Unit viaSide = Session::getViaWidth( layer );
Contact* contact = Contact::create( net
, layer
, gcell->getCenter().getX()
, gcell->getCenter().getY()
, viaSide
, viaSide
);
AutoContactVTee* autoContact = new AutoContactVTee( gcell, contact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
cdebug_log(145,0) << "create(net*) " << autoContact << endl;
return autoContact;
}
AutoContactVTee::AutoContactVTee ( GCell* gcell, Contact* contact )
: AutoContact(gcell,contact)
, _horizontal1(NULL)
, _vertical1 (NULL)
, _vertical2 (NULL)
{
setFlags( CntVTee );
}
AutoContactVTee::~AutoContactVTee ()
{ }
AutoSegment* AutoContactVTee::getOpposite ( const AutoSegment* from ) const
{
if (from == _vertical1) return _vertical2;
if (from == _vertical2) return _vertical1;
return NULL;
}
AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const
{
switch ( index ) {
case 0: return _horizontal1;
case 2: return _vertical1;
case 3: return _vertical2;
}
return NULL;
}
void AutoContactVTee::_invalidate ( unsigned int )
{
unsigned int flags = Flags::Propagate;
if (_vertical1 and _vertical2) {
if (_vertical1->isInvalidated() xor _vertical2->isInvalidated())
flags = Flags::NoFlags;
}
if (_vertical1 ) _vertical1 ->invalidate( flags );
if (_vertical2 ) _vertical2 ->invalidate( flags );
if (_horizontal1) _horizontal1->invalidate();
}
void AutoContactVTee::cacheDetach ( AutoSegment* segment )
{
if (segment == _horizontal1) _horizontal1 = NULL;
else if (segment == _vertical1) _vertical1 = NULL;
else if (segment == _vertical2) _vertical2 = NULL;
else return;
setFlags( CntInvalidatedCache );
}
void AutoContactVTee::cacheAttach ( AutoSegment* segment )
{
if (segment->getDirection() == Flags::Vertical) {
if (not _vertical1) _vertical1 = static_cast<AutoVertical*>(segment);
else if (not _vertical2) _vertical2 = static_cast<AutoVertical*>(segment);
else {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" v1 & v2 cache have not been cleared first, cancelling."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
return;
}
} else if (segment->getDirection() == Flags::Horizontal) {
if (_horizontal1) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" h1 cache has not been cleared first, cancelling."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
return;
}
_horizontal1 = static_cast<AutoHorizontal*>(segment);
}
if (_vertical1 and _vertical2 and _horizontal1)
unsetFlags( CntInvalidatedCache );
}
void AutoContactVTee::updateCache ()
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateCache() " << this << endl;
Component* anchor;
Horizontal** horizontals = new Horizontal* [3];
Vertical** verticals = new Vertical* [3];
_getTopology ( base(), anchor, horizontals, verticals, 3 );
_horizontal1 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[0]) );
_vertical1 = static_cast<AutoVertical *>( Session::lookup(verticals [0]) );
_vertical2 = static_cast<AutoVertical *>( Session::lookup(verticals [1]) );
string message;
if (verticals [0] == NULL) message = "VTee has less than two vertical segments.";
else if (verticals [1] == NULL) message = "VTee has less than two vertical segments.";
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";
if (not message.empty() ) {
showTopologyError( message );
setFlags( CntBadTopology );
}
unsetFlags( CntInvalidatedCache );
cdebug_log(145,0) << "h1:" << _horizontal1 << endl;
cdebug_log(145,0) << "v1:" << _vertical1 << endl;
cdebug_log(145,0) << "v2:" << _vertical2 << endl;
delete [] horizontals;
delete [] verticals;
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactVTee::updateGeometry ()
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateGeometry() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
base()->invalidate( false );
unsetFlags( CntInvalidated );
if (not hasBadTopology()) {
setX( getVertical1 ()->getX() );
setY( getHorizontal1()->getY() );
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactVTee::updateTopology ()
{
DebugSession::open ( getNet(), 140, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateTopology() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (not hasBadTopology()) {
RoutingGauge* rg = Session::getRoutingGauge();
size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() );
size_t depthV2 = rg->getLayerDepth( getVertical2 ()->getLayer() );
size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() );
size_t minDepth = std::min( depthH1, std::min(depthV1,depthV2) );
size_t maxDepth = std::max( depthH1, std::max(depthV1,depthV2) );
size_t delta = maxDepth - minDepth;
cdebug_log(145,0) << "minDepth:" << minDepth << endl;
cdebug_log(145,0) << "maxDepth:" << maxDepth << endl;
cdebug_log(145,0) << "delta:" << delta << endl;
unsetFlags( CntWeakTerminal );
if ( maxDepth - minDepth > 3 ) {
showTopologyError( "Sheared VTee, layer delta exceed 3." );
setFlags( CntBadTopology );
} else {
if (depthV1 == depthV2) {
cdebug_log(145,0) << "depthV1 == depthV2 (" << depthV1 << ")" << endl;
// Dogleg on the horizontal.
switch ( delta ) {
case 0: setLayer( rg->getRoutingLayer(minDepth) ); break;
case 1: setLayer( rg->getContactLayer(minDepth) ); break;
default:
cdebug_log(145,0) << "Restore connectivity: dogleg on h1." << endl;
setLayer( rg->getContactLayer( depthV1 + ((depthV1==minDepth)?0:-1) ) );
_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
break;
}
} else {
// Dogleg on the vertical with the greater gap (should be equal to +/-2).
int deltaV1 = (int)depthV1 - (int)depthH1;
int deltaV2 = (int)depthV2 - (int)depthH1;
if (std::abs(deltaV1) > std::abs(deltaV2)) {
setLayer( rg->getContactLayer( depthV2 + ((depthV2<depthH1)?0:-1) ) );
//_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
_vertical1->makeDogleg(this);
} else {
setLayer( rg->getContactLayer( depthV1 + ((depthV1<depthH1)?0:-1) ) );
//_vertical2 = static_cast<AutoVertical*>( _vertical2->makeDogleg(this) );
_vertical2->makeDogleg(this);
}
}
}
_horizontal1->invalidate( this );
_vertical1 ->invalidate( this );
_vertical2 ->invalidate( this );
}
cdebug_tabw(145,-1);
DebugSession::close ();
}
string AutoContactVTee::_getTypeName () const
{ return "ContactVTee"; }
} // Anabatic namespace.

View File

@ -0,0 +1,819 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoHorizontal.cpp" |
// +-----------------------------------------------------------------+
#include <algorithm>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/DebugSession.h"
#include "hurricane/RoutingPad.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/Configuration.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/AutoVertical.h"
namespace Anabatic {
using std::min;
using std::max;
using Hurricane::Error;
using Hurricane::Bug;
using Hurricane::DebugSession;
using Hurricane::RoutingPad;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoHorizontal".
Segment* AutoHorizontal::base () { return _horizontal; }
Segment* AutoHorizontal::base () const { return _horizontal; }
Horizontal* AutoHorizontal::getHorizontal () { return _horizontal; }
DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSourceX(); }
DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTargetX(); }
DbU::Unit AutoHorizontal::getDuSource () const { return _horizontal->getDxSource(); }
DbU::Unit AutoHorizontal::getDuTarget () const { return _horizontal->getDxTarget(); }
Interval AutoHorizontal::getSpanU () const { return Interval(_horizontal->getSourceX(),_horizontal->getTargetX()); }
void AutoHorizontal::setDuSource ( DbU::Unit du ) { _horizontal->setDxSource(du); }
void AutoHorizontal::setDuTarget ( DbU::Unit du ) { _horizontal->setDxTarget(du); }
string AutoHorizontal::_getTypeName () const { return "AutoHorizontal"; }
AutoHorizontal::AutoHorizontal ( Horizontal* horizontal )
: AutoSegment(horizontal)
, _horizontal(horizontal)
{
cdebug_log(145,0) << "CTOR AutoHorizontal " << this << endl;
cdebug_log(145,0) << " over " << horizontal << endl;
}
void AutoHorizontal::_postCreate ()
{
AutoSegment::_postCreate ();
AutoContact* source = getAutoSource();
if (source->isTerminal()) source->setY( _horizontal->getY() );
AutoContact* target = getAutoTarget();
if (target->isTerminal()) target->setY( _horizontal->getY() );
_gcell = source->getGCell();
setOptimalMax( getGCell()->getYMax() );
resetNativeConstraints( getGCell()->getYMin(), getGCell()->getYMax() );
if (getGCell() != target->getGCell()) {
setFlags( SegGlobal );
vector<GCell*> gcells;
getGCells( gcells );
for ( GCell* gcell : gcells ) {
if ( (gcell != getGCell()) and (gcell != target->getGCell()) )
gcell->addHSegment( this );
mergeNativeMin( gcell->getYMin() );
mergeNativeMax( gcell->getYMax() );
}
}
}
void AutoHorizontal::_preDestroy ()
{
cdebug_log(149,0) << "AutoHorizontal::_preDestroy() - <id:" << getId() << "> " << endl;
cdebug_log(149,0) << " " << _getString() << endl;
cdebug_tabw(145,1);
if (not Session::doDestroyTool()) {
vector<GCell*> gcells;
getGCells( gcells );
for ( GCell* gcell : gcells ) gcell->removeHSegment( this );
}
AutoSegment::_preDestroy ();
cdebug_tabw(145,-1);
}
AutoHorizontal::~AutoHorizontal ()
{
if ( Session::doDestroyBaseSegment() and not Session::doDestroyTool() ) {
cdebug_log(149,0) << "~AutoHorizontal() - " << endl;
_horizontal->destroy ();
}
}
Interval AutoHorizontal::getSourceConstraints ( unsigned int flags ) const
{
if (flags & Flags::NativeConstraints) {
Box nativeBox ( getAutoSource()->getNativeConstraintBox() );
return Interval ( nativeBox.getYMin(), nativeBox.getYMax() );
}
return Interval ( getAutoSource()->getCBYMin(), getAutoSource()->getCBYMax() );
}
Interval AutoHorizontal::getTargetConstraints ( unsigned int flags ) const
{
if (flags & Flags::NativeConstraints) {
Box nativeBox ( getAutoTarget()->getNativeConstraintBox() );
return Interval ( nativeBox.getYMin(), nativeBox.getYMax() );
}
return Interval ( getAutoTarget()->getCBYMin(), getAutoTarget()->getCBYMax() );
}
bool AutoHorizontal::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const
{
constraintMin = getNativeMin();
constraintMax = getNativeMax();
cdebug_log(149,0) << "Native constraints: ["
<< DbU::getValueString(constraintMin) << ":"
<< DbU::getValueString(constraintMax) << "]"
<< endl;
constraintMin = max ( constraintMin, getUserConstraints().getVMin() );
constraintMax = min ( constraintMax, getUserConstraints().getVMax() );
cdebug_log(149,0) << "Merge with user constraints: " << getUserConstraints() << " ["
<< DbU::getValueString(getUserConstraints().getVMin()) << ":"
<< DbU::getValueString(getUserConstraints().getVMax()) << "]"
<< endl;
cdebug_log(149,0) << "Resulting constraints: " << " ["
<< DbU::getValueString(constraintMin) << ":"
<< DbU::getValueString(constraintMax) << "]"
<< endl;
return true;
}
unsigned int AutoHorizontal::getDirection () const
{ return Flags::Horizontal; }
size_t AutoHorizontal::getGCells ( vector<GCell*>& gcells ) const
{
vector<GCell*>().swap( gcells );
DbU::Unit yprobe = getNativeMin();
GCell* gcell = getAutoSource()->getGCell();
GCell* end = getAutoTarget()->getGCell();
if (gcell->getXMin() > end->getXMin()) std::swap( gcell, end );
gcells.push_back( gcell );
while ( gcell != end ) {
gcell = gcell->getEast( yprobe );
if (not gcell) {
cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
break;
}
gcells.push_back( gcell );
}
return gcells.size();
}
bool AutoHorizontal::_canSlacken () const
{
cdebug_tabw(149,1);
Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Vertical );
Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Vertical );
Interval sourceConstraints = Interval(getAutoSource()->getCBYMin(),getAutoSource()->getCBYMax());
Interval targetConstraints = Interval(getAutoTarget()->getCBYMin(),getAutoTarget()->getCBYMax());
// Expand by a tiny amount for the "contains" to work for sure.
sourceConstraints.inflate( 1 );
targetConstraints.inflate( 1 );
cdebug_log(149,0) << "source " << getAutoSource() << endl;
cdebug_log(149,0) << "source constraints: " << sourceConstraints
<< " " << DbU::getValueString(sourceConstraints.getSize()) << endl;
cdebug_log(149,0) << "target " << getAutoTarget() << endl;
cdebug_log(149,0) << "target constraints: " << targetConstraints
<< " " << DbU::getValueString(targetConstraints.getSize()) << endl;
if (not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; }
if (not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; }
cdebug_tabw(149,-1);
return false;
}
bool AutoHorizontal::_slacken ( unsigned int flags )
{
cdebug_log(149,0) << "AutoHorizontal::_slacken() " << this << endl;
if (not isStrongTerminal()) return false;
const Configuration* configuration = Session::getConfiguration();
const Layer* metal2 = configuration->getRoutingLayer( 1 );
bool success = false;
bool isMetal2Source = false;
bool isMetal2Target = false;
DbU::Unit height = 0;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
if (source->isTerminal()) {
height = (static_cast<RoutingPad*>(source->getAnchor()))->getBoundingBox().getHeight();
isMetal2Source = (source->getLayer() == metal2);
}
if (target->isTerminal()) {
height = std::min( height, (static_cast<RoutingPad*>(target->getAnchor()))->getBoundingBox().getHeight() );
isMetal2Target = (target->getLayer() == metal2);
}
if (height >= 4*getPitch()) {
if (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < 5*getPitch()))
return false;
}
cdebug_tabw(149,1);
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
cdebug_log(149,0) << "test:" << (getLength() < 5*getPitch()) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl;
int lowSlack = (flags & Flags::HalfSlacken) ? 3 : 10;
bool slackened = false;
bool halfSlackened = false;
DbU::Unit targetPosition = getTargetPosition();
AutoSegment* parallel = this;
if (source->isTerminal()) {
Interval perpandConstraints = getAutoTarget()->getUConstraints(Flags::Horizontal);
Interval constraints = source->getUConstraints (Flags::Vertical|Flags::NoGCellShrink);
Interval nativeConstraints = source->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink);
int slack = constraints.getSize() / getPitch();
int nativeSlack = nativeConstraints.getSize() / getPitch();
cdebug_log(149,0) << "Source constraint: " << constraints
<< " slack:" << slack
<< " native slack:" << nativeSlack << endl;
cdebug_log(149,0) << "Perpand constraints on target: " << perpandConstraints << endl;
// Ugly: GCell's track number is hardwired.
if ((nativeSlack < lowSlack) or (nativeSlack - slack < 3)) {
cdebug_log(149,0) << "Slackening from Source: " << source << endl;
_makeDogleg( source->getGCell(), Flags::NoFlags );
slackened = true;
} else if (slack < 10) {
halfSlackened = true;
}
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
if (doglegs.size() >= 2) {
cdebug_log(149,0) << "AutoSegment::_slaken(): Source @" << DbU::getValueString(getSourcePosition()) << endl;
doglegs[doglegs.size()-2]->setAxis( getSourcePosition() );
success = true;
if (isMetal2Source) {
cdebug_log(149,0) << "Fixing on source terminal contact."
<< doglegs[doglegs.size()-2]->getAutoSource() << endl;
//doglegs[doglegs.size()-2]->getAutoSource()->setFlags( CntFixed );
doglegs[doglegs.size()-2]->getAutoSource()->setConstraintBox( source->getConstraintBox() );
doglegs[doglegs.size()-2]->getAutoSource()->setFlags( CntUserNativeConstraints );
}
parallel = doglegs[ doglegs.size()-1 ];
}
}
if (parallel) target = parallel->getAutoTarget();
if (target->isTerminal()) {
Interval constraints = target->getUConstraints (Flags::Vertical|Flags::NoGCellShrink);
Interval nativeConstraints = target->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink);
int slack = constraints.getSize() / getPitch();
int nativeSlack = nativeConstraints.getSize() / getPitch();
// Ugly: GCell's track number is hardwired.
cdebug_log(149,0) << "Target constraint: " << constraints
<< " slack:" << slack
<< " native slack:" << nativeSlack << endl;
if ((nativeSlack < lowSlack) or (nativeSlack - slack < 3)) {
cdebug_log(149,0) << "Slackening from Target: " << target << endl;
parallel->_makeDogleg( target->getGCell(), Flags::NoFlags );
slackened = true;
} else if (slack < 10) {
halfSlackened = true;
}
if (halfSlackened) {
setFlags( SegHalfSlackened );
} else if (slackened) {
setFlags ( SegSlackened );
unsetFlags( SegHalfSlackened );
}
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
if (doglegs.size() >= 2) {
cdebug_log(149,0) << "AutoSegment::_slaken(): Target @" << DbU::getValueString(targetPosition) << endl;
doglegs[doglegs.size()-2]->setAxis( targetPosition );
success = true;
if (isMetal2Target) {
cdebug_log(149,0) << "Fixing on target terminal contact: "
<< doglegs[doglegs.size()-2]->getAutoTarget() << endl;
//doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntFixed );
doglegs[doglegs.size()-2]->getAutoTarget()->setConstraintBox( target->getConstraintBox() );
doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntUserNativeConstraints );
}
}
}
cdebug_tabw(149,-1);
return success;
}
void AutoHorizontal::_setAxis ( DbU::Unit axis )
{
setFlags( SegAxisSet );
if ((axis != getAxis()) and isFixed()) {
cerr << Error( "AutoHorizontal::setAxis(): Cannot move fixed segment to %s.\n"
" (on: %s)"
, DbU::getValueString(axis).c_str()
, _getString().c_str()
) << endl;
}
if (_horizontal->getY() == axis) return;
cdebug_log(145,0) << "_setAxis() @Y " << DbU::toLambda(axis) << " " << this << endl;
_horizontal->setY( axis );
invalidate();
AutoContact* anchor = getAutoSource();
anchor->invalidate();
if (anchor->isTerminal()) anchor->setY( axis );
anchor = getAutoTarget();
anchor->invalidate();
if (anchor->isTerminal()) anchor->setY( axis );
}
void AutoHorizontal::updateOrient ()
{
if (_horizontal->getTargetX() < _horizontal->getSourceX()) {
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl;
_horizontal->invert();
unsigned int spinFlags = _flags & SegDepthSpin;
unsetFlags( SegDepthSpin );
if (spinFlags & SegSourceTop ) setFlags( SegTargetTop );
if (spinFlags & SegSourceBottom) setFlags( SegTargetBottom );
if (spinFlags & SegTargetTop ) setFlags( SegSourceTop );
if (spinFlags & SegTargetBottom) setFlags( SegSourceBottom );
}
}
void AutoHorizontal::updatePositions ()
{
_sourcePosition = _horizontal->getSourceX() - Session::getExtensionCap(getLayer());
_targetPosition = _horizontal->getTargetX() + Session::getExtensionCap(getLayer());
}
void AutoHorizontal::updateNativeConstraints ()
{
vector<GCell*> gcells;
getGCells( gcells );
resetNativeConstraints( gcells[0]->getYMin(), gcells[0]->getYMax() );
for ( GCell* gcell : gcells ) {
mergeNativeMin( gcell->getYMin() );
mergeNativeMax( gcell->getYMax() );
}
}
bool AutoHorizontal::checkPositions () const
{
bool coherency = true;
DbU::Unit sourcePosition = _horizontal->getSourceX() - Session::getExtensionCap(getLayer());
DbU::Unit targetPosition = _horizontal->getTargetX() + Session::getExtensionCap(getLayer());
if ( _sourcePosition != sourcePosition ) {
cerr << Error ( "%s\n Source position incoherency: "
"shadow: %s, real: %s."
, _getString().c_str()
, DbU::getValueString(_sourcePosition).c_str()
, DbU::getValueString( sourcePosition).c_str()
) << endl;
coherency = false;
}
if ( _targetPosition != targetPosition ) {
cerr << Error ( "%s\n Target position incoherency: "
"shadow: %s, real: %s."
, _getString().c_str()
, DbU::getValueString(_targetPosition).c_str()
, DbU::getValueString( targetPosition).c_str()
) << endl;
coherency = false;
}
return coherency;
}
bool AutoHorizontal::checkConstraints () const
{
Interval sourceConstraints = Interval(getAutoSource()->getCBYMin(),getAutoSource()->getCBYMax());
Interval targetConstraints = Interval(getAutoTarget()->getCBYMin(),getAutoTarget()->getCBYMax());
if (not sourceConstraints.intersect(targetConstraints)) {
cerr << Error ( "%s\n Constraints incoherency:\n"
" S:%s %s\n"
" T:%s %s"
, _getString().c_str()
, getString(sourceConstraints).c_str()
, getString(getAutoSource()).c_str()
, getString(targetConstraints).c_str()
, getString(getAutoTarget()).c_str()
) << endl;
return false;
}
return true;
}
bool AutoHorizontal::canMoveULeft ( float reserve ) const
{
#if THIS_IS_DISABLED
//cerr << "canMoveULeft() " << this << endl;
if (not isGlobal()) return false;
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return false;
if (not getAutoSource()->getGCell()->getDown()) return false;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
AutoSegment* perpandiculars[2] = { autoSource->getSegment(0), autoTarget->getSegment(0) };
if ( ( (not perpandiculars[0]->isGlobal()) or (perpandiculars[0]->getAutoSource() == autoSource) )
and ( (not perpandiculars[1]->isGlobal()) or (perpandiculars[1]->getAutoSource() == autoTarget) ) )
return false;
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
unsigned int depth = Session::getRoutingGauge()->getLayerDepth( getLayer() );
float currMaxDensity = 0.0;
float leftMaxDensity = 0.0;
//cerr << "| begin:" << begin << endl;
//cerr << "| end: " << end << endl;
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getRight() ) {
//cerr << "| gcell:" << gcell << endl;
if (currMaxDensity < gcell->getWDensity(depth)) currMaxDensity = gcell->getWDensity( depth );
}
begin = begin->getDown();
end = end ->getDown();
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getRight() ) {
if (leftMaxDensity < gcell->getWDensity(depth)) leftMaxDensity = gcell->getWDensity( depth );
}
return (leftMaxDensity + reserve < currMaxDensity);
#endif
return false;
}
bool AutoHorizontal::canMoveURight ( float reserve ) const
{
#if THIS_IS_DISABLED
//cerr << "canMoveURight() " << this << endl;
if (not isGlobal()) return false;
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return false;
if (not getAutoSource()->getGCell()->getUp()) return false;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
AutoSegment* perpandiculars[2] = { autoSource->getSegment(0), autoTarget->getSegment(0) };
if ( ( (not perpandiculars[0]->isGlobal()) or (perpandiculars[0]->getAutoTarget() == autoSource) )
and ( (not perpandiculars[1]->isGlobal()) or (perpandiculars[1]->getAutoTarget() == autoTarget) ) )
return false;
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
unsigned int depth = Session::getRoutingGauge()->getLayerDepth( getLayer() );
float currMaxDensity = 0.0;
float leftMaxDensity = 0.0;
//cerr << "| begin:" << begin << endl;
//cerr << "| end: " << end << endl;
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getRight() ) {
//cerr << "| gcell: " << gcell << endl;
if (currMaxDensity < gcell->getWDensity(depth)) currMaxDensity = gcell->getWDensity( depth );
}
begin = begin->getUp();
end = end ->getUp();
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getRight() ) {
if (leftMaxDensity < gcell->getWDensity(depth)) leftMaxDensity = gcell->getWDensity( depth );
}
return (leftMaxDensity + reserve < currMaxDensity);
#endif
return false;
}
bool AutoHorizontal::moveULeft ()
{
#if THIS_IS_DISABLED
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return false;
if (not getAutoSource()->getGCell()->getDown()) return false;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
AutoSegment* perpandicular = autoSource->getSegment(2);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoSource() == autoSource) {
begin->addVSegment( perpandicular );
} else {
if (begin->getDown() == perpandicular->getAutoSource()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
begin->getDown()->removeVSegment( perpandicular );
}
}
perpandicular = autoTarget->getSegment(2);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoSource() == autoTarget) {
end->addVSegment( perpandicular );
} else {
if (end->getDown() == perpandicular->getAutoSource()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
end->getDown()->removeVSegment( perpandicular );
}
}
if (begin != end) {
for ( GCell* gcell=begin->getRight() ; gcell and gcell!=end ; gcell=gcell->getRight() )
gcell->removeHSegment( this );
}
begin = begin->getDown();
end = end ->getDown();
autoSource->setGCell( begin );
autoTarget->setGCell( end );
if (begin != end) {
for ( GCell* gcell=begin->getRight() ; gcell and gcell!=end ; gcell=gcell->getRight() )
gcell->addHSegment( this );
}
DbU::Unit y = begin->getSide(Flags::Vertical).getVMax();
setAxis( y );
return true;
#endif
return false;
}
bool AutoHorizontal::moveURight ()
{
#if THIS_IS_DISABLED
//cerr << "moveURight() " << this << endl;
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return false;
if (not getAutoSource()->getGCell()->getUp()) return false;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
AutoSegment* perpandicular = autoSource->getSegment(2);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoTarget() == autoSource) {
begin->addVSegment( perpandicular );
} else {
if (begin->getUp() == perpandicular->getAutoTarget()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
begin->getUp()->removeVSegment( perpandicular );
}
}
perpandicular = autoTarget->getSegment(2);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoTarget() == autoTarget) {
end->addVSegment( perpandicular );
} else {
if (end->getUp() == perpandicular->getAutoTarget()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
end->getUp()->removeVSegment( perpandicular );
}
}
//cerr << "| begin:" << begin << endl;
//cerr << "| end: " << end << endl;
//cerr << "* remove" << endl;
if (begin != end) {
for ( GCell* gcell=begin->getRight() ; gcell and gcell!=end ; gcell=gcell->getRight() ) {
//cerr << "| gcell: " << end << endl;
gcell->removeHSegment( this );
}
}
begin = begin->getUp();
end = end ->getUp();
autoSource->setGCell( begin );
autoTarget->setGCell( end );
//cerr << "* add" << endl;
if (begin != end) {
for ( GCell* gcell=begin->getRight() ; gcell and gcell!=end ; gcell=gcell->getRight() ) {
//cerr << "| gcell: " << end << endl;
gcell->addHSegment( this );
}
}
DbU::Unit y = begin->getSide( Flags::Vertical ).getVMin();
setAxis( y );
return true;
#endif
return false;
}
unsigned int AutoHorizontal::_makeDogleg ( GCell* doglegGCell, unsigned int flags )
{
DebugSession::open( getNet(), 140, 150 );
cdebug_log(149,0) << "AutoHorizontal::_makeDogleg(GCell*)" << endl;
cdebug_tabw(149,1);
//Session::doglegReset();
AutoContact* autoTarget = getAutoTarget();
AutoContact* autoSource = getAutoSource();
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
DbU::Unit doglegAxis = (doglegGCell->getXMax() + doglegGCell->getXMin()) / 2;
if (isLocal())
doglegAxis = (getSourceX() + getTargetX()) / 2;
cdebug_log(149,0) << "Detaching from Target AutoContact " << autoTarget << "." << endl;
if (doglegGCell == begin) unsetFlags( SegGlobal );
if (doglegGCell != end) {
GCell* gcell = doglegGCell;
do {
if (gcell != begin)
gcell->removeHSegment( this );
gcell = gcell->getEast( getNativeMin() );
} while ( gcell and (gcell != end) );
}
size_t depth = Session::getRoutingGauge()->getLayerDepth( _horizontal->getLayer() );
bool upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer( depth + ((upLayer)?0:-1) );
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer( depth + ((upLayer)?1:-1) );
Session::dogleg( this );
targetDetach();
invalidate( Flags::Topology );
autoTarget->invalidate( Flags::Topology );
AutoContact* dlContact1 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer );
AutoContact* dlContact2 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer );
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Vertical );
segment1->setLayer( doglegLayer );
segment1->_setAxis( doglegAxis );
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
cdebug_log(149,0) << "New " << dlContact1 << endl;
cdebug_log(149,0) << "New " << dlContact2 << endl;
Session::dogleg( segment1 );
targetAttach( dlContact1 );
AutoSegment* segment2 = AutoSegment::create( dlContact2 , autoTarget, Flags::Horizontal );
autoTarget->cacheAttach( segment2 );
segment2->setLayer( getLayer() );
segment2->_setAxis( getY() );
segment2->setFlags( (isSlackened()?SegSlackened:0) );
Session::dogleg( segment2 );
if (autoSource->isTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );
autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell)
dlContact1->migrateConstraintBox( autoTarget );
} else if (autoTarget->isTerminal()) {
unsetFlags( SegTargetTerminal );
setFlags( SegWeakTerminal1 );
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegTargetTerminal );
autoSource->unsetFlags( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal );
if (autoSource->getGCell() == doglegGCell)
dlContact2->migrateConstraintBox( autoSource );
} else if (isWeakTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );
}
cdebug_log(149,0) << "Session::dogleg[x+1] perpand: " << segment1 << endl;
cdebug_log(149,0) << "Session::dogleg[x+2] new paral: " << segment2 << endl;
cdebug_log(149,0) << "Session::dogleg[x+0] original: " << this << endl;
dlContact1->updateCache();
dlContact2->updateCache();
//autoTarget->updateCache();
segment2->canonize( flags );
if (not isCanonical()) canonize( flags );
updateNativeConstraints();
segment2->updateNativeConstraints();
cdebug_tabw(149,-1);
DebugSession::close();
return (upLayer) ? Flags::AboveLayer : Flags::BelowLayer;
}
string AutoHorizontal::_getString () const
{
string s = AutoSegment::_getString();
return s;
}
Record* AutoHorizontal::_getRecord () const
{
Record* record = AutoSegment::_getRecord ();
record->add ( getSlot ( "_horizontal", _horizontal ) );
return record;
}
} // End of Anabatic namespace.

2387
anabatic/src/AutoSegment.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,512 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoSegments.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/Error.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoSegment.h"
namespace Anabatic {
using namespace std;
using Hurricane::tab;
using Hurricane::_TName;
using Hurricane::Error;
using Hurricane::ForEachIterator;
using Hurricane::Hook;
using Hurricane::Contact;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegmentStack".
void AutoSegmentStack::push ( AutoContact* contact, AutoSegment* segment )
{
cdebug_log(145,0) << "Stacking " << contact << " + " << segment << endl;
push_back( make_pair(contact,segment) );
}
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegments_OnContact".
AutoSegments_OnContact::Locator::Locator ( AutoSegment* master, Contact* contact )
: AutoSegmentHL()
, _master (master)
, _element (NULL)
{
_hook = contact->getBodyHook()->getPreviousMasterHook();
progress();
}
AutoSegmentHL* AutoSegments_OnContact::Locator::getClone () const
{ return new Locator(*this); }
AutoSegment* AutoSegments_OnContact::Locator::getElement () const
{ return _element; }
bool AutoSegments_OnContact::Locator::isValid () const
{ return !_hook; }
void AutoSegments_OnContact::Locator::progress ()
{
cdebug_log(145,0) << "AutoSegments_OnContact::Locator::progress()" << endl;
while (_hook and not _hook->isMaster()) {
_hook = _hook->getNextHook();
_element = NULL;
if ( _hook->isMaster() ) { _hook = NULL; break; }
Segment* segment = dynamic_cast<Segment*>( _hook->getComponent() );
if (segment) _element = Session::lookup( segment );
if (not _element or (_element == _master)) continue;
break;
}
}
string AutoSegments_OnContact::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_OnContact::Locator")
+ getString(_element)
+ ">";
return s;
}
AutoSegmentHC* AutoSegments_OnContact::getClone () const
{ return new AutoSegments_OnContact(*this); }
AutoSegmentHL* AutoSegments_OnContact::getLocator () const
{ return new Locator(_master,_contact); }
string AutoSegments_OnContact::_getString () const
{
string s = "<" + _TName("AutoSegments_OnContact") + " "
+ getString(_master)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "AutoSegments_Aligneds".
AutoSegments_Aligneds::Locator::Locator ( AutoSegment* segment, unsigned int flags )
: AutoSegmentHL()
, _flags (flags)
, _master(segment)
, _stack ()
{
if (not _master) return;
_flags |= (_master->isHorizontal()) ? Flags::Horizontal : Flags::Vertical;
cdebug_log(145,0) << "AutoSegments_Aligneds::Locator::Locator() - _flags:" << _flags << endl;
AutoContact* contact = segment->getAutoSource();
if (contact) _stack.push( contact, segment );
contact = segment->getAutoTarget();
if (contact) _stack.push( contact, segment );
progress();
}
AutoSegmentHL* AutoSegments_Aligneds::Locator::getClone () const
{ return new Locator(*this); }
bool AutoSegments_Aligneds::Locator::isValid () const
{ return not _stack.isEmpty(); }
void AutoSegments_Aligneds::Locator::progress ()
{
cdebug_log(145,0) << "AutoSegments_Aligneds::Locator::progress()" << endl;
while (not _stack.isEmpty()) {
AutoContact* sourceContact = _stack.getAutoContact ();
AutoSegment* sourceSegment = _stack.getAutoSegment ();
_stack.pop ();
LocatorHelper helper (sourceContact, _flags);
for ( ; helper.isValid() ; helper.progress() ) {
AutoSegment* currentSegment = helper.getSegment();
cdebug_log(145,0) << "Looking at: " << currentSegment << endl;
if (currentSegment == sourceSegment) continue;
if ( (not (_flags & Flags::NoCheckLayer))
and AutoSegment::areAlignedsAndDiffLayer(currentSegment,_master)) {
cerr << Error("Aligned segments not in same layer (aligneds locator)\n"
" %s\n"
" %s."
,getString(_master).c_str()
,getString(currentSegment).c_str()) << endl;
continue;
}
AutoContact* targetContact = currentSegment->getOppositeAnchor( sourceContact );
if (targetContact) _stack.push( targetContact, currentSegment );
}
if (_stack.getAutoSegment() == _master) continue;
break;
}
}
string AutoSegments_Aligneds::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_Aligneds::Locator") + ">";
return s;
}
AutoSegmentHC* AutoSegments_Aligneds::getClone () const
{ return new AutoSegments_Aligneds(*this); }
AutoSegmentHL* AutoSegments_Aligneds::getLocator () const
{ return new Locator(_segment,_flags); }
AutoSegment* AutoSegments_Aligneds::Locator::getElement () const
{ return _stack.getAutoSegment(); }
string AutoSegments_Aligneds::_getString () const
{
string s = "<" + _TName("AutoSegments_Aligneds") + " "
+ getString(_segment)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "AutoSegments_Perpandiculars".
AutoSegments_Perpandiculars::Locator::Locator ( AutoSegment* master )
: AutoSegmentHL()
, _flags (Flags::WithPerpands)
, _master (master)
, _stack ()
, _perpandiculars()
{
cdebug_log(145,0) << "AutoSegments_Perpandiculars::Locator::Locator()" << endl;
cdebug_log(145,0) << " " << _master << endl;
if (not _master) return;
if (_master->isHorizontal()) _flags |= Flags::Horizontal;
else _flags |= Flags::Vertical;
AutoContact* contact = _master->getAutoSource();
if ( contact ) _stack.push( contact, _master );
contact = _master->getAutoTarget();
if ( contact ) _stack.push( contact, _master );
progress();
}
AutoSegment* AutoSegments_Perpandiculars::Locator::getElement () const
{
if (_perpandiculars.empty()) return NULL;
return _perpandiculars.back();
}
void AutoSegments_Perpandiculars::Locator::progress ()
{
cdebug_log(145,0) << "AutoSegments_Perpandiculars::Locator::progress()" << endl;
if (not _perpandiculars.empty()) _perpandiculars.pop_back();
if (not _perpandiculars.empty()) return;
while ( not _stack.isEmpty() ) {
AutoContact* sourceContact = _stack.getAutoContact();
AutoSegment* sourceSegment = _stack.getAutoSegment();
_stack.pop();
LocatorHelper helper (sourceContact, _flags);
for ( ; helper.isValid() ; helper.progress() ) {
AutoSegment* currentSegment = helper.getSegment();
if (currentSegment == sourceSegment) continue;
if (AutoSegment::areAligneds(currentSegment,_master)) {
AutoContact* targetContact = currentSegment->getOppositeAnchor( sourceContact );
if (targetContact) {
if ( (_master->isHorizontal() and sourceContact->isHTee())
or (_master->isVertical () and sourceContact->isVTee()) ) {
if (AutoSegment::areAlignedsAndDiffLayer(currentSegment,_master)) {
cerr << Error("Aligned segments not in same layer (perpandicular locator)\n"
" %s\n"
" %s."
,getString(_master).c_str()
,getString(currentSegment).c_str()) << endl;
continue;
}
cdebug_log(145,0) << "Stacking target. " << endl;
_stack.push( targetContact, currentSegment );
}
}
} else {
_perpandiculars.push_back( currentSegment );
}
}
if (_stack.isEmpty()) break;
if (_stack.getAutoSegment() == _master) continue;
if (not _perpandiculars.empty()) break;
}
}
AutoSegmentHL* AutoSegments_Perpandiculars::Locator::getClone () const
{ return new Locator(*this); }
bool AutoSegments_Perpandiculars::Locator::isValid () const
{ return not _perpandiculars.empty(); }
AutoSegmentHC* AutoSegments_Perpandiculars::getClone () const
{ return new AutoSegments_Perpandiculars(*this); }
AutoSegmentHL* AutoSegments_Perpandiculars::getLocator () const
{ return new Locator(_segment); }
string AutoSegments_Perpandiculars::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_Perpandiculars::Locator") + ">";
return s;
}
string AutoSegments_Perpandiculars::_getString () const
{
string s = "<" + _TName("AutoSegments_Perpandiculars") + " "
+ getString(_segment)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "AutoSegments_AnchorOnGCell".
AutoSegments_AnchorOnGCell::Locator::Locator ( GCell* fcell, unsigned int flags )
: AutoSegmentHL()
, _flags (flags)
, _itContact (fcell->getContacts().begin())
, _itEnd (fcell->getContacts().end())
, _hookLocator(NULL)
, _element (NULL)
{ progress(); }
AutoSegments_AnchorOnGCell::Locator::~Locator ()
{ if (_hookLocator) delete _hookLocator; }
AutoSegment* AutoSegments_AnchorOnGCell::Locator::getElement () const
{ return _element; }
AutoSegmentHL* AutoSegments_AnchorOnGCell::Locator::getClone () const
{ return new Locator(*this); }
bool AutoSegments_AnchorOnGCell::Locator::isValid () const
{ return _element != NULL; }
void AutoSegments_AnchorOnGCell::Locator::progress ()
{
cdebug_log(145,1) << "AutoSegments_AnchorOnGCell::Locator::progress()" << endl;
while ( true ) {
if (_hookLocator == NULL) {
if (_itContact == _itEnd) {
cdebug_log(145,0) << "No more AutoContacts" << endl;
cdebug_tabw(145,-1);
return;
}
cdebug_log(145,0) << *_itContact << endl;
_hookLocator = (*_itContact)->getBodyHook()->getSlaveHooks().getLocator();
_itContact++;
} else {
_hookLocator->progress();
}
while ( _hookLocator->isValid() ) {
cdebug_log(145,0) << _hookLocator->getElement() << endl;
Hook* hook = dynamic_cast<Segment::SourceHook*>(_hookLocator->getElement());
if (hook) {
if ( ((_flags & Flags::Source) and (dynamic_cast<Segment::SourceHook*>(hook)))
or ((_flags & Flags::Target) and (dynamic_cast<Segment::TargetHook*>(hook))) ) {
_element = Session::lookup( static_cast<Segment*>(hook->getComponent()) );
if (_element->isHorizontal()) {
if (_flags & Flags::Horizontal) { cdebug_tabw(145,-1); return; }
} else
if (_flags & Flags::Vertical) { cdebug_tabw(145,-1); return; }
}
}
_hookLocator->progress();
}
_hookLocator = NULL;
_element = NULL;
}
cdebug_tabw(145,-1);
}
string AutoSegments_AnchorOnGCell::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_AnchorOnGCell::Locator") + ">";
return s;
}
AutoSegmentHC* AutoSegments_AnchorOnGCell::getClone () const
{ return new AutoSegments_AnchorOnGCell(*this); }
AutoSegmentHL* AutoSegments_AnchorOnGCell::getLocator () const
{ return new Locator(_fcell,_flags); }
string AutoSegments_AnchorOnGCell::_getString () const
{
string s = "<" + _TName("AutoSegments_AnchorOnGCell") + " "
+ getString(_fcell)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegments_CachedOnContact".
AutoSegments_CachedOnContact::Locator::Locator ( AutoContact* sourceContact, unsigned int direction )
: AutoSegmentHL()
, _helper(new LocatorHelper(sourceContact,direction))
{ }
AutoSegments_CachedOnContact::Locator::~Locator ()
{ delete _helper; }
AutoSegment* AutoSegments_CachedOnContact::Locator::getElement () const
{ return _helper->getSegment(); }
AutoSegmentHL* AutoSegments_CachedOnContact::Locator::getClone () const
{ return new Locator(*this); }
bool AutoSegments_CachedOnContact::Locator::isValid () const
{ return _helper->isValid(); }
void AutoSegments_CachedOnContact::Locator::progress ()
{
cdebug_log(145,0) << "AutoSegments_CachedOnContact::Locator::progress()" << endl;
_helper->progress();
}
AutoSegmentHL* AutoSegments_CachedOnContact::getLocator () const
{ return new Locator(_sourceContact,_direction); }
AutoSegmentHC* AutoSegments_CachedOnContact::getClone () const
{ return new AutoSegments_CachedOnContact(*this); }
string AutoSegments_CachedOnContact::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_CachedOnContact::Locator") + ">";
return s;
}
string AutoSegments_CachedOnContact::_getString () const
{
string s = "<" + _TName("AutoSegments_CachedOnContact") + " "
+ getString(_sourceContact)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "AutoSegments_IsAccountable".
AutoSegmentHF* AutoSegments_IsAccountable::getClone () const
{ return new AutoSegments_IsAccountable(); }
bool AutoSegments_IsAccountable::accept ( AutoSegment* segment ) const
{ return segment->isCanonical(); }
string AutoSegments_IsAccountable::_getString () const
{ return "<AutoSegments_IsAccountable>"; }
// -------------------------------------------------------------------
// Class : "AutoSegments_InDirection".
AutoSegmentHF* AutoSegments_InDirection::getClone () const
{ return new AutoSegments_InDirection(_direction); }
bool AutoSegments_InDirection::accept ( AutoSegment* segment ) const
{
return ( segment->isHorizontal() and (_direction & Flags::Horizontal) )
or ( segment->isVertical () and (_direction & Flags::Vertical ) );
}
string AutoSegments_InDirection::_getString () const
{ return "<AutoSegments_InDirection>"; }
} // Anabatic namespace.

View File

@ -0,0 +1,728 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoVertical.cpp" |
// +-----------------------------------------------------------------+
#include <algorithm>
#include "hurricane/Bug.h"
#include "hurricane/Vertical.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/Configuration.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
namespace Anabatic {
using std::min;
using std::max;
using Hurricane::Error;
using Hurricane::Bug;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoVertical".
Segment* AutoVertical::base () { return _vertical; }
Segment* AutoVertical::base () const { return _vertical; }
Vertical* AutoVertical::getVertical () { return _vertical; }
DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSourceY(); }
DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTargetY(); }
DbU::Unit AutoVertical::getDuSource () const { return _vertical->getDySource(); }
DbU::Unit AutoVertical::getDuTarget () const { return _vertical->getDyTarget(); }
Interval AutoVertical::getSpanU () const { return Interval(_vertical->getSourceY(),_vertical->getTargetY()); }
void AutoVertical::setDuSource ( DbU::Unit du ) { _vertical->setDySource(du); }
void AutoVertical::setDuTarget ( DbU::Unit du ) { _vertical->setDyTarget(du); }
string AutoVertical::_getTypeName () const { return "AutoVertical"; }
AutoVertical::AutoVertical ( Vertical* vertical )
: AutoSegment(vertical)
, _vertical(vertical)
{
cdebug_log(145,0) << "CTOR AutoVertical " << this << endl;
cdebug_log(145,0) << " over " << vertical << endl;
}
void AutoVertical::_postCreate ()
{
AutoSegment::_postCreate ();
AutoContact* source = getAutoSource();
if (source->isTerminal()) source->setX( _vertical->getX() );
AutoContact* target = getAutoTarget();
if (target->isTerminal()) target->setX( _vertical->getX() );
_gcell = source->getGCell();
setOptimalMax( getGCell()->getXMax() );
resetNativeConstraints( getGCell()->getXMin(), getGCell()->getXMax() );
if (getGCell() != target->getGCell()) {
setFlags( SegGlobal );
vector<GCell*> gcells;
getGCells( gcells );
for ( GCell* gcell : gcells ) {
if ( (gcell != getGCell()) and (gcell != target->getGCell()) )
gcell->addVSegment( this );
mergeNativeMin( gcell->getXMin() );
mergeNativeMax( gcell->getXMax() );
}
}
}
void AutoVertical::_preDestroy ()
{
cdebug_log(149,1) << "AutoVertical::_preDestroy() - <id:" << getId() << "> " << endl;
cdebug_log(149,0) << _getString() << endl;
if ( not Session::doDestroyTool() ) {
vector<GCell*> gcells;
getGCells( gcells );
for ( GCell* gcell : gcells ) gcell->removeVSegment( this );
}
AutoSegment::_preDestroy ();
cdebug_tabw(145,-1);
}
AutoVertical::~AutoVertical ()
{
if ( Session::doDestroyBaseSegment() and not Session::doDestroyTool() ) {
cdebug_log(149,0) << "~AutoVertical() - " << endl;
_vertical->destroy ();
}
}
Interval AutoVertical::getSourceConstraints ( unsigned int flags ) const
{
if (flags & Flags::NativeConstraints) {
Box nativeBox ( getAutoSource()->getNativeConstraintBox() );
return Interval ( nativeBox.getXMin(), nativeBox.getXMax() );
}
return Interval ( getAutoSource()->getCBXMin(), getAutoSource()->getCBXMax() );
}
Interval AutoVertical::getTargetConstraints ( unsigned int flags ) const
{
if (flags & Flags::NativeConstraints) {
Box nativeBox ( getAutoTarget()->getNativeConstraintBox() );
return Interval ( nativeBox.getXMin(), nativeBox.getXMax() );
}
return Interval ( getAutoTarget()->getCBXMin(), getAutoTarget()->getCBXMax() );
}
bool AutoVertical::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const
{
constraintMin = getNativeMin();
constraintMax = getNativeMax();
cdebug_log(149,0) << "Native constraints: ["
<< DbU::getValueString(constraintMin) << ":"
<< DbU::getValueString(constraintMax) << "]"
<< endl;
constraintMin = max ( constraintMin, getUserConstraints().getVMin() );
constraintMax = min ( constraintMax, getUserConstraints().getVMax() );
cdebug_log(149,0) << "Merge with user constraints: " << getUserConstraints() << " ["
<< DbU::getValueString(getUserConstraints().getVMin()) << ":"
<< DbU::getValueString(getUserConstraints().getVMax()) << "]"
<< endl;
cdebug_log(149,0) << "Resulting constraints: " << " ["
<< DbU::getValueString(constraintMin) << ":"
<< DbU::getValueString(constraintMax) << "]"
<< endl;
return true;
}
unsigned int AutoVertical::getDirection () const
{ return Flags::Vertical; }
size_t AutoVertical::getGCells ( vector<GCell*>& gcells ) const
{
vector<GCell*>().swap( gcells );
DbU::Unit xprobe = getNativeMin();
GCell* gcell = getAutoSource()->getGCell();
GCell* end = getAutoTarget()->getGCell();
if (gcell->getYMin() > end->getYMin()) std::swap( gcell, end );
gcells.push_back( gcell );
while ( gcell != end ) {
gcell = gcell->getNorth( xprobe );
if (not gcell) {
cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
break;
}
gcells.push_back( gcell );
}
return gcells.size();
}
bool AutoVertical::_canSlacken () const
{
cdebug_tabw(149,-1);
Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Horizontal );
Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Horizontal );
Interval sourceConstraints = Interval(getAutoSource()->getCBXMin(),getAutoSource()->getCBXMax());
Interval targetConstraints = Interval(getAutoTarget()->getCBXMin(),getAutoTarget()->getCBXMax());
// Expand by a tiny amount for the "contains" to work for sure.
sourceConstraints.inflate( 1 );
targetConstraints.inflate( 1 );
if (not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; }
if (not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; }
cdebug_tabw(149,-1);
return false;
}
bool AutoVertical::_slacken ( unsigned int flags )
{
cdebug_log(149,1) << "AutoVertical::_slacken() " << this << endl;
if ( not isStrongTerminal()
or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < getPitch()*5)) )
{ cdebug_tabw(149,-1); return false; }
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
cdebug_log(149,0) << "test:" << (getLength() < getPitch()*5) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl;
bool success = false;
bool slackened = false;
bool halfSlackened = false;
int lowSlack = (flags & Flags::HalfSlacken) ? 3 : 10;
AutoContact* source = getAutoSource();
AutoSegment* parallel = this;
if (source->isTerminal()) {
Interval constraints = source->getUConstraints (Flags::Horizontal|Flags::NoGCellShrink);
Interval nativeConstraints = source->getNativeUConstraints(Flags::Horizontal|Flags::NoGCellShrink);
int slack = constraints.getSize() / getPitch();
int nativeSlack = nativeConstraints.getSize() / getPitch();
// Ugly: GCell's track number is hardwired.
if ((slack < lowSlack) or (nativeSlack - slack < 3)) {
_makeDogleg( source->getGCell(), Flags::NoFlags );
slackened = true;
} else if (slack < 10) {
halfSlackened = true;
}
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
if (doglegs.size() >= 2) {
cdebug_log(149,0) << "AutoSegment::_slaken(): Source @" << DbU::getValueString(getSourcePosition()) << endl;
doglegs[doglegs.size()-2]->_setAxis( getSourcePosition() );
success = true;
parallel = doglegs[ doglegs.size()-1 ];
}
}
AutoContact* target = NULL;
if (parallel) {
target = parallel->getAutoTarget();
} else {
target = getAutoTarget();
}
if (target->isTerminal()) {
Interval constraints = target->getUConstraints (Flags::Horizontal|Flags::NoGCellShrink);
Interval nativeConstraints = target->getNativeUConstraints(Flags::Horizontal|Flags::NoGCellShrink);
int slack = constraints.getSize() / getPitch();
int nativeSlack = nativeConstraints.getSize() / getPitch();
// Ugly: GCell's track number is hardwired.
if ((slack < lowSlack) or (nativeSlack - slack < 3)) {
_makeDogleg( target->getGCell(), Flags::NoFlags );
slackened = true;
} else if (slack < 10) {
halfSlackened = true;
}
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
if (doglegs.size() >= 2) {
cdebug_log(149,0) << "AutoSegment::_slaken(): Source @" << DbU::getValueString(getTargetPosition()) << endl;
doglegs[doglegs.size()-2]->_setAxis( getTargetPosition() );
success = true;
}
}
if (halfSlackened) {
setFlags( SegHalfSlackened );
} else if (slackened) {
setFlags ( SegSlackened );
unsetFlags( SegHalfSlackened );
}
cdebug_tabw(149,-1);
return success;
}
void AutoVertical::_setAxis ( DbU::Unit axis )
{
setFlags( SegAxisSet );
if (_vertical->getX() == axis) return;
cdebug_log(149,0) << "_setAxis() @X " << DbU::toLambda(axis) << " " << this << endl;
_vertical->setX( axis );
invalidate();
AutoContact* anchor = getAutoSource();
anchor->invalidate();
if (anchor->isTerminal()) anchor->setX( axis );
anchor = getAutoTarget();
anchor->invalidate();
if (anchor->isTerminal()) anchor->setX( axis );
}
void AutoVertical::updateOrient ()
{
if (_vertical->getTargetY() < _vertical->getSourceY()) {
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl;
_vertical->invert();
unsigned int spinFlags = _flags & SegDepthSpin;
unsetFlags( SegDepthSpin );
if (spinFlags & SegSourceTop ) setFlags( SegTargetTop );
if (spinFlags & SegSourceBottom) setFlags( SegTargetBottom );
if (spinFlags & SegTargetTop ) setFlags( SegSourceTop );
if (spinFlags & SegTargetBottom) setFlags( SegSourceBottom );
}
}
void AutoVertical::updatePositions ()
{
_sourcePosition = _vertical->getSourceY() - Session::getExtensionCap(getLayer());
_targetPosition = _vertical->getTargetY() + Session::getExtensionCap(getLayer());
}
void AutoVertical::updateNativeConstraints ()
{
vector<GCell*> gcells;
getGCells( gcells );
resetNativeConstraints( gcells[0]->getXMin(), gcells[0]->getXMax() );
for ( GCell* gcell : gcells ) {
mergeNativeMin( gcell->getXMin() );
mergeNativeMax( gcell->getXMax() );
}
}
bool AutoVertical::checkPositions () const
{
bool coherency = true;
DbU::Unit sourcePosition = _vertical->getSourceY() - Session::getExtensionCap(getLayer());
DbU::Unit targetPosition = _vertical->getTargetY() + Session::getExtensionCap(getLayer());
if ( _sourcePosition != sourcePosition ) {
cerr << Error ( "%s\n Source position incoherency: "
"Shadow: %s, real: %s."
, _getString().c_str()
, DbU::getValueString(_sourcePosition).c_str()
, DbU::getValueString( sourcePosition).c_str()
) << endl;
coherency = false;
}
if ( _targetPosition != targetPosition ) {
cerr << Error ( "%s\n Target position incoherency: "
"Shadow: %s, real: %s."
, _getString().c_str()
, DbU::getValueString(_targetPosition).c_str()
, DbU::getValueString( targetPosition).c_str()
) << endl;
coherency = false;
}
return coherency;
}
bool AutoVertical::checkConstraints () const
{
Interval sourceConstraints = Interval(getAutoSource()->getCBXMin(),getAutoSource()->getCBXMax());
Interval targetConstraints = Interval(getAutoTarget()->getCBXMin(),getAutoTarget()->getCBXMax());
if (not sourceConstraints.intersect(targetConstraints)) {
cerr << Error ( "%s\n Constraints incoherency:\n"
" S:%s %s\n"
" T:%s %s"
, _getString().c_str()
, getString(sourceConstraints).c_str()
, getString(getAutoSource()).c_str()
, getString(targetConstraints).c_str()
, getString(getAutoTarget()).c_str()
) << endl;
return false;
}
return true;
}
bool AutoVertical::canMoveULeft ( float reserve ) const
{
#if THIS_IS_DISABLED
if (not isGlobal()) return false;
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return false;
if (not getAutoSource()->getGCell()->getLeft()) return false;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
AutoSegment* perpandiculars[2] = { autoSource->getSegment(0), autoTarget->getSegment(0) };
if ( ( (not perpandiculars[0]->isGlobal()) or (perpandiculars[0]->getAutoSource() == autoSource) )
and ( (not perpandiculars[1]->isGlobal()) or (perpandiculars[1]->getAutoSource() == autoTarget) ) )
return false;
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
unsigned int depth = Session::getRoutingGauge()->getLayerDepth( getLayer() );
float currMaxDensity = 0.0;
float leftMaxDensity = 0.0;
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getUp() ) {
if (currMaxDensity < gcell->getWDensity(depth)) currMaxDensity = gcell->getWDensity( depth );
}
begin = begin->getLeft();
end = end ->getLeft();
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getUp() ) {
if (leftMaxDensity < gcell->getWDensity(depth)) leftMaxDensity = gcell->getWDensity( depth );
}
return (leftMaxDensity + reserve < currMaxDensity);
#endif
return false;
}
bool AutoVertical::canMoveURight ( float reserve ) const
{
#if THIS_IS_DISABLED
if (not isGlobal()) return false;
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return false;
if (not getAutoSource()->getGCell()->getRight()) return false;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
AutoSegment* perpandiculars[2] = { autoSource->getSegment(0), autoTarget->getSegment(0) };
if ( ( (not perpandiculars[0]->isGlobal()) or (perpandiculars[0]->getAutoTarget() == autoSource) )
and ( (not perpandiculars[1]->isGlobal()) or (perpandiculars[1]->getAutoTarget() == autoTarget) ) )
return false;
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
unsigned int depth = Session::getRoutingGauge()->getLayerDepth( getLayer() );
float currMaxDensity = 0.0;
float leftMaxDensity = 0.0;
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getUp() ) {
if (currMaxDensity < gcell->getWDensity(depth)) currMaxDensity = gcell->getWDensity( depth );
}
begin = begin->getRight();
end = end ->getRight();
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getUp() ) {
if (leftMaxDensity < gcell->getWDensity(depth)) leftMaxDensity = gcell->getWDensity( depth );
}
return (leftMaxDensity + reserve < currMaxDensity);
#endif
return false;
}
bool AutoVertical::moveULeft ()
{
#if THIS_IS_DISABLED
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return false;
if (not getAutoSource()->getGCell()->getLeft()) return false;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
AutoSegment* perpandicular = autoSource->getSegment(0);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoSource() == autoSource) {
begin->addHSegment( perpandicular );
} else {
if (begin->getLeft() == perpandicular->getAutoSource()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
begin->getLeft()->removeHSegment( perpandicular );
}
}
perpandicular = autoTarget->getSegment(0);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoSource() == autoTarget) {
end->addHSegment( perpandicular );
} else {
if (end->getLeft() == perpandicular->getAutoSource()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
end->getLeft()->removeHSegment( perpandicular );
}
}
if (begin != end) {
for ( GCell* gcell=begin->getUp() ; gcell and gcell!=end ; gcell=gcell->getUp() )
gcell->removeVSegment( this );
}
begin = begin->getLeft();
end = end ->getLeft();
autoSource->setGCell( begin );
autoTarget->setGCell( end );
if (begin != end) {
for ( GCell* gcell=begin->getUp() ; gcell and gcell!=end ; gcell=gcell->getUp() )
gcell->addVSegment( this );
}
DbU::Unit x = begin->getSide( Flags::Horizontal ).getVMax();
setAxis( x );
return true;
#endif
return false;
}
bool AutoVertical::moveURight ()
{
#if THIS_IS_DISABLED
cdebug_log(149,0) << "AutoVertical::moveURight()" << endl;
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return true;
if (not getAutoSource()->getGCell()->getRight()) return true;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
AutoSegment* perpandicular = autoSource->getSegment(0);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoTarget() == autoSource) {
begin->addHSegment( perpandicular );
} else {
if (begin->getRight() == perpandicular->getAutoTarget()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
begin->getRight()->removeHSegment( perpandicular );
}
}
perpandicular = autoTarget->getSegment(0);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoTarget() == autoTarget) {
end->addHSegment( perpandicular );
} else {
if (end->getRight() == perpandicular->getAutoTarget()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
end->getRight()->removeHSegment( perpandicular );
}
}
if (begin != end) {
for ( GCell* gcell=begin->getUp() ; gcell and gcell!=end ; gcell=gcell->getUp() )
gcell->removeVSegment( this );
}
begin = begin->getRight();
end = end ->getRight();
autoSource->setGCell( begin );
autoTarget->setGCell( end );
if (begin != end) {
for ( GCell* gcell=begin->getUp() ; gcell and gcell!=end ; gcell=gcell->getUp() )
gcell->addVSegment( this );
}
DbU::Unit x = begin->getSide( Flags::Horizontal ).getVMin();
setAxis( x );
cdebug_log(149,0) << "Moved to axis: " << DbU::getValueString(x) << endl;
return true;
#endif
return false;
}
unsigned int AutoVertical::_makeDogleg ( GCell* doglegGCell, unsigned int flags )
{
cdebug_log(149,0) << "AutoVertical::_makeDogleg(GCell*)" << endl;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
//Session::doglegReset();
DbU::Unit doglegAxis = (doglegGCell->getYMax() + doglegGCell->getYMin()) / 2;
if (isLocal())
doglegAxis = (getSourceY() + getTargetY()) / 2;
if (doglegGCell == begin) unsetFlags( SegGlobal );
if (doglegGCell != end) {
GCell* gcell = doglegGCell;
do {
if (gcell != begin)
gcell->removeVSegment( this );
gcell = gcell->getNorth( getNativeMin() );
} while ( gcell and (gcell != end) );
}
size_t depth = Session::getRoutingGauge()->getLayerDepth ( _vertical->getLayer() );
bool upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) );
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer ( depth + ((upLayer)?1:-1) );
Session::dogleg( this );
targetDetach();
invalidate( Flags::Topology );
autoTarget->invalidate( Flags::Topology );
AutoContact* dlContact1 = AutoContactTurn::create( doglegGCell, _vertical->getNet(), contactLayer );
cdebug_log(149,0) << dlContact1 << endl;
AutoContact* dlContact2 = AutoContactTurn::create( doglegGCell, _vertical->getNet(), contactLayer );
cdebug_log(149,0) << dlContact2 << endl;
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Horizontal );
cdebug_log(149,0) << segment1 << endl;
segment1->setLayer( doglegLayer );
segment1->_setAxis( doglegAxis );
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
cdebug_log(149,0) << "New " << dlContact1->base() << "." << endl;
cdebug_log(149,0) << "New " << dlContact2->base() << "." << endl;
Session::dogleg( segment1 );
targetAttach( dlContact1 );
AutoSegment* segment2 = AutoVertical::create ( dlContact2, autoTarget, Flags::Vertical );
autoTarget->cacheAttach( segment2 );
segment2->setLayer( getLayer() );
segment2->_setAxis( getX() );
segment2->setFlags( (isSlackened()?SegSlackened:0) );
Session::dogleg( segment2 );
if (isSourceTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );
autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell)
dlContact1->migrateConstraintBox( autoTarget );
} else if (isTargetTerminal()) {
unsetFlags( SegTargetTerminal );
setFlags( SegWeakTerminal1 );
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegTargetTerminal );
autoSource->unsetFlags( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal );
if (autoSource->getGCell() == doglegGCell)
dlContact2->migrateConstraintBox( autoSource );
} else if (isWeakTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );
}
cdebug_log(149,0) << "Session::dogleg[x+1] perpand: " << segment1 << endl;
cdebug_log(149,0) << "Session::dogleg[x+2] new paral: " << segment2 << endl;
cdebug_log(149,0) << "Session::dogleg[x+0] original: " << this << endl;
dlContact1->updateCache();
dlContact2->updateCache();
//autoTarget->updateCache();
segment2->canonize( flags );
if (not isCanonical()) canonize( flags );
updateNativeConstraints();
segment2->updateNativeConstraints();
return (upLayer) ? Flags::AboveLayer : Flags::BelowLayer;
}
string AutoVertical::_getString () const
{
string s = AutoSegment::_getString();
return s;
}
Record* AutoVertical::_getRecord () const
{
Record* record = AutoSegment::_getRecord ();
record->add ( getSlot ( "_vertical", _vertical ) );
return record;
}
} // End of Anabatic namespace.

View File

@ -20,6 +20,16 @@ endif ( CHECK_DETERMINISM )
anabatic/AnabaticEngine.h
anabatic/GraphicAnabaticEngine.h
anabatic/Dijkstra.h
anabatic/AutoContact.h
anabatic/AutoContactTerminal.h
anabatic/AutoContactTurn.h
anabatic/AutoContactHTee.h
anabatic/AutoContactVTee.h
anabatic/AutoSegment.h anabatic/AutoSegments.h
anabatic/AutoHorizontal.h
anabatic/AutoVertical.h
anabatic/Session.h
)
set( mocIncludes anabatic/GraphicAnabaticEngine.h )
set( pyIncludes anabatic/PyAnabaticEngine.h
@ -35,6 +45,19 @@ endif ( CHECK_DETERMINISM )
GlobalRoute.cpp
GraphicAnabaticEngine.cpp
Dijkstra.cpp
AutoContact.cpp
AutoContactTerminal.cpp
AutoContactTurn.cpp
AutoContactHTee.cpp
AutoContactVTee.cpp
AutoSegment.cpp AutoSegments.cpp
AutoHorizontal.cpp
AutoVertical.cpp
Session.cpp
NetConstraints.cpp
NetOptimals.cpp
LoadGlobalRouting.cpp
)
set( pyCpps PyAnabaticEngine.cpp
PyGraphicAnabaticEngine.cpp

View File

@ -70,6 +70,9 @@ namespace Anabatic {
, _cg (NULL)
, _rg (NULL)
, _extensionCaps ()
, _saturateRatio (Cfg::getParamPercentage("katabatic.saturateRatio",80.0)->asDouble())
, _saturateRp (Cfg::getParamInt ("katabatic.saturateRp" ,8 )->asInt())
, _globalThreshold(0)
, _allowedDepth (0)
, _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt()))
, _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt()))
@ -117,15 +120,17 @@ namespace Anabatic {
ConfigurationConcrete::ConfigurationConcrete ( const ConfigurationConcrete& other )
: Configuration()
, _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv)
, _gcontact (other._gcontact)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps(other._extensionCaps)
, _allowedDepth (other._allowedDepth)
, _edgeCostH (other._edgeCostH)
, _edgeCostK (other._edgeCostK)
, _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv)
, _gcontact (other._gcontact)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps (other._extensionCaps)
, _saturateRatio (other._saturateRatio)
, _globalThreshold(other._globalThreshold)
, _allowedDepth (other._allowedDepth)
, _edgeCostH (other._edgeCostH)
, _edgeCostK (other._edgeCostK)
{
if (other._cg) _cg = other._cg->getClone();
if (other._rg) _rg = other._rg->getClone();
@ -220,11 +225,23 @@ namespace Anabatic {
{ return getDirection( getLayerDepth(layer) ); }
float ConfigurationConcrete::getSaturateRatio () const
{ return _saturateRatio; }
size_t ConfigurationConcrete::getSaturateRp () const
{ return _saturateRp; }
DbU::Unit ConfigurationConcrete::getGlobalThreshold () const
{ return _globalThreshold; }
DbU::Unit ConfigurationConcrete::getPitch ( size_t depth, Flags flags ) const
{
if (flags == Flags::NoFlags) return _rg->getLayerPitch(depth);
if (flags & Flags::PitchAbove) {
if (flags & Flags::AboveLayer) {
if (depth < getAllowedDepth())
return _rg->getLayerPitch( depth + 1 );
else {
@ -233,7 +250,7 @@ namespace Anabatic {
}
}
if (flags & Flags::PitchBelow) {
if (flags & Flags::BelowLayer) {
if ( (depth > 0) and (_rg->getLayerType(depth-1) != Constant::PinOnly) )
return _rg->getLayerPitch( depth - 1 );
else {
@ -282,6 +299,18 @@ namespace Anabatic {
}
void ConfigurationConcrete::setSaturateRatio ( float ratio )
{ _saturateRatio = ratio; }
void ConfigurationConcrete::setSaturateRp ( size_t threshold )
{ _saturateRp = threshold; }
void ConfigurationConcrete::setGlobalThreshold ( DbU::Unit threshold )
{ _globalThreshold = threshold; }
DbU::Unit ConfigurationConcrete::getEdgeLength () const
{ return _edgeLength; }

View File

@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; explicit-buffer-name: "Constants.cpp<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved
@ -36,17 +36,17 @@ namespace Anabatic {
string s = "";
s += (_flags & Horizontal ) ? 'h' : '-';
s += (_flags & Vertical ) ? 'v' : '-';
s += (_flags & SourceGCell ) ? 'S' : '-';
s += (_flags & TargetGCell ) ? 'T' : '-';
s += (_flags & Source ) ? 'S' : '-';
s += (_flags & Target ) ? 'T' : '-';
s += (_flags & DeviceGCell ) ? 'd' : '-';
s += (_flags & ChannelGCell) ? 'c' : '-';
s += (_flags & StrutGCell ) ? 's' : '-';
s += (_flags & MatrixGCell ) ? 'm' : '-';
s += ",";
s += (_flags & Invalidated ) ? 'i' : '-';
s += (_flags & Destroy ) ? 'D' : '-';
s += (_flags & PitchAbove ) ? 'A' : '-';
s += (_flags & PitchBelow ) ? 'B' : '-';
s += (_flags & DestroyGCell) ? 'D' : '-';
s += (_flags & AboveLayer ) ? 'A' : '-';
s += (_flags & BelowLayer ) ? 'B' : '-';
return s;
}

View File

@ -101,8 +101,8 @@ namespace Anabatic {
void Edge::_preDestroy ()
{
_source->_remove( this, _flags|Flags::SourceGCell );
_target->_remove( this, _flags|Flags::TargetGCell );
_source->_remove( this, _flags|Flags::Source );
_target->_remove( this, _flags|Flags::Target );
Super::_preDestroy();
}

File diff suppressed because it is too large Load Diff

View File

@ -189,6 +189,8 @@ namespace Anabatic {
delete dijkstra;
UpdateSession::close();
_state = EngineGlobalLoaded;
}

View File

@ -431,6 +431,13 @@ namespace Anabatic {
}
void GraphicAnabaticEngine::_detailRoute ()
{
AnabaticEngine* engine = getForFramework( CreateEngine );
engine->loadGlobalRouting( EngineLoadGrByNet );
}
void GraphicAnabaticEngine::addToMenu ( CellViewer* viewer )
{
assert( _viewer == NULL );
@ -453,6 +460,11 @@ namespace Anabatic {
, "Global Route"
, std::bind(&GraphicAnabaticEngine::_globalRoute,this)
);
_viewer->addToMenu( "placeAndRoute.anabatic.detailedRoute"
, "Anabatic - &Detailed Route"
, "Run the <b>Anabatic</b> detailed router"
, std::bind(&GraphicAnabaticEngine::_detailRoute,this)
);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,192 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2013, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NetConstraints.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/DebugSession.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Pad.h"
#include "hurricane/Plug.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Cell.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/Session.h"
#include "anabatic/AnabaticEngine.h"
namespace {
// \addtogroup NetConstraints
// \{
/* \function void propagateConstraintFromRp ( RoutingPad* rp )
* \param rp The \c RoutingPad starting point.
*
* Do a full constraint propagation starting from this \c RoutingPad.
*/
// \}
using namespace std;
using namespace CRL;
using namespace Hurricane;
using namespace Anabatic;
// -----------------------------------------------------------------
// Local Functions.
void propagateConstraintFromRp ( RoutingPad* rp )
{
cdebug_log(145,1) << "propagateConstraintFromRp() - " << rp << endl;
forEach ( Component*, icomponent, rp->getSlaveComponents() ) {
cdebug_log(145,0) << "slave component: " << *icomponent << endl;
AutoContact* sourceContact = Session::lookup( dynamic_cast<Contact*>(*icomponent) );
if (sourceContact) {
cdebug_log(145,0) << "Start slave: " << sourceContact << endl;
set<AutoSegment*> verticalSegments;
set<AutoSegment*> horizontalSegments;
forEach ( AutoSegment*, isegment, sourceContact->getAutoSegments() ) {
cdebug_log(145,0) << "Examining: " << (*isegment) << endl;
AutoContact* targetContact = isegment->getOppositeAnchor(sourceContact);
if (targetContact) {
if (isegment->isHorizontal()) {
cdebug_log(145,0) << "On horizontal stack " << (*isegment) << endl;
horizontalSegments.insert( (*isegment) );
} else {
cdebug_log(145,0) << "On vertical stack " << (*isegment) << endl;
verticalSegments.insert( (*isegment) );
}
}
}
Box constraintBox = sourceContact->getConstraintBox();
// Propagate constraint through horizontally aligned segments.
cdebug_log(145,0) << "Propagate constraint on horizontal segments" << endl;
set<AutoSegment*>::iterator ihorizontal = horizontalSegments.begin();
for ( ; ihorizontal != horizontalSegments.end() ; ++ihorizontal ) {
AutoContact* contact = NULL;
forEach ( AutoSegment*, ialigned, (*ihorizontal)->getAligneds() ) {
contact = ialigned->getAutoTarget();
cdebug_log(145,0) << "contact: " << contact << endl;
if (contact) {
cdebug_log(145,0) << "Apply to (target): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getYMin()
, constraintBox.getYMax()
, Flags::Horizontal|Flags::WarnOnError );
}
contact = ialigned->getAutoSource();
cdebug_log(145,0) << "contact: " << contact << endl;
if (contact) {
cdebug_log(145,0) << "Apply to (source): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getYMin()
, constraintBox.getYMax()
, Flags::Horizontal|Flags::WarnOnError );
}
}
}
// Propagate constraint through vertically aligned segments.
cdebug_log(145,0) << "Propagate constraint on vertical segments" << endl;
set<AutoSegment*>::iterator ivertical = verticalSegments.begin();
for ( ; ivertical != verticalSegments.end() ; ++ivertical ) {
AutoContact* contact = NULL;
forEach ( AutoSegment*, ialigned, (*ivertical)->getAligneds() ) {
contact = ialigned->getAutoTarget();
if (contact) {
cdebug_log(145,0) << "Apply to (target): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getXMin()
, constraintBox.getXMax()
, Flags::Vertical|Flags::WarnOnError );
}
contact = ialigned->getAutoSource();
if (contact) {
cdebug_log(145,0) << "Apply to (source): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getXMin()
, constraintBox.getXMax()
, Flags::Vertical|Flags::WarnOnError );
}
}
}
}
}
cdebug_log(145,0) << "propagateConstraintFromRp() - Exit" << endl;
cdebug_tabw(145,-1);
}
} // Anonymous namespace.
namespace Anabatic {
using Hurricane::Cell;
void AnabaticEngine::computeNetConstraints ( Net* net )
{
DebugSession::open( net, 140, 150);
cdebug_log(149,0) << "Anabatic::computeNetConstraints( " << net << " )" << endl;
cdebug_tabw(145,1);
vector<RoutingPad*> routingPads;
forEach ( Component*, icomponent, net->getComponents() ) {
Contact* contact = dynamic_cast<Contact*>( *icomponent );
if (contact) {
AutoContact* autoContact = Session::lookup( contact );
if (autoContact)
autoContact->restoreNativeConstraintBox();
} else {
RoutingPad* routingPad = dynamic_cast<RoutingPad*>( *icomponent );
if (routingPad) routingPads.push_back( routingPad );
}
}
for ( size_t i=0 ; i<routingPads.size() ; i++ )
propagateConstraintFromRp( routingPads[i] );
// forEach ( Segment*, isegment, net->getSegments() ) {
// AutoSegment* autoSegment = Session::lookup( *isegment );
// if (autoSegment) autoSegment->toConstraintAxis();
// }
cdebug_tabw(145,-1);
DebugSession::close();
}
} // Anabatic namespace.

View File

@ -0,0 +1,82 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NetOptimals.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/DebugSession.h"
#include "hurricane/Net.h"
#include "hurricane/Segment.h"
#include "anabatic/Session.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using namespace std;
using Hurricane::tab;
using Hurricane::ForEachIterator;
using Hurricane::Net;
using Hurricane::Segment;
using Hurricane::DebugSession;
void AnabaticEngine::_computeNetOptimals ( Net* net )
{
DebugSession::open( net, 140, 150 );
cdebug_log(149,0) << "Anabatic::_computeNetOptimals( " << net << " )" << endl;
cdebug_tabw(145,1);
vector<AutoSegment*> segments;
forEach ( Segment*, segment, net->getSegments() ) {
AutoSegment* autoSegment = Session::lookup( *segment );
if (autoSegment) segments.push_back( autoSegment );
}
sort( segments.begin(), segments.end(), AutoSegment::CompareId() );
set<AutoSegment*> processeds;
for ( size_t i=0 ; i<segments.size() ; i++ )
segments[i]->computeOptimal( processeds );
cdebug_tabw(145,-1);
DebugSession::close();
}
void AnabaticEngine::toOptimals ( Net* net )
{
DebugSession::open( net, 140, 150 );
cdebug_log(149,0) << "Anabatic::_toOptimals( " << net << " )" << endl;
cdebug_tabw(145,1);
vector<AutoSegment*> segments;
forEach ( Segment*, segment, net->getSegments() ) {
AutoSegment* autoSegment = Session::lookup( *segment );
if (autoSegment) segments.push_back( autoSegment );
}
sort( segments.begin(), segments.end(), AutoSegment::CompareId() );
for ( size_t i=0 ; i<segments.size() ; i++ ) {
if (segments[i]->isCanonical()) segments[i]->toOptimalAxis();
}
cdebug_tabw(145,-1);
DebugSession::close();
}
} // Anabatic namespace.

407
anabatic/src/Session.cpp Normal file
View File

@ -0,0 +1,407 @@
// -*- mode: C++; explicit-buffer-name: "Session.cpp<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Session.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/Error.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Cell.h"
#include "hurricane/UpdateSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/Configuration.h"
#include "anabatic/Session.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/AnabaticEngine.h"
namespace {
const char* reopenSession =
"Session::open() :\n\n"
" Session already open for %s (internal error).";
const char* openSessionError =
"%s :\n\n"
" Session has not been opened (internal error).";
} // End of local namespace.
namespace Anabatic {
using namespace std;
using Hurricane::tab;
using Hurricane::Error;
using Hurricane::ForEachIterator;
using Hurricane::UpdateSession;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::Cell;
// -------------------------------------------------------------------
// Class : "Anabatic::Session".
Session* Session::_session = NULL;
Session* Session::get ( const char* message )
{
if (not _session and message)
throw Error( openSessionError, message );
return _session;
}
Session::Session ( AnabaticEngine* anbt )
: _anabatic (anbt)
, _technology (anbt->getConfiguration()->getRoutingGauge()->getTechnology())
, _cellGauge (anbt->getConfiguration()->getCellGauge())
, _routingGauge (anbt->getConfiguration()->getRoutingGauge())
, _autoContacts ()
, _doglegs ()
, _segmentInvalidateds()
, _segmentRevalidateds()
, _netInvalidateds ()
, _netRevalidateds ()
{ }
void Session::_postCreate ()
{
UpdateSession::open();
_session = this;
}
Session::~Session ()
{ }
void Session::_preDestroy ()
{
if (_anabatic->getState() <= EngineActive) {
_revalidate ();
_anabatic->updateDensity();
}
UpdateSession::close();
}
bool Session::_doDestroyBaseContact () { return _anabatic->doDestroyBaseContact(); }
bool Session::_doDestroyBaseSegment () { return _anabatic->doDestroyBaseSegment(); }
bool Session::_doDestroyTool () { return _anabatic->doDestroyTool(); }
Configuration* Session::_getConfiguration () { return _anabatic->getConfiguration(); }
void Session::_invalidate ( Net* net )
{
cdebug_log(149,0) << "Session::invalidate(Net*) - " << net << endl;
_netInvalidateds.insert(net);
}
void Session::_canonize ()
{
cdebug_log(145,1) << "Anabatic::Session::_canonize()" << endl;
if (_segmentInvalidateds.empty()) {
cdebug_log(145,0) << "Invalidated AutoSegment collection <_segmentInvalidateds> is empty." << endl;
cdebug_tabw(145,-1);
return;
}
set<Segment*> exploredSegments;
vector<AutoSegment*> aligneds;
// Should no longer be necessary to ensure determinism.
//sort( _segmentInvalidateds.begin(), _segmentInvalidateds.end(), AutoSegment::CompareId() );
for ( size_t i=0 ; i<_segmentInvalidateds.size() ; i++ ) {
AutoSegment* seedSegment = _segmentInvalidateds[i];
AutoSegment* canonical = seedSegment;
if (exploredSegments.find(seedSegment->base()) == exploredSegments.end()) {
cdebug_log(145,0) << "New chunk from: " << seedSegment << endl;
aligneds.push_back( seedSegment );
bool isWeakGlobal = seedSegment->isGlobal();
if (not seedSegment->isNotAligned()) {
forEach ( AutoSegment*, aligned, seedSegment->getAligneds() ) {
cdebug_log(145,0) << "Aligned: " << *aligned << endl;
aligneds.push_back ( *aligned );
exploredSegments.insert ( aligned->base() );
isWeakGlobal = isWeakGlobal or aligned->isGlobal();
if (AutoSegment::CompareId()( *aligned, canonical ))
canonical = *aligned;
}
}
cdebug_tabw(145,1);
canonical->setFlags( SegCanonical );
cdebug_log(145,0) << "Canonical: " << canonical << endl;
for ( size_t j=0 ; j<aligneds.size() ; j++ ) {
if (isWeakGlobal and not aligneds[j]->isGlobal()) aligneds[j]->setFlags ( SegWeakGlobal );
else aligneds[j]->unsetFlags( SegWeakGlobal );
if (aligneds[j] == canonical) continue;
if (aligneds[j]->isCanonical()) {
cerr << Error("Session::_canonize(): On %s\n"
" Segment is no longer the canonical one, this must not happens."
,getString(aligneds[j]).c_str()) << endl;
}
aligneds[j]->unsetFlags( SegCanonical );
cdebug_log(145,0) << "Secondary: " << aligneds[j] << endl;
}
if (aligneds.empty()) canonical->setFlags( SegNotAligned );
cdebug_log(149,0) << "Align @" << DbU::toLambda(canonical->getAxis())
<< " on " << canonical << endl;
//canonical->setAxis( canonical->getAxis(), Flags::Realignate );
if (canonical->isUnsetAxis()) canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate );
else canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate );
aligneds.clear();
cdebug_tabw(145,-1);
}
}
cdebug_tabw(145,-1);
}
void Session::_revalidateTopology ()
{
cdebug_log(145,1) << "Anabatic::Session::_revalidateTopology()" << endl;
set<Net*>::iterator inet = _netInvalidateds.begin();
for ( ; inet != _netInvalidateds.end() ; inet++ ) {
cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << *inet << endl;
_anabatic->updateNetTopology ( *inet );
_anabatic->computeNetConstraints( *inet );
_anabatic->_computeNetOptimals ( *inet );
_anabatic->_computeNetTerminals ( *inet );
}
_canonize ();
for ( size_t i=0 ; i<_segmentInvalidateds.size() ; ++i ) {
if (_segmentInvalidateds[i]->isCanonical()) {
if (_segmentInvalidateds[i]->isUnsetAxis()) _segmentInvalidateds[i]->toOptimalAxis();
else _segmentInvalidateds[i]->toConstraintAxis();
}
}
_netRevalidateds.clear();
_netRevalidateds.swap( _netInvalidateds );
cdebug_tabw(145,-1);
}
size_t Session::_revalidate ()
{
cdebug_log(145,1) << "Anabatic::Session::revalidate()" << endl;
cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl;
cdebug_log(145,0) << "_autoContacts.size(): " << _autoContacts.size() << endl;
size_t count = 0;
if (not _netInvalidateds.empty()) _revalidateTopology();
cdebug_log(145,0) << "AutoContacts Revalidate (after _revalidateTopology())." << endl;
for ( size_t i=0 ; i < _autoContacts.size() ; i++, count++ )
_autoContacts[i]->updateGeometry();
_autoContacts.clear();
cdebug_log(145,0) << "AutoSegments Revalidate (after AutoContact::updateGeometry())." << endl;
cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl;
_segmentRevalidateds.clear();
for ( size_t i=0 ; i < _segmentInvalidateds.size() ; ++i, ++count ) {
_segmentInvalidateds[i]->revalidate();
if ( not _destroyedSegments.empty()
and (_destroyedSegments.find(_segmentInvalidateds[i]) != _destroyedSegments.end()) )
continue;
_segmentRevalidateds.push_back( _segmentInvalidateds[i] );
}
_segmentInvalidateds.clear();
cdebug_log(145,0) << "AutoSegments/AutoContacts queued deletion." << endl;
unsigned int flags = _anabatic->flags() & Flags::DestroyMask;
_anabatic->flags() = Flags::DestroyMask;
set<AutoSegment*>::iterator isegment = _destroyedSegments.begin();
for ( ; isegment != _destroyedSegments.end() ; isegment++ ) {
AutoContact* source = (*isegment)->getAutoSource();
AutoContact* target = (*isegment)->getAutoTarget();
(*isegment)->destroy();
if (source and source->canDestroy(true)) source->destroy();
if (target and target->canDestroy(true)) target->destroy();
}
_anabatic->flags() = flags;
set<AutoSegment*>().swap( _destroyedSegments );
cdebug_tabw(145,-1);
return count;
}
Session* Session::open ( AnabaticEngine* anbt )
{
cdebug_log(145,0) << "Session::open()" << endl;
if (_session) {
if (_session->_anabatic != anbt)
throw Error( reopenSession, getString(_session->getAnabatic()).c_str() );
return _session;
}
Session* session = new Session ( anbt );
session->_postCreate();
return session;
}
void Session::close ()
{
cdebug_log(145,1) << "Session::close()" << endl;
if (not _session) throw Error( openSessionError, "Session::Close()" );
_session->_preDestroy();
delete _session;
_session = NULL;
cdebug_tabw(145,-1);
}
unsigned int Session::getDirection ( size_t depth )
{
RoutingGauge* rg = get("getDirection()")->_routingGauge;
switch ( rg->getLayerDirection(depth) ) {
case Constant::Horizontal: return Flags::Horizontal;
case Constant::Vertical: return Flags::Vertical;
}
return 0;
}
DbU::Unit Session::_getPitch ( size_t depth, unsigned int flags ) const
{
if (flags == Flags::NoFlags) return _routingGauge->getLayerPitch(depth);
if (flags & Flags::AboveLayer) {
if (depth < getAllowedDepth())
return _routingGauge->getLayerPitch( depth + 1 );
else {
if ( (depth > 0) and (_routingGauge->getLayerType(depth-1) != Constant::PinOnly) )
return _routingGauge->getLayerPitch( depth - 1 );
}
}
if (flags & Flags::BelowLayer) {
if ( (depth > 0) and (_routingGauge->getLayerType(depth-1) != Constant::PinOnly) )
return _routingGauge->getLayerPitch( depth - 1 );
else {
if (depth < getAllowedDepth())
return _routingGauge->getLayerPitch( depth + 1 );
}
}
// Should issue at least a warning here.
return _routingGauge->getLayerPitch(depth);
}
bool Session::isInDemoMode ()
{ return get("isInDemoMode()")->_anabatic->isInDemoMode(); }
float Session::getSaturateRatio ()
{ return get("getSaturateRatio()")->_anabatic->getSaturateRatio(); }
size_t Session::getSaturateRp ()
{ return get("getSaturateRp()")->_anabatic->getSaturateRp(); }
bool Session::doWarnGCellOverload ()
{ return get("doWarnGCellOverload()")->_anabatic->doWarnOnGCellOverload(); }
void Session::setAnabaticFlags ( unsigned int flags )
{ get("setKabaticFlags()")->_anabatic->flags() = flags; }
void Session::link ( AutoContact* autoContact )
{ return get("link(AutoContact*)")->_anabatic->_link( autoContact ); }
void Session::link ( AutoSegment* autoSegment )
{ return get("link(AutoSegment*)")->_anabatic->_link( autoSegment ); }
void Session::unlink ( AutoContact* autoContact )
{ return get("unlink(AutoContact*)")->_anabatic->_unlink( autoContact ); }
void Session::unlink ( AutoSegment* autoSegment )
{ return get("unlink(AutoSegment*)")->_anabatic->_unlink( autoSegment ); }
AutoContact* Session::lookup ( Contact* contact )
{ return get("lookup(Contact*)")->_anabatic->_lookup( contact ); }
AutoSegment* Session::lookup ( Segment* segment )
{ return get("lookup(Segment*)")->_anabatic->_lookup( segment ); }
string Session::_getString () const
{
return "<" + _getTypeName() + " "
+ getString(_anabatic->getCell()->getName())
+ ">";
}
Record* Session::_getRecord () const
{
Record* record = new Record ( _getString() );
record->add ( getSlot ( "_anabatic" , _anabatic ) );
record->add ( getSlot ( "_autoContacts", &_autoContacts ) );
//record->add ( getSlot ( "_autoSegments", &_autoSegments ) );
return record;
}
} // End of Anabatic namespace.

View File

@ -34,6 +34,8 @@ namespace Hurricane {
#include "anabatic/Configuration.h"
#include "anabatic/Matrix.h"
#include "anabatic/GCell.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoSegments.h"
namespace Anabatic {
@ -53,80 +55,150 @@ namespace Anabatic {
class AnabaticEngine : public ToolEngine {
public:
enum DensityMode { AverageHVDensity=1 // Average between all densities.
, AverageHDensity =2 // Average between all H densities.
, AverageVDensity =3 // Average between all V densities.
, MaxHVDensity =4 // Maximum between average H and average V.
, MaxVDensity =5 // Maximum of V densities.
, MaxHDensity =6 // Maximum of H densities.
, MaxDensity =7 // Maximum of H & V densities.
};
public:
typedef ToolEngine Super;
public:
static AnabaticEngine* create ( Cell* );
static AnabaticEngine* get ( const Cell* );
static const Name& staticGetName ();
virtual const Name& getName () const;
virtual Configuration* getConfiguration ();
inline CellViewer* getViewer () const;
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 ();
void reset ();
void startMeasures ();
void stopMeasures ();
void printMeasures ( const string& ) const;
inline void _add ( GCell* );
inline void _remove ( GCell* );
inline void _updateLookup ( GCell* );
inline bool _inDestroy () const;
// Inspector support.
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
protected:
AnabaticEngine ( Cell* );
virtual ~AnabaticEngine ();
virtual void _postCreate ();
virtual void _preDestroy ();
void _clear ();
private:
AnabaticEngine ( const AnabaticEngine& );
AnabaticEngine& operator= ( const AnabaticEngine& );
static AnabaticEngine* create ( Cell* );
static AnabaticEngine* get ( const Cell* );
static const Name& staticGetName ();
virtual const Name& getName () const;
virtual Configuration* getConfiguration ();
inline unsigned int getDensityMode () const;
inline CellViewer* getViewer () const;
inline void setViewer ( CellViewer* );
inline EngineState getState () const;
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 setState ( EngineState state );
inline void setDensityMode ( unsigned int );
inline void addOv ( Edge* );
inline void removeOv ( Edge* );
// Dijkstra related functions.
inline int getStamp () const;
inline int incStamp ();
// Global routing related functions.
void globalRoute ();
void cleanupGlobal ();
// Detailed routing related functions.
inline bool isInDemoMode () const;
inline bool doWarnOnGCellOverload () const;
inline bool doDestroyBaseContact () const;
inline bool doDestroyBaseSegment () const;
inline bool doDestroyTool () const;
inline DbU::Unit getGlobalThreshold () const;
inline float getSaturateRatio () const;
inline size_t getSaturateRp () const;
inline DbU::Unit getExtensionCap () const;
void updateDensity ();
inline void setGlobalThreshold ( DbU::Unit );
inline void setSaturateRatio ( float );
inline void setSaturateRp ( size_t );
void loadGlobalRouting ( unsigned int method );
void computeNetConstraints ( Net* );
void toOptimals ( Net* );
void updateNetTopology ( Net* );
void finalizeLayout ();
inline const AutoContactLut& _getAutoContactLut () const;
inline const AutoSegmentLut& _getAutoSegmentLut () const;
void _link ( AutoContact* );
void _link ( AutoSegment* );
void _unlink ( AutoContact* );
void _unlink ( AutoSegment* );
AutoContact* _lookup ( Contact* ) const;
AutoSegment* _lookup ( Segment* ) const;
void _loadGrByNet ();
void _loadNetGlobalRouting ( Net* );
void _computeNetOptimals ( Net* );
void _computeNetTerminals ( Net* );
void _alignate ( Net* );
void _saveNet ( Net* );
void _destroyAutoContacts ();
void _destroyAutoSegments ();
// Misc. functions.
inline const Flags& flags () const;
inline Flags& flags ();
void reset ();
void startMeasures ();
void stopMeasures ();
void printMeasures ( const string& ) const;
inline void _add ( GCell* );
inline void _remove ( GCell* );
inline void _updateLookup ( GCell* );
inline bool _inDestroy () const;
// Inspector support.
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
protected:
AnabaticEngine ( Cell* );
virtual ~AnabaticEngine ();
virtual void _postCreate ();
virtual void _preDestroy ();
void _gutAnabatic ();
private:
AnabaticEngine ( const AnabaticEngine& );
AnabaticEngine& operator= ( const AnabaticEngine& );
private:
static Name _toolName;
Timer _timer;
Configuration* _configuration;
Matrix _matrix;
vector<GCell*> _gcells;
vector<Edge*> _ovEdges;
CellViewer* _viewer;
Flags _flags;
int _stamp;
static Name _toolName;
Timer _timer;
Configuration* _configuration;
EngineState _state;
Matrix _matrix;
vector<GCell*> _gcells;
vector<Edge*> _ovEdges;
CellViewer* _viewer;
Flags _flags;
int _stamp;
unsigned int _densityMode;
AutoSegmentLut _autoSegmentLut;
AutoContactLut _autoContactLut;
};
inline CellViewer* AnabaticEngine::getViewer () const { return _viewer; }
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); }
inline const Flags& AnabaticEngine::flags () const { return _flags; }
inline Flags& AnabaticEngine::flags () { return _flags; }
inline void AnabaticEngine::_updateLookup ( GCell* gcell ) { _matrix.updateLookup(gcell); }
inline bool AnabaticEngine::_inDestroy () const { return _flags & Flags::Destroy; }
inline EngineState AnabaticEngine::getState () const { return _state; }
inline void AnabaticEngine::setState ( EngineState state ) { _state = state; }
inline CellViewer* AnabaticEngine::getViewer () const { return _viewer; }
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); }
inline unsigned int AnabaticEngine::getDensityMode () const { return _densityMode; }
inline void AnabaticEngine::setDensityMode ( unsigned int mode ) { _densityMode=mode; }
inline const AutoContactLut& AnabaticEngine::_getAutoContactLut () const { return _autoContactLut; }
inline const AutoSegmentLut& AnabaticEngine::_getAutoSegmentLut () const { return _autoSegmentLut; }
inline const Flags& AnabaticEngine::flags () const { return _flags; }
inline Flags& AnabaticEngine::flags () { return _flags; }
inline bool AnabaticEngine::doDestroyBaseContact () const { return _flags & Flags::DestroyBaseContact; }
inline bool AnabaticEngine::doDestroyBaseSegment () const { return _flags & Flags::DestroyBaseSegment; }
inline bool AnabaticEngine::doDestroyTool () const { return _state >= EngineGutted; }
inline bool AnabaticEngine::doWarnOnGCellOverload () const { return _flags & Flags::WarnOnGCellOverload; }
inline bool AnabaticEngine::isInDemoMode () const { return _flags & Flags::DemoMode; }
inline DbU::Unit AnabaticEngine::getGlobalThreshold () const { return _configuration->getGlobalThreshold(); }
inline float AnabaticEngine::getSaturateRatio () const { return _configuration->getSaturateRatio(); }
inline size_t AnabaticEngine::getSaturateRp () const { return _configuration->getSaturateRp(); }
inline void AnabaticEngine::setSaturateRatio ( float ratio ) { _configuration->setSaturateRatio(ratio); }
inline void AnabaticEngine::setSaturateRp ( size_t threshold ) { _configuration->setSaturateRp(threshold); }
inline void AnabaticEngine::setGlobalThreshold ( DbU::Unit threshold ) { _configuration->setGlobalThreshold(threshold); }
inline void AnabaticEngine::_updateLookup ( GCell* gcell ) { _matrix.updateLookup(gcell); }
inline bool AnabaticEngine::_inDestroy () const { return _flags & Flags::DestroyMask; }
inline void AnabaticEngine::_add ( GCell* gcell )
{

View File

@ -0,0 +1,351 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoContact.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOCONTACT_H
#define ANABATIC_AUTOCONTACT_H
#include <vector>
#include <map>
#include "hurricane/Contact.h"
#include "hurricane/ExtensionGo.h"
#include "anabatic/Constants.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/GCell.h"
namespace Anabatic {
using std::cerr;
using std::endl;
using Hurricane::tab;
using Hurricane::Name;
using Hurricane::Net;
using Hurricane::Component;
using Hurricane::Components;
using Hurricane::Layer;
using Hurricane::Contact;
using Hurricane::ExtensionGo;
class AnabaticEngine;
class AutoHorizontal;
class AutoVertical;
class AutoContact;
typedef std::map<Contact*,AutoContact*> AutoContactLut;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContact".
enum AutoContactFlag { CntFixed = 0x00000001
, CntTerminal = 0x00000002
, CntTurn = 0x00000004
, CntHTee = 0x00000008
, CntVTee = 0x00000010
, CntInvalidated = 0x00000020
, CntInvalidatedCache = 0x00000040
, CntInCreationStage = 0x00000080
, CntBadTopology = 0x00000100
, CntIgnoreAnchor = 0x00000200
, CntWeakTerminal = 0x00000400
, CntUserNativeConstraints = 0x00000800
};
class AutoContact {
public:
static AutoContact* createFrom ( Contact* );
public:
// Wrapped Contact Accessors.
inline Hook* getBodyHook ();
inline Hook* getAnchorHook ();
inline Component* getAnchor () const;
inline Net* getNet () const;
inline const Layer* getLayer () const;
inline DbU::Unit getX () const;
inline DbU::Unit getY () const;
inline DbU::Unit getDx () const;
inline DbU::Unit getDy () const;
inline Point getCenter () const;
inline Point getPosition () const;
inline DbU::Unit getWidth () const;
inline DbU::Unit getHalfWidth () const;
inline DbU::Unit getHeight () const;
inline DbU::Unit getHalfHeight () const;
inline Components getSlaveComponents () const;
// Wrapped Contact Modifiers.
inline void setLayer ( const Layer* );
inline void setWidth ( DbU::Unit );
inline void setHeight ( DbU::Unit );
inline void setSizes ( DbU::Unit width, DbU::Unit height );
inline void setX ( DbU::Unit );
inline void setY ( DbU::Unit );
inline void setPosition ( DbU::Unit width, DbU::Unit height );
inline void setPosition ( const Point& );
inline void setDx ( DbU::Unit );
inline void setDy ( DbU::Unit );
inline void setOffset ( DbU::Unit dx, DbU::Unit dy );
virtual void translate ( const DbU::Unit& tx, const DbU::Unit& ty );
// Predicates.
inline bool isInCreationStage () const;
inline bool isInvalidated () const;
inline bool isInvalidatedCache () const;
inline bool isTerminal () const;
inline bool isTurn () const;
bool isTee ( unsigned int direction ) const;
inline bool isHTee () const;
inline bool isVTee () const;
inline bool isFixed () const;
inline bool isUserNativeConstraints () const;
inline bool hasBadTopology () const;
bool canDestroy ( unsigned int flags=0 ) const;
bool canMoveUp ( const AutoSegment* moved ) const;
// Accessors.
inline Contact* base () const;
static size_t getAllocateds ();
static const Name& getStaticName ();
virtual const Name& getName () const;
inline size_t getId () const;
virtual Box getBoundingBox () const;
inline GCell* getGCell () const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const = 0;
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const = 0;
virtual AutoSegment* getSegment ( unsigned int ) const = 0;
unsigned int getMinDepth () const;
unsigned int getMaxDepth () const;
void getLengths ( DbU::Unit* lengths, AutoSegment::DepthLengthSet& );
virtual Box getNativeConstraintBox () const;
Interval getNativeUConstraints ( unsigned int direction ) const;
Interval getUConstraints ( unsigned int direction ) const;
inline DbU::Unit getCBXMin () const;
inline DbU::Unit getCBXMax () const;
inline DbU::Unit getCBYMin () const;
inline DbU::Unit getCBYMax () const;
inline Box getConstraintBox () const;
Box& intersectConstraintBox ( Box& box ) const;
// Collections.
AutoSegments getAutoSegments ();
// Modifiers.
void invalidate ( unsigned int flags=0 );
virtual void cacheDetach ( AutoSegment* ) = 0;
virtual void cacheAttach ( AutoSegment* ) = 0;
virtual void updateCache () = 0;
virtual void updateGeometry () = 0;
virtual void updateTopology () = 0;
void showTopologyError ( const std::string&, unsigned int flags=0 );
virtual void checkTopology ();
inline void setFlags ( unsigned int );
inline void unsetFlags ( unsigned int );
void setGCell ( GCell* );
inline void setCBXMin ( DbU::Unit xMin );
inline void setCBXMax ( DbU::Unit xMax );
inline void setCBYMin ( DbU::Unit yMin );
inline void setCBYMax ( DbU::Unit yMax );
void setConstraintBox ( const Box& box );
bool restrictConstraintBox ( DbU::Unit constraintMin
, DbU::Unit constraintMax
, unsigned int flags=Flags::WarnOnError );
void restoreNativeConstraintBox ();
void migrateConstraintBox ( AutoContact* other );
void destroy ();
// Inspector Management.
Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
private:
// Internal: Attributes.
static size_t _maxId;
static size_t _allocateds;
static const Name _goName;
protected:
size_t _id;
Contact* _contact;
GCell* _gcell;
unsigned int _flags;
int _dxMin:8;
int _dxMax:8;
int _dyMin:8;
int _dyMax:8;
protected:
// Constructors & Destructors.
AutoContact ( GCell*, Contact* );
virtual ~AutoContact ();
static void _preCreate ( GCell*, Net*, const Layer* );
virtual void _postCreate ();
virtual void _preDestroy ();
private:
AutoContact ( const AutoContact& );
AutoContact& operator= ( const AutoContact& );
protected:
inline int _getDeltaMin ( DbU::Unit x, DbU::Unit xMin );
inline int _getDeltaMax ( DbU::Unit x, DbU::Unit xMin, DbU::Unit xMax );
static void _getTopology ( Contact*, Component*& anchor, Horizontal**&, Vertical**&, size_t );
virtual void _invalidate ( unsigned int flags ) = 0;
};
// Wrapped Contact Inline Functions.
inline Hook* AutoContact::getBodyHook () { return _contact->getBodyHook(); }
inline Hook* AutoContact::getAnchorHook () { return _contact->getAnchorHook(); }
inline Component* AutoContact::getAnchor () const { return _contact->getAnchor(); }
inline Net* AutoContact::getNet () const { return _contact->getNet(); }
inline const Layer* AutoContact::getLayer () const { return _contact->getLayer(); }
inline DbU::Unit AutoContact::getX () const { return _contact->getX(); }
inline DbU::Unit AutoContact::getY () const { return _contact->getY(); }
inline DbU::Unit AutoContact::getDx () const { return _contact->getDx(); }
inline DbU::Unit AutoContact::getDy () const { return _contact->getDy(); }
inline Point AutoContact::getCenter () const { return _contact->getCenter(); }
inline Point AutoContact::getPosition () const { return _contact->getPosition(); }
inline DbU::Unit AutoContact::getWidth () const { return _contact->getWidth(); }
inline DbU::Unit AutoContact::getHalfWidth () const { return _contact->getHalfWidth(); }
inline DbU::Unit AutoContact::getHeight () const { return _contact->getHeight(); }
inline DbU::Unit AutoContact::getHalfHeight () const { return _contact->getHalfHeight(); }
inline Components AutoContact::getSlaveComponents () const { return _contact->getSlaveComponents(); }
inline void AutoContact::setLayer ( const Layer* layer ) { _contact->setLayer(layer); }
inline void AutoContact::setWidth ( DbU::Unit w ) { _contact->setWidth(w); }
inline void AutoContact::setHeight ( DbU::Unit h ) { _contact->setHeight(h); }
inline void AutoContact::setSizes ( DbU::Unit w, DbU::Unit h ) { _contact->setSizes(w,h); }
inline void AutoContact::setX ( DbU::Unit x ) { _contact->setX(x); }
inline void AutoContact::setY ( DbU::Unit y ) { _contact->setY(y); }
inline void AutoContact::setPosition ( DbU::Unit x, DbU::Unit y ) { _contact->setPosition(x,y); }
inline void AutoContact::setPosition ( const Point& p ) { _contact->setPosition(p); }
inline void AutoContact::setDx ( DbU::Unit dx ) { _contact->setDx(dx); }
inline void AutoContact::setDy ( DbU::Unit dy ) { _contact->setDy(dy); }
inline void AutoContact::setOffset ( DbU::Unit dx, DbU::Unit dy ) { _contact->setOffset(dx,dy); }
// AutoContact Inline Functions.
inline bool AutoContact::isInCreationStage () const { return _flags&CntInCreationStage; }
inline bool AutoContact::isInvalidated () const { return _flags&CntInvalidated; }
inline bool AutoContact::isInvalidatedCache () const { return _flags&CntInvalidatedCache; }
inline bool AutoContact::isTurn () const { return _flags&CntTurn; }
inline bool AutoContact::isFixed () const { return _flags&CntFixed; }
inline bool AutoContact::isUserNativeConstraints () const { return _flags&CntUserNativeConstraints; }
inline bool AutoContact::isTerminal () const { return _flags&CntTerminal; }
inline bool AutoContact::isHTee () const { return _flags&CntHTee; }
inline bool AutoContact::isVTee () const { return _flags&CntVTee; }
inline bool AutoContact::hasBadTopology () const { return _flags&CntBadTopology; }
inline size_t AutoContact::getId () const { return _id; }
inline Contact* AutoContact::base () const { return _contact; }
inline GCell* AutoContact::getGCell () const { return _gcell; }
inline Box AutoContact::getConstraintBox () const { return Box(getCBXMin(),getCBYMin(),getCBXMax(),getCBYMax()); }
inline void AutoContact::setCBXMin ( DbU::Unit xMin ) { _dxMin = _getDeltaMin(xMin,_gcell->getXMin()); }
inline void AutoContact::setCBXMax ( DbU::Unit xMax ) { _dxMax = _getDeltaMax(xMax,_gcell->getXMin(),_gcell->getXMax()); }
inline void AutoContact::setCBYMin ( DbU::Unit yMin ) { _dyMin = _getDeltaMin(yMin,_gcell->getYMin()); }
inline void AutoContact::setCBYMax ( DbU::Unit yMax ) { _dyMax = _getDeltaMax(yMax,_gcell->getYMin(),_gcell->getYMax()); }
inline void AutoContact::setFlags ( unsigned int flags ) { _flags|= flags; }
inline void AutoContact::unsetFlags ( unsigned int flags ) { _flags&=~flags; }
inline int AutoContact::_getDeltaMin ( DbU::Unit x, DbU::Unit xMin ) { if (x<xMin) return 0; return (int)DbU::toLambda(x-xMin); }
inline int AutoContact::_getDeltaMax ( DbU::Unit x, DbU::Unit xMin, DbU::Unit xMax ) { if (x>xMax) x=xMax; return (int)DbU::toLambda(x-xMin); }
inline DbU::Unit AutoContact::getCBXMin () const
{ return isFixed() ? _contact->getX() : DbU::fromLambda(_dxMin) + _gcell->getXMin(); }
inline DbU::Unit AutoContact::getCBXMax () const
{ return isFixed() ? _contact->getX() : DbU::fromLambda(_dxMax) + _gcell->getXMin(); }
inline DbU::Unit AutoContact::getCBYMin () const
{ return isFixed() ? _contact->getY() : DbU::fromLambda(_dyMin) + _gcell->getYMin(); }
inline DbU::Unit AutoContact::getCBYMax () const
{ return isFixed() ? _contact->getY() : DbU::fromLambda(_dyMax) + _gcell->getYMin(); }
// -------------------------------------------------------------------
// Class : "Anabatic::LocatorHelper".
class LocatorHelper {
public:
inline LocatorHelper ( AutoContact*, unsigned int flags=0 );
inline bool isValid () const;
inline AutoSegment* getSegment () const;
inline void progress ();
private:
inline unsigned int _min () const;
inline unsigned int _max () const;
private:
unsigned int _flags;
unsigned int _index;
AutoContact* _contact;
};
inline LocatorHelper::LocatorHelper ( AutoContact* contact, unsigned int flags )
: _flags(flags), _index(_min()), _contact(contact)
{
cdebug_tabw(145,1);
cdebug_log(145,0) << "CTOR LocatorHelper " << contact->_getString() << endl;
cdebug_log(145,0) << "+ _min():" << _min() << endl;
cdebug_log(145,0) << "+ _max():" << _max() << endl;
cdebug_log(145,0) << "+ getSegment(_min()):" << _contact->getSegment(_min()) << endl;
if (not _contact->getSegment(_index)) progress();
cdebug_tabw(145,-1);
}
inline bool LocatorHelper::isValid () const
{ return _index < _max(); }
inline unsigned int LocatorHelper::_min () const
{ return (_flags & (Flags::Horizontal|Flags::WithPerpands)) ? 0 : 2; }
inline unsigned int LocatorHelper::_max () const
{ return ((_flags & Flags::Horizontal) and not (_flags & Flags::WithPerpands)) ? 2 : 4; }
inline AutoSegment* LocatorHelper::getSegment () const
{
cdebug_log(145,0) << "LocatorHelper::getSegment(" << _index << ") - " << _contact->getSegment(_index) << endl;
return (_index < _max()) ? _contact->getSegment(_index) : NULL;
}
inline void LocatorHelper::progress ()
{
cdebug_tabw(145,1);
++_index;
cdebug_log(145,0) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl;
while ((_index < _max()) and (_contact->getSegment(_index) == NULL)) {
++_index;
cdebug_log(145,0) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl;
}
cdebug_tabw(145,-1);
}
// -------------------------------------------------------------------
// Helper Functions.
template<typename Type>inline void order ( Type& a, Type& b ) { if (a>b) std::swap(a,b); }
inline DbU::Unit setInBound ( DbU::Unit lower, DbU::Unit upper, DbU::Unit& value )
{
if ( lower > value ) value = lower;
if ( upper < value ) value = upper;
return value;
}
inline size_t abssub ( size_t a, size_t b ) { return (a>b) ? a-b : b-a; }
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoContact);
#endif // ANABATIC_AUTOCONTACT_H

View File

@ -0,0 +1,76 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoContactHTee.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOCONTACT_HTEE_H
#define ANABATIC_AUTOCONTACT_HTEE_H
#include "anabatic/AutoContact.h"
namespace Anabatic {
class AutoHorizontal;
class AutoVertical;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactHTee".
class AutoContactHTee : public AutoContact {
friend class AutoContact;
public:
static AutoContactHTee* create ( GCell*, Net*, const Layer* );
protected:
// Constructors & Destructors.
AutoContactHTee ( GCell*, Contact* );
virtual ~AutoContactHTee ();
virtual void _invalidate ( unsigned int flags );
public:
inline AutoHorizontal* getHorizontal1 () const;
inline AutoHorizontal* getHorizontal2 () const;
inline AutoVertical* getVertical1 () const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const;
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const;
virtual AutoSegment* getSegment ( unsigned int ) const;
virtual void updateGeometry ();
virtual void updateTopology ();
virtual void cacheDetach ( AutoSegment* );
virtual void cacheAttach ( AutoSegment* );
virtual void updateCache ();
virtual string _getTypeName () const;
private:
AutoContactHTee ( const AutoContactHTee& );
AutoContactHTee& operator= ( const AutoContactHTee& );
private:
AutoHorizontal* _horizontal1;
AutoHorizontal* _horizontal2;
AutoVertical* _vertical1;
};
inline AutoHorizontal* AutoContactHTee::getHorizontal1 () const { return _horizontal1; };
inline AutoHorizontal* AutoContactHTee::getHorizontal2 () const { return _horizontal2; };
inline AutoVertical* AutoContactHTee::getVertical1 () const { return _vertical1; };
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoContactHTee);
#endif // ANABATIC_AUTOCONTACT_HTEE_H

View File

@ -0,0 +1,82 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2012-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoContactTerminal.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOCONTACT_TERMINAL_H
#define ANABATIC_AUTOCONTACT_TERMINAL_H
#include "anabatic/AutoContact.h"
namespace Anabatic {
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactTerminal".
class AutoContactTerminal : public AutoContact {
friend class AutoContact;
public:
static AutoContactTerminal* create ( GCell* gcell
, Component* anchor
, const Layer* layer
, Point point
, DbU::Unit width
, DbU::Unit height
);
static AutoContactTerminal* create ( GCell* gcell
, Component* anchor
, const Layer* layer
, const DbU::Unit dx
, const DbU::Unit dy
, const DbU::Unit width
, const DbU::Unit height
);
protected:
// Constructors & Destructors.
AutoContactTerminal ( GCell*, Contact* );
virtual ~AutoContactTerminal ();
virtual void _invalidate ( unsigned int flags );
public:
virtual Box getNativeConstraintBox () const;
inline AutoSegment* getSegment () const;
virtual AutoSegment* getSegment ( unsigned int ) const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const;
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const;
virtual void updateGeometry ();
virtual void updateTopology ();
virtual void cacheDetach ( AutoSegment* );
virtual void cacheAttach ( AutoSegment* );
virtual void updateCache ();
virtual string _getTypeName () const;
private:
AutoContactTerminal ( const AutoContactTerminal& );
AutoContactTerminal& operator= ( const AutoContactTerminal& );
protected:
AutoSegment* _segment;
};
inline AutoSegment* AutoContactTerminal::getSegment () const { return _segment; }
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoContactTerminal);
#endif // ANABATIC_AUTOCONTACT_TERMINAL_H

View File

@ -0,0 +1,74 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoContactTurn.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOCONTACT_TURN_H
#define ANABATIC_AUTOCONTACT_TURN_H
#include "anabatic/AutoContact.h"
namespace Anabatic {
class AutoContactTerminal;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactTurn".
class AutoContactTurn : public AutoContact {
friend class AutoContact;
public:
static AutoContactTurn* create ( GCell*, Net*, const Layer* );
static void insert ( AutoContactTerminal* );
protected:
// Constructors & Destructors.
AutoContactTurn ( GCell*, Contact* );
virtual ~AutoContactTurn ();
virtual void _invalidate ( unsigned int flags );
public:
inline AutoHorizontal* getHorizontal1 () const;
inline AutoVertical* getVertical1 () const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const;
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const;
virtual AutoSegment* getSegment ( unsigned int ) const;
virtual void updateGeometry ();
virtual void updateTopology ();
virtual void cacheDetach ( AutoSegment* );
virtual void cacheAttach ( AutoSegment* );
virtual void updateCache ();
virtual string _getTypeName () const;
private:
AutoContactTurn ( const AutoContactTurn& );
AutoContactTurn& operator= ( const AutoContactTurn& );
private:
AutoHorizontal* _horizontal1;
AutoVertical* _vertical1;
};
inline AutoHorizontal* AutoContactTurn::getHorizontal1 () const { return _horizontal1; };
inline AutoVertical* AutoContactTurn::getVertical1 () const { return _vertical1; };
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoContactTurn);
#endif // ANABATIC_AUTOCONTACT_TURN_H

View File

@ -0,0 +1,73 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoContactVTee.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOCONTACT_VTEE_H
#define ANABATIC_AUTOCONTACT_VTEE_H
#include "anabatic/AutoContact.h"
namespace Anabatic {
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactVTee".
class AutoContactVTee : public AutoContact {
friend class AutoContact;
public:
static AutoContactVTee* create ( GCell*, Net*, const Layer* );
protected:
// Constructors & Destructors.
AutoContactVTee ( GCell*, Contact* );
virtual ~AutoContactVTee ();
virtual void _invalidate ( unsigned int flags );
public:
inline AutoHorizontal* getHorizontal1 () const;
inline AutoVertical* getVertical1 () const;
inline AutoVertical* getVertical2 () const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const;
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const;
virtual AutoSegment* getSegment ( unsigned int ) const;
virtual void updateGeometry ();
virtual void updateTopology ();
virtual void cacheDetach ( AutoSegment* );
virtual void cacheAttach ( AutoSegment* );
virtual void updateCache ();
virtual string _getTypeName () const;
private:
AutoContactVTee ( const AutoContactVTee& );
AutoContactVTee& operator= ( const AutoContactVTee& );
private:
AutoHorizontal* _horizontal1;
AutoVertical* _vertical1;
AutoVertical* _vertical2;
};
inline AutoHorizontal* AutoContactVTee::getHorizontal1 () const { return _horizontal1; };
inline AutoVertical* AutoContactVTee::getVertical1 () const { return _vertical1; };
inline AutoVertical* AutoContactVTee::getVertical2 () const { return _vertical2; };
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoContactVTee);
#endif // ANABATIC_AUTOCONTACT_VTEE_H

View File

@ -0,0 +1,96 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2013, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoHorizontal.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOHORIZONTAL_H
#define ANABATIC_AUTOHORIZONTAL_H
#include "hurricane/Horizontal.h"
#include "anabatic/AutoSegment.h"
namespace Anabatic {
// -------------------------------------------------------------------
// Class : "AutoHorizontal".
class AutoHorizontal : public AutoSegment {
friend class AutoSegment;
public:
// Predicates.
virtual bool _canSlacken () const;
virtual bool canMoveULeft ( float reserve=0.0 ) const;
virtual bool canMoveURight ( float reserve=0.0 ) const;
// Accessors.
virtual Segment* base ();
virtual Segment* base () const;
virtual Horizontal* getHorizontal ();
virtual DbU::Unit getSourceU () const;
virtual DbU::Unit getTargetU () const;
virtual DbU::Unit getDuSource () const;
virtual DbU::Unit getDuTarget () const;
virtual Interval getSpanU () const;
virtual bool getConstraints ( DbU::Unit& min , DbU::Unit& max ) const;
virtual Interval getSourceConstraints ( unsigned int flags=0 ) const;
virtual Interval getTargetConstraints ( unsigned int flags=0 ) const;
virtual unsigned int getDirection () const;
virtual size_t getGCells ( vector<GCell*>& ) const;
// Modifiers.
virtual void setDuSource ( DbU::Unit );
virtual void setDuTarget ( DbU::Unit );
virtual void _setAxis ( DbU::Unit );
virtual void updateOrient ();
virtual void updatePositions ();
virtual void updateNativeConstraints ();
virtual bool checkPositions () const;
virtual bool checkConstraints () const;
virtual unsigned int _makeDogleg ( GCell*, unsigned int flags );
virtual bool moveULeft ();
virtual bool moveURight ();
virtual bool _slacken ( unsigned int flags );
#if THIS_IS_DISABLED
virtual void desalignate ( AutoContact* );
#endif
// Inspector Management.
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
// Internal: Attributes.
protected:
Horizontal* _horizontal;
// Internal: Constructors.
protected:
AutoHorizontal ( Horizontal* );
virtual ~AutoHorizontal ();
virtual void _postCreate ();
virtual void _preDestroy ();
private:
AutoHorizontal ( const AutoHorizontal& );
AutoHorizontal& operator= ( const AutoHorizontal& );
};
} // End of Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoHorizontal);
#endif // ANABATIC_AUTOHORIZONTAL_H

View File

@ -0,0 +1,586 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoSegment.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOSEGMENT_H
#define ANABATIC_AUTOSEGMENT_H
#include <set>
#include <iostream>
#include <functional>
#include "hurricane/Interval.h"
#include "hurricane/Segment.h"
#include "hurricane/Components.h"
#include "hurricane/Contact.h"
namespace Hurricane {
class Layer;
class Horizontal;
class Vertical;
class Cell;
}
#include "crlcore/RoutingGauge.h"
#include "anabatic/Constants.h"
#include "anabatic/GCell.h"
#include "anabatic/AutoSegments.h"
#include "anabatic/Session.h"
namespace Anabatic {
using std::set;
using std::cerr;
using std::endl;
using std::binary_function;
using Hurricane::StaticObservable;
using Hurricane::BaseObserver;
using Hurricane::tab;
using Hurricane::Interval;
using Hurricane::Layer;
using Hurricane::Components;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::Cell;
using CRL::RoutingGauge;
class AutoHorizontal;
class AutoVertical;
// -------------------------------------------------------------------
// Class : "AutoSegment".
enum AutoSegmentFlag { SegNoFlags = 0x0
, SegHorizontal = (1<< 0)
, SegFixed = (1<< 1)
, SegGlobal = (1<< 2)
, SegWeakGlobal = (1<< 3)
, SegCanonical = (1<< 4)
, SegBipoint = (1<< 5)
, SegDogleg = (1<< 6)
, SegStrap = (1<< 7)
, SegSourceTop = (1<< 8)
, SegSourceBottom = (1<< 9)
, SegTargetTop = (1<<10)
, SegTargetBottom = (1<<11)
, SegIsReduced = (1<<12)
, SegLayerChange = (1<<13)
, SegSourceTerminal = (1<<14) // Replace Terminal.
, SegTargetTerminal = (1<<15) // Replace Terminal.
, SegStrongTerminal = SegSourceTerminal|SegTargetTerminal
, SegWeakTerminal1 = (1<<16) // Replace TopologicalEnd.
, SegWeakTerminal2 = (1<<17) // Replace TopologicalEnd.
, SegNotSourceAligned = (1<<18)
, SegNotTargetAligned = (1<<19)
, SegUnbound = (1<<20)
, SegHalfSlackened = (1<<21)
, SegSlackened = (1<<22)
, SegAxisSet = (1<<23)
, SegInvalidated = (1<<24)
, SegInvalidatedSource = (1<<25)
, SegInvalidatedTarget = (1<<26)
, SegInvalidatedLayer = (1<<27)
, SegCreated = (1<<28)
, SegUserDefined = (1<<29)
// Masks.
, SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2
, SegNotAligned = SegNotSourceAligned|SegNotTargetAligned
, SegSpinTop = SegSourceTop |SegTargetTop
, SegSpinBottom = SegSourceBottom |SegTargetBottom
, SegDepthSpin = SegSpinTop |SegSpinBottom
};
class AutoSegment {
friend class AutoHorizontal;
friend class AutoVertical;
public:
class Observable : public StaticObservable<1> {
public:
enum Indexes { TrackSegment = 0
};
public:
inline Observable ();
private:
Observable ( const StaticObservable& );
Observable& operator= ( const StaticObservable& );
};
public:
enum ObserverFlag { Create = 0x000000001
, Destroy = 0x000000002
, Invalidate = 0x000000004
, Revalidate = 0x000000008
, RevalidatePPitch = 0x000000010
};
public:
typedef std::function< void(AutoSegment*) > RevalidateCb_t;
public:
static void setDestroyMode ( bool );
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Segment* hurricaneSegment
);
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, unsigned int dir
, size_t depth=RoutingGauge::nlayerdepth
);
void destroy ();
// Wrapped Segment Functions.
virtual Segment* base () const = 0;
virtual Segment* base () = 0;
virtual Horizontal* getHorizontal () { return NULL; };
virtual Vertical* getVertical () { return NULL; };
inline Cell* getCell () const;
inline Net* getNet () const;
inline const Layer* getLayer () const;
inline Box getBoundingBox () const;
inline Hook* getSourceHook ();
inline Hook* getTargetHook ();
inline Contact* getSource () const;
inline Contact* getTarget () const;
inline Component* getOppositeAnchor ( Component* ) const;
inline Components getAnchors () const;
virtual DbU::Unit getX () const;
virtual DbU::Unit getY () const;
inline DbU::Unit getWidth () const;
inline DbU::Unit getLength () const;
inline DbU::Unit getSourcePosition () const;
inline DbU::Unit getTargetPosition () const;
inline DbU::Unit getSourceX () const;
inline DbU::Unit getSourceY () const;
inline DbU::Unit getTargetX () const;
inline DbU::Unit getTargetY () const;
inline void invert ();
inline void setLayer ( const Layer* );
// Predicates.
inline bool isHorizontal () const;
inline bool isVertical () const;
inline bool isGlobal () const;
inline bool isWeakGlobal () const;
inline bool isLocal () const;
inline bool isFixed () const;
inline bool isBipoint () const;
inline bool isWeakTerminal () const;
inline bool isWeakTerminal1 () const;
inline bool isWeakTerminal2 () const;
inline bool isTerminal () const;
inline bool isNotSourceAligned () const;
inline bool isNotTargetAligned () const;
inline bool isNotAligned () const;
bool isStrongTerminal ( unsigned int flags=0 ) const;
inline bool isSourceTerminal () const;
inline bool isTargetTerminal () const;
inline bool isLayerChange () const;
inline bool isSpinTop () const;
inline bool isSpinBottom () const;
inline bool isSpinTopOrBottom () const;
inline bool isReduced () const;
inline bool isStrap () const;
inline bool isDogleg () const;
inline bool isUnbound () const;
inline bool isInvalidated () const;
inline bool isInvalidatedLayer () const;
inline bool isCreated () const;
inline bool isCanonical () const;
inline bool isUnsetAxis () const;
inline bool isSlackened () const;
inline bool isUserDefined () const;
bool isReduceCandidate () const;
bool isUTurn () const;
virtual bool _canSlacken () const = 0;
bool canReduce () const;
bool mustRaise () const;
unsigned int canDogleg ( Interval );
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0;
virtual bool canMoveURight ( float reserve=0.0 ) const = 0;
bool canMoveUp ( float reserve=0.0, unsigned int flags=0 ) const;
bool canPivotUp ( float reserve=0.0, unsigned int flags=0 ) const;
bool canPivotDown ( float reserve=0.0, unsigned int flags=0 ) const;
bool canSlacken ( unsigned int flags=0 ) const;
virtual bool checkPositions () const = 0;
virtual bool checkConstraints () const = 0;
bool checkDepthSpin () const;
// Accessors.
inline unsigned long getId () const;
inline unsigned int getFlags () const;
virtual unsigned int getDirection () const = 0;
inline GCell* getGCell () const;
virtual size_t getGCells ( vector<GCell*>& ) const = 0;
inline AutoContact* getAutoSource () const;
inline AutoContact* getAutoTarget () const;
AutoContact* getOppositeAnchor ( AutoContact* ) const;
size_t getPerpandicularsBound ( set<AutoSegment*>& );
inline AutoSegment* getParent () const;
inline unsigned int getDepth () const;
inline DbU::Unit getPitch () const;
DbU::Unit getPPitch () const;
inline DbU::Unit getAxis () const;
virtual DbU::Unit getSourceU () const = 0;
virtual DbU::Unit getTargetU () const = 0;
virtual DbU::Unit getDuSource () const = 0;
virtual DbU::Unit getDuTarget () const = 0;
inline DbU::Unit getOrigin () const;
inline DbU::Unit getExtremity () const;
virtual Interval getSpanU () const = 0;
Interval getMinSpanU () const;
virtual Interval getSourceConstraints ( unsigned int flags=0 ) const = 0;
virtual Interval getTargetConstraints ( unsigned int flags=0 ) const = 0;
virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0;
inline bool getConstraints ( Interval& i ) const;
inline const Interval& getUserConstraints () const;
inline const Interval& getNativeConstraints () const;
virtual DbU::Unit getSlack () const;
inline DbU::Unit getOptimalMin () const;
inline DbU::Unit getOptimalMax () const;
inline DbU::Unit getNativeMin () const;
inline DbU::Unit getNativeMax () const;
Interval& getOptimal ( Interval& i ) const;
virtual DbU::Unit getCost ( DbU::Unit axis ) const;
virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max );
inline AutoSegment* getCanonical ( Interval& i );
float getMaxUnderDensity ( unsigned int flags );
// Modifiers.
inline void unsetFlags ( unsigned int );
inline void setFlags ( unsigned int );
void setFlagsOnAligneds ( unsigned int );
inline void incReduceds ();
inline void decReduceds ();
virtual void setDuSource ( DbU::Unit du ) = 0;
virtual void setDuTarget ( DbU::Unit du ) = 0;
void computeTerminal ();
virtual void updateOrient () = 0;
virtual void updatePositions () = 0;
virtual void updateNativeConstraints () = 0;
void updateSourceSpin ();
void updateTargetSpin ();
void sourceDetach ();
void targetDetach ();
void sourceAttach ( AutoContact* );
void targetAttach ( AutoContact* );
//inline void mergeUserConstraints ( const Interval& );
void mergeUserConstraints ( const Interval& );
inline void resetUserConstraints ();
inline void setOptimalMin ( DbU::Unit min );
inline void setOptimalMax ( DbU::Unit max );
inline void mergeNativeMin ( DbU::Unit min );
inline void mergeNativeMax ( DbU::Unit max );
inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max );
bool checkNotInvalidated () const;
inline void setParent ( AutoSegment* );
void revalidate ();
AutoSegment* makeDogleg ( AutoContact* );
unsigned int makeDogleg ( Interval, unsigned int flags=Flags::NoFlags );
unsigned int makeDogleg ( GCell*, unsigned int flags=Flags::NoFlags );
virtual unsigned int _makeDogleg ( GCell*, unsigned int flags ) = 0;
virtual bool moveULeft () = 0;
virtual bool moveURight () = 0;
bool slacken ( unsigned int flags );
virtual bool _slacken ( unsigned int flags ) = 0;
void _changeDepth ( unsigned int depth, unsigned int flags );
void changeDepth ( unsigned int depth, unsigned int flags );
bool moveUp ( unsigned int flags=Flags::NoFlags );
bool moveDown ( unsigned int flags=Flags::NoFlags );
bool reduceDoglegLayer ();
bool reduce ();
bool raise ();
// Canonical Modifiers.
AutoSegment* canonize ( unsigned int flags=Flags::NoFlags );
virtual void invalidate ( unsigned int flags=Flags::Propagate );
void invalidate ( AutoContact* );
void computeOptimal ( set<AutoSegment*>& processeds );
void setAxis ( DbU::Unit, unsigned int flags=Flags::NoFlags );
bool toConstraintAxis ( unsigned int flags=Flags::Realignate );
bool toOptimalAxis ( unsigned int flags=Flags::Realignate );
// Collections & Filters.
AutoSegments getOnSourceContact ( unsigned int direction );
AutoSegments getOnTargetContact ( unsigned int direction );
AutoSegments getCachedOnSourceContact ( unsigned int direction );
AutoSegments getCachedOnTargetContact ( unsigned int direction );
AutoSegments getAligneds ( unsigned int flags=Flags::NoFlags );
AutoSegments getPerpandiculars ();
size_t getAlignedContacts ( map<AutoContact*,int>& ) const ;
// Observers.
template< typename OwnerT >
inline OwnerT* getObserver ( size_t slot );
inline void setObserver ( size_t slot, BaseObserver* );
inline void notify ( unsigned int flags );
// Inspector Management.
virtual Record* _getRecord () const = 0;
virtual string _getString () const = 0;
virtual string _getTypeName () const = 0;
// Non-reviewed atomic modifiers.
bool _check () const;
#if THIS_IS_DISABLED
virtual void desalignate ( AutoContact* ) = 0;
bool shearUp ( GCell*
, AutoSegment*& movedUp
, float reserve
, unsigned int flags );
#endif
protected:
// Internal: Static Attributes.
static size_t _allocateds;
static size_t _globalsCount;
static bool _destroyBase;
static bool _destroyTool;
static unsigned long _maxId;
// Internal: Attributes.
const unsigned long _id;
GCell* _gcell;
unsigned int _flags;
unsigned int _depth : 8;
unsigned int _optimalMin : 8;
unsigned int _optimalMax : 8;
unsigned int _reduceds : 2;
DbU::Unit _sourcePosition;
DbU::Unit _targetPosition;
Interval _userConstraints;
Interval _nativeConstraints;
AutoSegment* _parent;
Observable _observers;
// Internal: Constructors & Destructors.
protected:
AutoSegment ( Segment* segment );
virtual ~AutoSegment ();
static void _preCreate ( AutoContact* source, AutoContact* target );
virtual void _postCreate ();
virtual void _preDestroy ();
private:
AutoSegment ( const AutoSegment& );
AutoSegment& operator= ( const AutoSegment& );
protected:
void _invalidate ();
inline unsigned int _getFlags () const;
std::string _getStringFlags () const;
virtual void _setAxis ( DbU::Unit ) = 0;
public:
struct CompareId : public binary_function<AutoSegment*,AutoSegment*,bool> {
inline bool operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const;
};
public:
struct CompareByDepthLength : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
struct CompareByDepthAxis : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
// Static Utilities.
public:
static inline bool areAlignedsAndDiffLayer ( AutoSegment*, AutoSegment* );
static bool isTopologicalBound ( AutoSegment* seed, unsigned int flags );
static inline bool arePerpandiculars ( AutoSegment* a, AutoSegment* b );
static inline bool arePerpandiculars ( bool isHorizontalA, AutoSegment* b );
static inline bool areAligneds ( AutoSegment* a, AutoSegment* b );
static unsigned int getPerpandicularState ( AutoContact* contact
, AutoSegment* source
, AutoSegment* current
, bool isHorizontalMaster
, const Layer* masterLayer=NULL
);
static inline unsigned int getPerpandicularState ( AutoContact* contact
, AutoSegment* source
, AutoSegment* current
, AutoSegment* master
);
static void getTopologicalInfos ( AutoSegment* seed
, vector<AutoSegment*>& collapseds
, vector<AutoSegment*>& perpandiculars
, DbU::Unit& leftBound
, DbU::Unit& rightBound
);
static int getTerminalCount ( AutoSegment* seed
, vector<AutoSegment*>& collapseds
);
static inline int getTerminalCount ( AutoSegment* seed );
static inline size_t getGlobalsCount ();
static inline size_t getAllocateds ();
static inline unsigned long getMaxId ();
};
// Inline Functions.
inline unsigned long AutoSegment::getId () const { return _id; }
inline Cell* AutoSegment::getCell () const { return base()->getCell(); }
inline Net* AutoSegment::getNet () const { return base()->getNet(); }
inline const Layer* AutoSegment::getLayer () const { return base()->getLayer(); }
inline Box AutoSegment::getBoundingBox () const { return base()->getBoundingBox(); }
inline Hook* AutoSegment::getSourceHook () { return base()->getSourceHook(); }
inline Hook* AutoSegment::getTargetHook () { return base()->getTargetHook(); }
inline Contact* AutoSegment::getSource () const { return static_cast<Contact*>(base()->getSource()); }
inline Contact* AutoSegment::getTarget () const { return static_cast<Contact*>(base()->getTarget()); }
inline Component* AutoSegment::getOppositeAnchor ( Component* anchor ) const { return base()->getOppositeAnchor(anchor); };
inline AutoSegment* AutoSegment::getParent () const { return _parent; }
inline DbU::Unit AutoSegment::getSourcePosition () const { return _sourcePosition; }
inline DbU::Unit AutoSegment::getTargetPosition () const { return _targetPosition; }
inline DbU::Unit AutoSegment::getSourceX () const { return base()->getSourceX(); }
inline DbU::Unit AutoSegment::getSourceY () const { return base()->getSourceY(); }
inline DbU::Unit AutoSegment::getTargetX () const { return base()->getTargetX(); }
inline DbU::Unit AutoSegment::getTargetY () const { return base()->getTargetY(); }
inline DbU::Unit AutoSegment::getWidth () const { return base()->getWidth(); }
inline DbU::Unit AutoSegment::getLength () const { return base()->getLength(); }
inline void AutoSegment::invert () { base()->invert(); }
inline GCell* AutoSegment::getGCell () const { return _gcell; }
inline AutoContact* AutoSegment::getAutoSource () const { return Session::lookup(getSource()); }
inline AutoContact* AutoSegment::getAutoTarget () const { return Session::lookup(getTarget()); }
inline bool AutoSegment::getConstraints ( Interval& i ) const { return getConstraints(i.getVMin(),i.getVMax()); }
inline AutoSegment* AutoSegment::getCanonical ( Interval& i ) { return getCanonical(i.getVMin(),i.getVMax()); }
inline unsigned int AutoSegment::getDepth () const { return _depth; }
inline DbU::Unit AutoSegment::getPitch () const { return Session::getPitch(getDepth(),Flags::NoFlags); }
inline DbU::Unit AutoSegment::getAxis () const { return isHorizontal()?base()->getY():base()->getX(); }
inline DbU::Unit AutoSegment::getOrigin () const { return isHorizontal()?_gcell->getYMin():_gcell->getXMin(); }
inline DbU::Unit AutoSegment::getExtremity () const { return isHorizontal()?_gcell->getYMax():_gcell->getXMax(); }
inline DbU::Unit AutoSegment::getOptimalMin () const { return DbU::lambda(_optimalMin) + getOrigin(); }
inline DbU::Unit AutoSegment::getOptimalMax () const { return DbU::lambda(_optimalMax) + getOrigin(); }
inline DbU::Unit AutoSegment::getNativeMin () const { return _nativeConstraints.getVMin(); }
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; }
inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; }
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }
inline bool AutoSegment::isFixed () const { return _flags & SegFixed; }
inline bool AutoSegment::isGlobal () const { return _flags & SegGlobal; }
inline bool AutoSegment::isWeakGlobal () const { return _flags & SegWeakGlobal; }
inline bool AutoSegment::isLocal () const { return not (_flags & SegGlobal); }
inline bool AutoSegment::isBipoint () const { return _flags & SegBipoint; }
inline bool AutoSegment::isWeakTerminal () const { return _flags & SegWeakTerminal; }
inline bool AutoSegment::isWeakTerminal1 () const { return _flags & SegWeakTerminal1; }
inline bool AutoSegment::isWeakTerminal2 () const { return _flags & SegWeakTerminal2; }
inline bool AutoSegment::isSourceTerminal () const { return _flags & SegSourceTerminal; }
inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; }
inline bool AutoSegment::isTerminal () const { return _flags & SegStrongTerminal; }
inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; }
inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; }
inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; }
inline bool AutoSegment::isDogleg () const { return _flags & SegDogleg ; }
inline bool AutoSegment::isUnbound () const { return _flags & SegUnbound ; }
inline bool AutoSegment::isStrap () const { return _flags & SegStrap; }
inline bool AutoSegment::isLayerChange () const { return _flags & SegLayerChange; }
inline bool AutoSegment::isSpinTop () const { return ((_flags & SegSpinTop ) == SegSpinTop); }
inline bool AutoSegment::isSpinBottom () const { return ((_flags & SegSpinBottom) == SegSpinBottom); }
inline bool AutoSegment::isSpinTopOrBottom () const { return isSpinTop() or isSpinBottom(); }
inline bool AutoSegment::isReduced () const { return _flags & SegIsReduced; }
inline bool AutoSegment::isSlackened () const { return _flags & SegSlackened; }
inline bool AutoSegment::isCanonical () const { return _flags & SegCanonical; }
inline bool AutoSegment::isUnsetAxis () const { return not (_flags & SegAxisSet); }
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; }
inline unsigned int AutoSegment::getFlags () const { return _flags; }
inline unsigned int AutoSegment::_getFlags () const { return _flags; }
inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; }
inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; }
inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); }
inline void AutoSegment::setOptimalMin ( DbU::Unit min ) { _optimalMin = (unsigned int)DbU::getLambda(min-getOrigin()); }
inline void AutoSegment::setOptimalMax ( DbU::Unit max ) { _optimalMax = (unsigned int)DbU::getLambda(max-getOrigin()); }
inline void AutoSegment::mergeNativeMin ( DbU::Unit min ) { _nativeConstraints.getVMin() = std::max( min, _nativeConstraints.getVMin() ); }
inline void AutoSegment::mergeNativeMax ( DbU::Unit max ) { _nativeConstraints.getVMax() = std::min( max, _nativeConstraints.getVMax() ); }
inline void AutoSegment::resetNativeConstraints ( DbU::Unit min, DbU::Unit max ) { _nativeConstraints = Interval( min, max ); }
//inline void AutoSegment::mergeUserConstraints ( const Interval& constraints ) { _userConstraints.intersection(constraints); }
inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); }
inline void AutoSegment::setParent ( AutoSegment* parent )
{
if ( parent == this ) {
cerr << "Parentage Looping: " << parent->_getString() << endl;
}
_parent = parent;
}
inline bool AutoSegment::CompareId::operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const
{ return lhs->getId() < rhs->getId(); }
inline unsigned long AutoSegment::getMaxId ()
{ return _maxId; }
inline bool AutoSegment::areAlignedsAndDiffLayer ( AutoSegment* s1, AutoSegment* s2 )
{ return s1 and s2
and (s1->isHorizontal() == s2->isHorizontal())
and (s1->getLayer() != s2->getLayer()); }
inline bool AutoSegment::arePerpandiculars ( AutoSegment* a, AutoSegment* b )
{ return a and b and (a->isHorizontal() != b->isHorizontal()); }
inline bool AutoSegment::arePerpandiculars ( bool isHorizontalA, AutoSegment* b )
{ return b and (isHorizontalA != b->isHorizontal()); }
inline bool AutoSegment::areAligneds ( AutoSegment* a, AutoSegment* b )
{ return a and b and (a->isHorizontal() == b->isHorizontal()); }
inline unsigned int AutoSegment::getPerpandicularState ( AutoContact* contact
, AutoSegment* source
, AutoSegment* current
, AutoSegment* master )
{
return getPerpandicularState ( contact, source, current, master->isHorizontal(), master->getLayer() );
}
inline int AutoSegment::getTerminalCount ( AutoSegment* seed )
{
cdebug_log(145,0) << "getTerminalCount() - " << seed << endl;
vector<AutoSegment*> collapseds;
vector<AutoSegment*> perpandiculars;
DbU::Unit leftBound;
DbU::Unit rightBound;
getTopologicalInfos ( seed
, collapseds
, perpandiculars
, leftBound
, rightBound
);
return getTerminalCount ( seed, collapseds );
}
inline size_t AutoSegment::getGlobalsCount () { return _globalsCount; }
inline size_t AutoSegment::getAllocateds () { return _allocateds; }
inline void AutoSegment::setObserver ( size_t slot, BaseObserver* observer )
{ _observers.setObserver( slot, observer ); }
template<typename OwnerT>
inline OwnerT* AutoSegment::getObserver ( size_t slot )
{ return _observers.getObserver<OwnerT>(slot); }
inline void AutoSegment::notify ( unsigned int flags )
{ _observers.notify( flags ); }
inline AutoSegment::Observable::Observable () : StaticObservable<1>() { }
} // End of Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoSegment);
# endif // ANABATIC_AUTOSEGMENT_H

View File

@ -0,0 +1,446 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoSegments.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOSEGMENTS_H
#define ANABATIC_AUTOSEGMENTS_H
#include <string>
#include <list>
#include <vector>
#include <map>
#include "hurricane/Collection.h"
#include "hurricane/DbU.h"
#include "hurricane/Box.h"
namespace Hurricane {
class Hook;
class Component;
class Contact;
class Segment;
class Net;
}
namespace Anabatic {
using std::string;
using std::pair;
using std::list;
using std::vector;
using std::map;
using Hurricane::Record;
using Hurricane::DbU;
using Hurricane::Box;
using Hurricane::Hook;
using Hurricane::Component;
using Hurricane::Contact;
using Hurricane::Segment;
using Hurricane::Net;
using Hurricane::Filter;
using Hurricane::Locator;
using Hurricane::Collection;
using Hurricane::GenericFilter;
using Hurricane::GenericLocator;
using Hurricane::GenericCollection;
class LocatorHelper;
class AutoContact;
class AutoSegment;
class GCell;
// -------------------------------------------------------------------
// Collections.
typedef Hurricane::Filter<AutoSegment*> AutoSegmentHF;
typedef Hurricane::Locator<AutoSegment*> AutoSegmentHL;
typedef Hurricane::Collection<AutoSegment*> AutoSegmentHC;
typedef GenericCollection<AutoSegment*> AutoSegments;
typedef GenericLocator<AutoSegment*> AutoSegmentLocator;
typedef GenericFilter<AutoSegment*> AutoSegmentFilter;
typedef map<Segment*,AutoSegment*> AutoSegmentLut;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegmentStack".
class AutoSegmentStack : protected list<pair<AutoContact*,AutoSegment*> > {
public:
inline bool isEmpty () const;
inline size_t getSize () const;
void push ( AutoContact*, AutoSegment* );
inline void pop ();
inline AutoContact* getAutoContact () const;
inline AutoSegment* getAutoSegment () const;
};
inline bool AutoSegmentStack::isEmpty () const { return empty(); };
inline size_t AutoSegmentStack::getSize () const { return size(); };
inline void AutoSegmentStack::pop () { if ( !empty() ) pop_back(); };
inline AutoContact* AutoSegmentStack::getAutoContact () const { return empty() ? NULL : back().first; };
inline AutoSegment* AutoSegmentStack::getAutoSegment () const { return empty() ? NULL : back().second; };
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegments_OnContact".
class AutoSegments_OnContact : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
Locator ( AutoSegment* master, Contact* contact );
inline Locator ( const Locator& );
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
AutoSegment* _master;
Hook* _hook;
AutoSegment* _element;
};
public:
// AutoSegments_OnContact Methods.
inline AutoSegments_OnContact ( AutoSegment* master, Contact* contact );
inline AutoSegments_OnContact ( const AutoSegments_OnContact& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
protected:
// AutoSegments_OnContact Attributes.
AutoSegment* _master;
Contact* _contact;
};
inline AutoSegments_OnContact::Locator::Locator ( const Locator &locator )
: AutoSegmentHL()
, _master(locator._master)
, _hook(locator._hook)
, _element(locator._element)
{ }
inline AutoSegments_OnContact::AutoSegments_OnContact ( AutoSegment* master, Contact* contact )
: AutoSegmentHC()
, _master(master)
, _contact(contact)
{ }
inline AutoSegments_OnContact::AutoSegments_OnContact ( const AutoSegments_OnContact& segments )
: AutoSegmentHC()
, _master(segments._master)
, _contact(segments._contact)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_Aligneds".
class AutoSegments_Aligneds : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
inline Locator ( AutoSegment* segment , unsigned int flags );
inline Locator ( const Locator &locator );
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
unsigned int _flags;
AutoSegment* _master;
AutoSegmentStack _stack;
};
public:
// AutoSegments_Aligneds Methods.
AutoSegments_Aligneds ( AutoSegment*, unsigned int flags=Flags::NoFlags );
AutoSegments_Aligneds ( const AutoSegments_Aligneds& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
protected:
// AutoSegments_Aligneds Attributes.
unsigned int _flags;
AutoSegment* _segment;
};
inline AutoSegments_Aligneds::Locator::Locator ( const Locator &locator )
: AutoSegmentHL()
, _flags (locator._flags)
, _master(locator._master)
, _stack (locator._stack)
{ }
inline AutoSegments_Aligneds::AutoSegments_Aligneds ( AutoSegment* segment, unsigned int flags )
: AutoSegmentHC()
, _flags (flags)
, _segment(segment)
{ }
inline AutoSegments_Aligneds::AutoSegments_Aligneds ( const AutoSegments_Aligneds& autosegments )
: AutoSegmentHC()
, _flags (autosegments._flags)
, _segment(autosegments._segment)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_Perpandiculars".
class AutoSegments_Perpandiculars : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
Locator ( AutoSegment* master );
inline Locator ( const Locator& );
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
unsigned int _flags;
AutoSegment* _master;
AutoSegmentStack _stack;
vector<AutoSegment*> _perpandiculars;
};
public:
// AutoSegments_Perpandiculars Methods.
inline AutoSegments_Perpandiculars ( AutoSegment* master );
inline AutoSegments_Perpandiculars ( const AutoSegments_Perpandiculars& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
protected:
// AutoSegments_Perpandiculars Attributes.
AutoSegment* _segment;
};
inline AutoSegments_Perpandiculars::Locator::Locator ( const Locator& locator )
: AutoSegmentHL()
, _flags (locator._flags)
, _master (locator._master)
, _stack (locator._stack)
, _perpandiculars()
{ }
inline AutoSegments_Perpandiculars::AutoSegments_Perpandiculars
( AutoSegment* segment )
: AutoSegmentHC()
, _segment(segment)
{ }
inline AutoSegments_Perpandiculars::AutoSegments_Perpandiculars
( const AutoSegments_Perpandiculars& autosegments )
: AutoSegmentHC()
, _segment(autosegments._segment)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_AnchorOnGCell".
class AutoSegments_AnchorOnGCell : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
Locator ( GCell* fcell, unsigned int flags );
inline Locator ( const Locator& );
virtual ~Locator ();
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
unsigned int _flags;
vector<AutoContact*>::const_iterator _itContact;
vector<AutoContact*>::const_iterator _itEnd;
Hurricane::Locator<Hook*>* _hookLocator;
AutoSegment* _element;
};
public:
// AutoSegments_Perpandiculars Methods.
inline AutoSegments_AnchorOnGCell ( GCell* fcell, unsigned int flags );
inline AutoSegments_AnchorOnGCell ( const AutoSegments_AnchorOnGCell& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
public:
// AutoSegments_Perpandiculars Attributes.
GCell* _fcell;
unsigned int _flags;
};
inline AutoSegments_AnchorOnGCell::Locator::Locator ( const Locator &locator )
: AutoSegmentHL()
, _flags (locator._flags)
, _itContact (locator._itContact)
, _itEnd (locator._itEnd)
, _hookLocator (locator._hookLocator->getClone())
, _element (locator._element)
{ }
inline AutoSegments_AnchorOnGCell::AutoSegments_AnchorOnGCell ( GCell* fcell, unsigned int flags )
: AutoSegmentHC()
, _fcell(fcell)
, _flags(flags)
{ }
inline AutoSegments_AnchorOnGCell::AutoSegments_AnchorOnGCell
( const AutoSegments_AnchorOnGCell& autosegments )
: AutoSegmentHC()
, _fcell(autosegments._fcell)
, _flags(autosegments._flags)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_CachedOnContact".
class AutoSegments_CachedOnContact : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
Locator ( AutoContact* sourceAnchor, unsigned int direction );
inline Locator ( const Locator& );
virtual ~Locator ();
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
LocatorHelper* _helper;
};
// Constructors.
public:
// AutoSegments_CachedOnContact Methods.
inline AutoSegments_CachedOnContact ( AutoContact* sourceContact
, unsigned int direction=Flags::Horizontal|Flags::Vertical );
inline AutoSegments_CachedOnContact ( const AutoSegments_CachedOnContact& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
protected:
// AutoSegments_CachedOnContact Attributes.
unsigned int _direction;
AutoContact* _sourceContact;
};
inline AutoSegments_CachedOnContact::Locator::Locator ( const Locator &locator )
: AutoSegmentHL()
, _helper(locator._helper)
{ }
inline AutoSegments_CachedOnContact::AutoSegments_CachedOnContact
( AutoContact* sourceContact, unsigned int direction )
: AutoSegmentHC()
, _direction (direction)
, _sourceContact(sourceContact)
{
if (_direction & Flags::Vertical) _direction |= Flags::WithPerpands;
}
inline AutoSegments_CachedOnContact::AutoSegments_CachedOnContact
( const AutoSegments_CachedOnContact& autosegments )
: AutoSegmentHC()
, _direction (autosegments._direction)
, _sourceContact(autosegments._sourceContact)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_IsAccountable".
class AutoSegments_IsAccountable : public AutoSegmentHF {
public:
virtual AutoSegmentHF* getClone () const;
virtual bool accept ( AutoSegment* ) const;
virtual string _getString () const;
};
// -------------------------------------------------------------------
// Class : "AutoSegments_InDirection".
class AutoSegments_InDirection : public AutoSegmentHF {
public:
inline AutoSegments_InDirection ( unsigned int direction );
inline AutoSegments_InDirection ( const AutoSegments_InDirection& );
virtual AutoSegmentHF* getClone () const;
virtual bool accept ( AutoSegment* segment ) const;
virtual string _getString () const;
protected:
unsigned int _direction;
};
inline AutoSegments_InDirection::AutoSegments_InDirection ( unsigned int direction )
: AutoSegmentHF()
, _direction(direction)
{}
inline AutoSegments_InDirection::AutoSegments_InDirection ( const AutoSegments_InDirection& filter )
: AutoSegmentHF()
, _direction(filter._direction)
{}
} // End of Anabatic namespace.
# endif

View File

@ -0,0 +1,97 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2013, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoVertical.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOVERTICAL_H
#define ANABATIC_AUTOVERTICAL_H
#include "hurricane/Vertical.h"
#include "anabatic/AutoSegment.h"
namespace Anabatic {
// -------------------------------------------------------------------
// Class : "AutoVertical".
class AutoVertical : public AutoSegment {
friend class AutoSegment;
public:
// Predicates.
virtual bool _canSlacken () const;
virtual bool canMoveULeft ( float reserve=0.0 ) const;
virtual bool canMoveURight ( float reserve=0.0 ) const;
// Accessors.
virtual Segment* base ();
virtual Segment* base () const;
virtual Vertical* getVertical ();
virtual DbU::Unit getSourceU () const;
virtual DbU::Unit getTargetU () const;
virtual DbU::Unit getDuSource () const;
virtual DbU::Unit getDuTarget () const;
virtual Interval getSpanU () const;
virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const;
virtual Interval getSourceConstraints ( unsigned int flags=0 ) const;
virtual Interval getTargetConstraints ( unsigned int flags=0 ) const;
virtual unsigned int getDirection () const;
virtual size_t getGCells ( vector<GCell*>& ) const;
// Modifiers.
virtual void setDuSource ( DbU::Unit );
virtual void setDuTarget ( DbU::Unit );
virtual void _setAxis ( DbU::Unit );
virtual void updateOrient ();
virtual void updatePositions ();
virtual void updateNativeConstraints ();
virtual bool checkPositions () const;
virtual bool checkConstraints () const;
virtual unsigned int _makeDogleg ( GCell*, unsigned int flags );
virtual bool moveULeft ();
virtual bool moveURight ();
virtual bool _slacken ( unsigned int flags );
#if THIS_IS_DISABLED
virtual void desalignate ( AutoContact* );
#endif
// Inspector Management.
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
protected:
// Internal: Attributes.
Vertical* _vertical;
// Constructors.
protected:
AutoVertical ( Vertical* );
virtual ~AutoVertical ();
virtual void _postCreate ();
virtual void _preDestroy ();
private:
AutoVertical ( const AutoVertical& );
AutoVertical& operator= ( const AutoVertical& );
};
} // End of Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoVertical);
#endif // ANABATIC_AUTOHORIZONTAL_H

View File

@ -83,7 +83,13 @@ namespace Anabatic {
virtual DbU::Unit getWireWidth ( const Layer* ) const = 0;
virtual DbU::Unit getExtensionCap ( const Layer* ) const = 0;
virtual Flags getDirection ( const Layer* ) const = 0;
virtual float getSaturateRatio () const = 0;
virtual size_t getSaturateRp () const = 0;
virtual DbU::Unit getGlobalThreshold () const = 0;
virtual void setAllowedDepth ( size_t ) = 0;
virtual void setSaturateRatio ( float ) = 0;
virtual void setSaturateRp ( size_t ) = 0;
virtual void setGlobalThreshold ( DbU::Unit ) = 0;
virtual DbU::Unit getEdgeLength () const = 0;
virtual DbU::Unit getEdgeWidth () const = 0;
virtual float getEdgeCostH () const = 0;
@ -140,7 +146,13 @@ namespace Anabatic {
virtual DbU::Unit getWireWidth ( const Layer* ) const;
virtual DbU::Unit getExtensionCap ( const Layer* ) const;
virtual Flags getDirection ( const Layer* ) const;
virtual float getSaturateRatio () const;
virtual size_t getSaturateRp () const;
virtual DbU::Unit getGlobalThreshold () const;
virtual void setAllowedDepth ( size_t );
virtual void setSaturateRatio ( float );
virtual void setSaturateRp ( size_t );
virtual void setGlobalThreshold ( DbU::Unit );
virtual DbU::Unit getEdgeLength () const;
virtual DbU::Unit getEdgeWidth () const;
virtual float getEdgeCostH () const;
@ -159,6 +171,9 @@ namespace Anabatic {
CellGauge* _cg;
RoutingGauge* _rg;
std::vector<DbU::Unit> _extensionCaps;
float _saturateRatio;
size_t _saturateRp;
DbU::Unit _globalThreshold;
size_t _allowedDepth;
DbU::Unit _edgeLength;
DbU::Unit _edgeWidth;

View File

@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; explicit-buffer-name: "Constants.h<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved
@ -24,25 +24,60 @@ namespace Anabatic {
class Flags : public Hurricane::BaseFlags {
public:
enum Flag { NoFlags = 0
, Horizontal = (1<<0)
, Vertical = (1<<1)
, SourceGCell = (1<<2)
, TargetGCell = (1<<3)
, DeviceGCell = (1<<4)
, ChannelGCell = (1<<5)
, StrutGCell = (1<<6)
, MatrixGCell = (1<<7)
, Invalidated = (1<<8)
, Destroy = (1<<9)
, WestSide = Horizontal|TargetGCell
, EastSide = Horizontal|SourceGCell
, SouthSide = Vertical |TargetGCell
, NorthSide = Vertical |SourceGCell
, AllSides = WestSide|EastSide|SouthSide|NorthSide
, PitchAbove = (1<<10)
, PitchBelow = (1<<11)
};
static const unsigned int NoFlags = 0;
// Flags used for both objects states & functions arguments.
static const unsigned int Horizontal = (1 << 0);
static const unsigned int Vertical = (1 << 1);
static const unsigned int Source = (1 << 2);
static const unsigned int Target = (1 << 3);
static const unsigned int Invalidated = (1 << 4);
// Flags for GCell objects states only.
static const unsigned int DeviceGCell = (1 << 5);
static const unsigned int ChannelGCell = (1 << 6);
static const unsigned int StrutGCell = (1 << 7);
static const unsigned int MatrixGCell = (1 << 8);
static const unsigned int IoPadGCell = (1 << 9);
static const unsigned int Saturated = (1 << 10);
// Flags for Anabatic objects states only.
static const unsigned int DemoMode = (1 << 5);
static const unsigned int WarnOnGCellOverload = (1 << 6);
static const unsigned int DestroyGCell = (1 << 7);
static const unsigned int DestroyBaseContact = (1 << 8);
static const unsigned int DestroyBaseSegment = (1 << 9);
// Masks.
static const unsigned int WestSide = Horizontal|Target;
static const unsigned int EastSide = Horizontal|Source;
static const unsigned int SouthSide = Vertical |Target;
static const unsigned int NorthSide = Vertical |Source;
static const unsigned int AllSides = WestSide|EastSide|SouthSide|NorthSide ;
static const unsigned int DirectionMask = Horizontal|Vertical;
static const unsigned int DestroyMask = DestroyGCell|DestroyBaseContact|DestroyBaseSegment;
// Flags for functions arguments only.
static const unsigned int AboveLayer = (1 << 5);
static const unsigned int BelowLayer = (1 << 6);
static const unsigned int OpenSession = (1 << 7);
static const unsigned int Realignate = (1 << 8);
static const unsigned int NativeConstraints = (1 << 9);
static const unsigned int ForceMove = (1 << 10);
static const unsigned int WithPerpands = (1 << 11);
static const unsigned int WarnOnError = (1 << 12);
static const unsigned int Topology = (1 << 13);
static const unsigned int GlobalSegment = (1 << 14);
static const unsigned int AllowTerminal = (1 << 15);
static const unsigned int AllowLocal = (1 << 16);
static const unsigned int IgnoreContacts = (1 << 17);
static const unsigned int Propagate = (1 << 18);
static const unsigned int Superior = (1 << 19);
static const unsigned int DoglegOnLeft = (1 << 20);
static const unsigned int DoglegOnRight = (1 << 21);
static const unsigned int WithNeighbors = (1 << 22);
static const unsigned int NoCheckLayer = (1 << 23);
static const unsigned int HalfSlacken = (1 << 24);
static const unsigned int NoGCellShrink = (1 << 25);
static const unsigned int CParanoid = (1 << 26);
static const unsigned int Create = (1 << 27);
static const unsigned int CheckLowDensity = (1 << 28);
static const unsigned int NoUpdate = (1 << 29);
public:
inline Flags ( unsigned int flags = NoFlags );
inline Flags ( BaseFlags );
@ -56,6 +91,23 @@ namespace Anabatic {
Flags::Flags ( BaseFlags base ) : BaseFlags(base) { }
enum EngineState { EngineCreation = 1
, EngineGlobalLoaded = 2
, EngineActive = 3
, EngineDriving = 4
, EnginePreDestroying = 5
, EngineGutted = 6
};
enum EngineAlgorithm { EngineLoadGrByNet = (1 << 0)
, EngineLoadGrByGCell = (1 << 1)
, EngineLayerAssignByLength = (1 << 2)
, EngineLayerAssignByTrunk = (1 << 3)
, EngineNoNetLayerAssign = (1 << 4)
};
} // Anabatic namespace.

View File

@ -20,20 +20,25 @@
#include <vector>
#include <string>
#include <set>
#include <functional>
#include "hurricane/Name.h"
#include "hurricane/Box.h"
#include "hurricane/Cell.h"
#include "hurricane/ExtensionGo.h"
namespace Hurricane {
class Contact;
class RoutingPad;
}
#include "anabatic/Edge.h"
#include "anabatic/AutoSegments.h"
namespace Anabatic {
using std::string;
using std::vector;
using std::set;
using std::binary_function;
using Hurricane::StaticObservable;
using Hurricane::BaseObserver;
using Hurricane::Name;
@ -45,9 +50,11 @@ namespace Anabatic {
using Hurricane::Net;
using Hurricane::Entity;
using Hurricane::Contact;
using Hurricane::RoutingPad;
using Hurricane::Cell;
class AnabaticEngine;
class GCell;
// -------------------------------------------------------------------
@ -56,6 +63,18 @@ namespace Anabatic {
class GCell : public ExtensionGo {
public:
typedef ExtensionGo Super;
typedef std::set< GCell*, Entity::CompareById > Set;
typedef std::vector<GCell*> Vector;
public:
enum DensityMode { AverageHVDensity = 1 // Average between all densities.
, AverageHDensity = 2 // Average between all H densities.
, AverageVDensity = 3 // Average between all V densities.
, MaxHVDensity = 4 // Maximum between average H and average V.
, MaxVDensity = 5 // Maximum of V densities.
, MaxHDensity = 6 // Maximum of H densities.
, MaxDensity = 7 // Maximum of H & V densities.
};
public:
class Observable : public StaticObservable<1> {
public:
@ -68,123 +87,219 @@ namespace Anabatic {
Observable& operator= ( const StaticObservable& );
};
public:
static Box getBorder ( const GCell*, const GCell* );
class CompareByDensity : public binary_function<GCell*,GCell*,bool> {
public:
CompareByDensity ( size_t depth );
inline bool operator() ( GCell* lhs, GCell* rhs );
private:
size_t _depth;
};
class CompareByKey : public binary_function<const GCell*,const GCell*,bool> {
public:
inline bool operator() ( const GCell* lhs, const GCell* rhs );
};
public:
class Key {
public:
inline Key ( GCell*, size_t depth );
inline float getDensity () const;
inline GCell* getGCell () const;
inline void update ( size_t depth );
friend bool operator< ( const Key&, const Key& );
private:
GCell* _gcell;
float _density;
};
public:
static Box getBorder ( const GCell*, const GCell* );
public:
static GCell* create ( AnabaticEngine* );
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 isWest ( GCell* ) const;
bool isEast ( GCell* ) const;
bool isNorth ( GCell* ) const;
bool isSouth ( GCell* ) 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* );
inline bool isSaturated () const;
bool isSaturated ( size_t depth ) const;
inline bool isInvalidated () const;
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 bool isIoPad () const;
bool isWest ( GCell* ) const;
bool isEast ( GCell* ) const;
bool isNorth ( GCell* ) const;
bool isSouth ( GCell* ) 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* );
void cleanupGlobal ();
// Detailed routing functions.
bool hasFreeTrack ( size_t depth, float reserve ) const;
inline size_t getDepth () const;
Interval getSide ( unsigned int ) const;
float getHCapacity () const;
float getVCapacity () const;
float getDensity ( unsigned int flags=Flags::NoFlags ) const;
float getAverageHVDensity () const;
float getMaxHVDensity () const;
inline float getCDensity ( unsigned int flags=Flags::NoFlags ) const;
inline float getWDensity ( size_t depth, unsigned int flags=Flags::NoFlags ) const;
inline DbU::Unit getBlockage ( size_t depth ) const;
inline float getFragmentation ( size_t depth ) const;
inline float getFeedthroughs ( size_t depth ) const;
inline float getGlobalsCount ( size_t depth ) const;
inline const vector<AutoSegment*>& getHSegments () const;
inline const vector<AutoSegment*>& getVSegments () const;
inline const vector<AutoContact*>& getContacts () const;
AutoSegments getHStartSegments ();
AutoSegments getVStartSegments ();
AutoSegments getHStopSegments ();
AutoSegments getVStopSegments ();
inline AutoSegments getStartSegments ( unsigned int direction );
inline AutoSegments getStopSegments ( unsigned int direction );
size_t getRoutingPads ( set<RoutingPad*>& );
inline const Key& getKey () const;
size_t checkDensity () const;
bool checkEdgeSaturation ( size_t hreserved, size_t vreserved) const;
void addBlockage ( size_t depth, DbU::Unit );
inline void addHSegment ( AutoSegment* );
inline void addVSegment ( AutoSegment* );
inline void addContact ( AutoContact* );
void removeVSegment ( AutoSegment* );
void removeHSegment ( AutoSegment* );
void removeContact ( AutoContact* );
void updateContacts ();
size_t updateDensity ();
inline void updateKey ( size_t depth );
bool stepBalance ( size_t depth, Set& invalidateds );
void rpDesaturate ( set<Net*>& );
bool stepDesaturate ( size_t depth
, set<Net*>&, AutoSegment*& moved
, unsigned int flags=Flags::NoFlags );
bool stepNetDesaturate ( size_t depth
, set<Net*>& globalNets
, Set& invalidateds );
// 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;
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.
template<typename OwnerT>
inline OwnerT* getObserver ( size_t slot );
inline void setObserver ( size_t slot, BaseObserver* );
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 ();
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& );
GCell ( const GCell& );
GCell& operator= ( const GCell& );
private:
static Name _extensionName;
Observable _observable;
AnabaticEngine* _anabatic;
Flags _flags;
vector<Edge*> _westEdges;
vector<Edge*> _eastEdges;
vector<Edge*> _southEdges;
vector<Edge*> _northEdges;
DbU::Unit _xmin;
DbU::Unit _ymin;
vector<Contact*> _contacts;
static Name _extensionName;
Observable _observable;
AnabaticEngine* _anabatic;
Flags _flags;
vector<Edge*> _westEdges;
vector<Edge*> _eastEdges;
vector<Edge*> _southEdges;
vector<Edge*> _northEdges;
DbU::Unit _xmin;
DbU::Unit _ymin;
vector<Contact*> _gcontacts;
vector<AutoSegment*> _vsegments;
vector<AutoSegment*> _hsegments;
vector<AutoContact*> _contacts;
size_t _depth;
size_t _pinDepth;
DbU::Unit* _blockages;
float _cDensity;
float* _densities;
float* _feedthroughs;
float* _fragmentations;
float* _globalsCount;
Key _key;
};
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 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 bool GCell::isIoPad () const { return _flags & Flags::IoPadGCell; }
inline bool GCell::isSaturated () const { return _flags & Flags::Saturated; }
inline bool GCell::isInvalidated () const { return _flags & Flags::Invalidated; }
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 _gcontacts; }
inline size_t GCell::getDepth () const { return _depth; }
inline const vector<AutoSegment*>& GCell::getVSegments () const { return _vsegments; }
inline const vector<AutoSegment*>& GCell::getHSegments () const { return _hsegments; }
inline const vector<AutoContact*>& GCell::getContacts () const { return _contacts; }
inline const GCell::Key& GCell::getKey () const { return _key; }
inline void GCell::updateKey ( size_t depth ) { _key.update(depth); }
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
@ -215,11 +330,103 @@ namespace Anabatic {
inline GCell::Observable::Observable () : StaticObservable<1>() { }
inline AutoSegments GCell::getStartSegments ( unsigned int direction )
{ return (direction&Flags::Horizontal) ? getHStartSegments() : getVStartSegments(); }
inline AutoSegments GCell::getStopSegments ( unsigned int direction )
{ return (direction&Flags::Horizontal) ? getHStopSegments() : getVStopSegments(); }
inline float GCell::getCDensity ( unsigned int flags ) const
{ if (isInvalidated() and not(flags & Flags::NoUpdate)) const_cast<GCell*>(this)->updateDensity(); return _cDensity; }
inline float GCell::getWDensity ( size_t depth, unsigned int flags ) const
{ if (isInvalidated() and not(flags & Flags::NoUpdate)) const_cast<GCell*>(this)->updateDensity(); return _densities[depth]; }
inline float GCell::getFragmentation ( size_t depth ) const
{ if (isInvalidated()) const_cast<GCell*>(this)->updateDensity(); return _fragmentations[depth]; }
inline float GCell::getFeedthroughs ( size_t depth ) const
{ if (isInvalidated()) const_cast<GCell*>(this)->updateDensity(); return _feedthroughs[depth]; }
inline float GCell::getGlobalsCount ( size_t depth ) const
{ if (isInvalidated()) const_cast<GCell*>(this)->updateDensity(); return _globalsCount[depth]; }
inline DbU::Unit GCell::getBlockage ( size_t depth ) const
{ return (depth<_depth) ? _blockages[depth] : 0; }
inline void GCell::addVSegment ( AutoSegment* segment )
{ _flags |= Flags::Invalidated; _vsegments.push_back(segment); }
inline void GCell::addHSegment ( AutoSegment* segment )
{ _flags |= Flags::Invalidated; _hsegments.push_back(segment); }
inline void GCell::addContact ( AutoContact* contact )
{ _flags |= Flags::Invalidated; _contacts.push_back(contact); }
inline bool operator< ( const GCell& lhs, const GCell& rhs )
{
if (lhs.getYMin() != rhs.getYMin()) return lhs.getYMin() < rhs.getYMin();
if (lhs.getXMin() != rhs.getXMin()) return lhs.getXMin() < rhs.getXMin();
return lhs.getId() < rhs.getId();
}
// GCell::CompareByKey Inline Functions.
inline bool GCell::CompareByKey::operator() ( const GCell* lhs, const GCell* rhs )
{ return lhs->getKey() < rhs->getKey(); }
// GCell::Key Inline Functions.
inline GCell::Key::Key ( GCell* owner, size_t depth ) : _gcell(owner), _density(owner->getWDensity(depth,Flags::NoUpdate)) {}
inline float GCell::Key::getDensity () const { return _density; }
inline GCell* GCell::Key::getGCell () const { return _gcell; }
inline void GCell::Key::update ( size_t depth ) { _density=_gcell->getWDensity(depth); }
inline bool operator< ( const GCell::Key& lhs, const GCell::Key& rhs )
{
float difference = lhs._density - rhs._density;
if (difference != 0.0) return (difference > 0.0);
return lhs._gcell->getId() < rhs._gcell->getId();
}
// -------------------------------------------------------------------
// Class : "GCellSet".
// Class : "GCellDensitySet".
class GCellDensitySet {
public:
GCellDensitySet ( size_t depth );
GCellDensitySet ( size_t depth, const std::vector<GCell*>& );
~GCellDensitySet ();
inline bool empty () const;
inline size_t size () const;
inline const std::set<GCell*,GCell::CompareByKey>&
getGCells () const;
inline void insert ( GCell* );
inline void erase ( GCell* );
inline void unqueue ( GCell* );
void requeue ();
private:
size_t _depth;
std::set<GCell*,GCell::CompareByKey> _set;
GCell::Set _requests;
};
typedef std::set< GCell*, Entity::CompareById > GCellSet;
inline bool GCellDensitySet::empty () const { return _set.empty(); }
inline size_t GCellDensitySet::size () const { return _set.size(); }
inline void GCellDensitySet::insert ( GCell* gcell ) { _requests.insert( gcell ); }
inline void GCellDensitySet::erase ( GCell* gcell ) { if (not _set.empty()) _set.erase( gcell ); }
inline void GCellDensitySet::unqueue ( GCell* gcell ) { insert( gcell ); }
inline const std::set<GCell*,GCell::CompareByKey>& GCellDensitySet::getGCells () const { return _set; }
// -------------------------------------------------------------------
// Utilities.
string getVectorString ( float*, size_t );
} // Anabatic namespace.

View File

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

View File

@ -0,0 +1,236 @@
// -*- mode: C++; explicit-buffer-name: "Session.h<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/Session.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_SESSION_H
#define ANABATIC_SESSION_H
#include <string>
#include <vector>
#include <set>
#include <map>
#include <boost/function.hpp>
#include "hurricane/Commons.h"
#include "hurricane/DbU.h"
#include "crlcore/CellGauge.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/Constants.h"
#include "anabatic/Configuration.h"
namespace Hurricane {
class Layer;
class Technology;
class Net;
class Contact;
class Segment;
}
namespace Anabatic {
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::set;
using std::map;
using std::make_pair;
using Hurricane::tab;
using Hurricane::_TName;
using Hurricane::Record;
using Hurricane::Layer;
using Hurricane::Technology;
using Hurricane::DbU;
using Hurricane::Net;
using Hurricane::Contact;
using Hurricane::Segment;
using CRL::RoutingGauge;
class AutoContact;
class AutoSegment;
class AnabaticEngine;
// -------------------------------------------------------------------
// Class : "Anabatic::Session".
class Session {
public:
// Static Methods.
static inline bool doDestroyBaseContact ();
static inline bool doDestroyBaseSegment ();
static inline bool doDestroyTool ();
static bool isInDemoMode ();
static bool doWarnGCellOverload ();
static Session* get ( const char* message=NULL );
static inline Technology* getTechnology ();
static inline AnabaticEngine* getAnabatic ();
static inline const Configuration* getConfiguration ();
static float getSaturateRatio ();
static size_t getSaturateRp ();
static inline size_t getAllowedDepth ();
static DbU::Unit getExtensionCap ();
static inline CellGauge* getCellGauge ();
static inline DbU::Unit getSliceHeight ();
static inline DbU::Unit getSliceStep ();
static inline RoutingGauge* getRoutingGauge ();
static inline RoutingLayerGauge* getLayerGauge ( size_t depth );
static inline size_t getDepth ();
static inline size_t getViaDepth ( const Layer* layer );
static inline size_t getLayerDepth ( const Layer* layer );
static inline const Layer* getRoutingLayer ( size_t );
static inline const Layer* getContactLayer ( size_t );
static unsigned int getDirection ( size_t depth );
static inline DbU::Unit getPitch ( size_t depth, unsigned int flags );
static inline DbU::Unit getOffset ( size_t depth );
static inline DbU::Unit getWireWidth ( size_t depth );
static inline DbU::Unit getViaWidth ( size_t depth );
static inline unsigned int getDirection ( const Layer* );
static inline DbU::Unit getPitch ( const Layer*, unsigned int flags );
static inline DbU::Unit getOffset ( const Layer* );
static inline DbU::Unit getWireWidth ( const Layer* );
static inline DbU::Unit getViaWidth ( const Layer* );
static inline DbU::Unit getExtensionCap ( const Layer* );
static inline size_t getSegmentStackSize ();
static inline size_t getContactStackSize ();
static inline const vector<AutoSegment*>& getInvalidateds ();
static inline const vector<AutoSegment*>& getRevalidateds ();
static inline const set<AutoSegment*>& getDestroyeds ();
static inline const vector<AutoSegment*>& getDoglegs ();
static inline const set<Net*>& getNetsModificateds ();
static Session* open ( AnabaticEngine* );
static void close ();
static void setAnabaticFlags ( unsigned int );
static inline void dogleg ( AutoSegment* );
static inline void doglegReset ();
static inline void revalidateTopology ();
static inline void setInvalidateMask ( unsigned int );
static inline void invalidate ( Net* );
static inline void invalidate ( AutoContact* );
static inline void invalidate ( AutoSegment* );
static inline size_t revalidate ();
static void link ( AutoContact* );
static void link ( AutoSegment* );
static void unlink ( AutoContact* );
static void unlink ( AutoSegment* );
static AutoContact* lookup ( Contact* );
static AutoSegment* lookup ( Segment* );
static inline void destroyRequest ( AutoSegment* );
// Methods.
bool _doDestroyBaseContact ();
bool _doDestroyBaseSegment ();
bool _doDestroyTool ();
virtual Configuration* _getConfiguration ();
inline void _dogleg ( AutoSegment* );
inline void _doglegReset ();
void _invalidate ( Net* );
inline void _invalidate ( AutoContact* );
inline void _invalidate ( AutoSegment* );
inline void _destroyRequest ( AutoSegment* );
void _canonize ();
void _revalidateTopology ();
size_t _revalidate ();
DbU::Unit _getPitch ( size_t depth, unsigned int flags ) const;
Record* _getRecord () const;
string _getString () const;
inline string _getTypeName () const;
protected:
static Session* _session;
AnabaticEngine* _anabatic;
Technology* _technology;
CellGauge* _cellGauge;
RoutingGauge* _routingGauge;
vector<AutoContact*> _autoContacts;
vector<AutoSegment*> _doglegs;
vector<AutoSegment*> _segmentInvalidateds;
vector<AutoSegment*> _segmentRevalidateds;
set<Net*> _netInvalidateds;
set<Net*> _netRevalidateds;
set<AutoSegment*> _destroyedSegments;
// Constructors.
protected:
Session ( AnabaticEngine* );
virtual ~Session ();
virtual void _postCreate ();
virtual void _preDestroy ();
private:
Session ( const Session& );
Session& operator= ( const Session& );
};
// Inline Functions.
inline Technology* Session::getTechnology () { return get("getTechnology()")->_technology; }
inline CellGauge* Session::getCellGauge () { return get("getCellGauge()")->_cellGauge; }
inline RoutingGauge* Session::getRoutingGauge () { return get("getRoutingGauge()")->_routingGauge; }
inline bool Session::doDestroyBaseContact () { return get("doDestroyBaseContact()")->_doDestroyBaseContact(); }
inline bool Session::doDestroyBaseSegment () { return get("doDestroyBaseSegment()")->_doDestroyBaseSegment(); }
inline bool Session::doDestroyTool () { return get("doDestroyTool()")->_doDestroyTool(); }
inline const Configuration* Session::getConfiguration () { return get("getConfiguration()")->_getConfiguration(); }
inline AnabaticEngine* Session::getAnabatic () { return get("getAnabatic()")->_anabatic; }
inline void Session::revalidateTopology () { return get("revalidateTopology()")->_revalidateTopology(); }
inline size_t Session::revalidate () { return get("revalidate()")->_revalidate(); }
inline size_t Session::getSegmentStackSize () { return get("getSegmentStackSize()")->_segmentInvalidateds.size(); }
inline size_t Session::getContactStackSize () { return get("getContactStackSize()")->_autoContacts.size(); }
inline const vector<AutoSegment*>& Session::getInvalidateds () { return get("getInvalidateds()")->_segmentInvalidateds; }
inline const vector<AutoSegment*>& Session::getRevalidateds () { return get("getRevalidateds()")->_segmentRevalidateds; }
inline const set<AutoSegment*>& Session::getDestroyeds () { return get("getDestroyeds()")->_destroyedSegments; }
inline const vector<AutoSegment*>& Session::getDoglegs () { return get("getDoglegs()")->_doglegs; }
inline const set<Net*>& Session::getNetsModificateds () { return get("getNetsModificateds()")->_netRevalidateds; }
inline void Session::doglegReset () { return get("doglegReset()")->_doglegReset (); }
inline void Session::invalidate ( Net* net ) { return get("invalidate(Net*)")->_invalidate(net); }
inline void Session::invalidate ( AutoContact* autoContact ) { return get("invalidate(AutoContact*)")->_invalidate(autoContact); }
inline void Session::invalidate ( AutoSegment* autoSegment ) { return get("invalidate(AutoSegment*)")->_invalidate(autoSegment); }
inline void Session::dogleg ( AutoSegment* autoSegment ) { return get("dogleg(AutoSegment*)")->_dogleg(autoSegment); }
inline void Session::destroyRequest ( AutoSegment* autoSegment ) { return get("destroyRequest(AutoSegment*)")->_destroyRequest(autoSegment); }
inline size_t Session::getAllowedDepth () { return getConfiguration()->getAllowedDepth(); }
inline DbU::Unit Session::getSliceHeight () { return getCellGauge()->getSliceHeight(); }
inline DbU::Unit Session::getSliceStep () { return getCellGauge()->getSliceStep(); }
inline RoutingLayerGauge* Session::getLayerGauge ( size_t depth ) { return getRoutingGauge()->getLayerGauge(depth); }
inline size_t Session::getDepth () { return getRoutingGauge()->getDepth(); }
inline size_t Session::getViaDepth ( const Layer* layer ) { return getRoutingGauge()->getViaDepth(layer); }
inline size_t Session::getLayerDepth ( const Layer* layer ) { return getRoutingGauge()->getLayerDepth(layer); }
inline const Layer* Session::getRoutingLayer ( size_t depth ) { return getRoutingGauge()->getRoutingLayer(depth); }
inline const Layer* Session::getContactLayer ( size_t depth ) { return getRoutingGauge()->getContactLayer(depth); }
inline DbU::Unit Session::getPitch ( size_t depth, unsigned int flags=Flags::NoFlags ) { return get("getPitch(depth,flags)")->_getPitch( depth, flags ); }
inline DbU::Unit Session::getOffset ( size_t depth ) { return getRoutingGauge()->getLayerOffset(depth); }
inline DbU::Unit Session::getWireWidth ( size_t depth ) { return getRoutingGauge()->getLayerWireWidth(depth); }
inline DbU::Unit Session::getViaWidth ( size_t depth ) { return getRoutingGauge()->getViaWidth(depth); }
inline DbU::Unit Session::getPitch ( const Layer* layer, unsigned int flags=Flags::NoFlags ) { return getPitch( getLayerDepth(layer), flags ); }
inline DbU::Unit Session::getOffset ( const Layer* layer ) { return getOffset ( getLayerDepth(layer) ); }
inline DbU::Unit Session::getWireWidth ( const Layer* layer ) { return getWireWidth( getLayerDepth(layer) ); }
inline DbU::Unit Session::getViaWidth ( const Layer* layer ) { return getViaWidth ( getViaDepth(layer) ); }
inline DbU::Unit Session::getExtensionCap ( const Layer* layer ) { return getConfiguration()->getExtensionCap(layer); }
inline unsigned int Session::getDirection ( const Layer* layer ) { return getDirection( getLayerDepth(layer) ); }
inline void Session::_dogleg ( AutoSegment* segment ) { _doglegs.push_back(segment); }
inline void Session::_doglegReset () { _doglegs.clear(); }
inline void Session::_invalidate ( AutoContact* contact ) { _autoContacts.push_back(contact); }
inline void Session::_invalidate ( AutoSegment* segment ) { _segmentInvalidateds.push_back(segment); }
inline void Session::_destroyRequest ( AutoSegment* segment ) { _destroyedSegments.insert(segment); }
inline string Session::_getTypeName () const { return _TName("Session"); }
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::Session);
#endif // ANABATIC_SESSION_H