coriolis/katabatic/src/AutoContactTurn.cpp

265 lines
8.1 KiB
C++
Raw Normal View History

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2012, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | K a t 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/UpdateSession.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "katabatic/AutoContactTurn.h"
#include "katabatic/AutoVertical.h"
#include "katabatic/AutoHorizontal.h"
#include "katabatic/Session.h"
namespace Katabatic {
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::DebugSession;
using Hurricane::ltracein;
using Hurricane::ltraceout;
// -------------------------------------------------------------------
// Class : "Katabatic::AutoContactTurn".
AutoContactTurn* AutoContactTurn::create ( GCell* gcell, Net* net, const Layer* layer )
{
_preCreate( gcell, net, layer );
Contact* contact = Contact::create ( net
, layer
, gcell->getCenter().getX()
, gcell->getCenter().getY()
, DbU::lambda(2.0)
, DbU::lambda(2.0)
);
AutoContactTurn* autoContact = new AutoContactTurn ( gcell, contact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
ltrace(90) << "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::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() == KbHorizontal) {
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() == KbVertical) {
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);
}
unsetFlags( CntInvalidatedCache );
}
void AutoContactTurn::updateCache ()
{
DebugSession::open( getNet(), 80 );
ltrace(110) << _getTypeName() << "::updateCache() " << this << endl;
ltracein(110);
Component* anchor;
Horizontal** horizontals = new Horizontal* [2];
Vertical** verticals = new Vertical* [2];
_getTopology ( 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.";
if (not message.empty()) {
showTopologyError( message );
setFlags( CntBadTopology );
} else
unsetFlags( CntInvalidatedCache );
ltrace(110) << "h1:" << _horizontal1 << endl;
ltrace(110) << "v1:" << _vertical1 << endl;
delete [] horizontals;
delete [] verticals;
ltraceout(110);
DebugSession::close();
}
void AutoContactTurn::updateGeometry ()
{
DebugSession::open( getNet(), 80 );
ltrace(110) << _getTypeName() << "::updateGeometry() " << this << endl;
ltracein(110);
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
ltraceout(110);
return;
}
base()->invalidate( false );
unsetFlags ( CntInvalidated );
if (not hasBadTopology()) {
setX( getVertical1 ()->getX() );
setY( getHorizontal1()->getY() );
}
ltraceout(110);
DebugSession::close();
}
void AutoContactTurn::updateTopology ()
{
DebugSession::open ( getNet(), 80 );
ltrace(110) << _getTypeName() << "::updateTopology() " << this << endl;
ltracein(110);
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
ltraceout(110);
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 );
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() );
ltrace(110) << "Update h1: " << _horizontal1 << endl;
} else /*if (_vertical1->isInvalidatedLayer())*/ {
//_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
_vertical1->makeDogleg(this);
depthV1 = rg->getLayerDepth( _vertical1->getLayer() );
ltrace(110) << "Update v1: " << _vertical1 << endl;
}
delta = abssub ( depthH1, depthV1 );
}
setLayer ( (delta == 0) ? rg->getRoutingLayer(depthContact) : rg->getContactLayer(depthContact) );
}
}
ltraceout(110);
DebugSession::close ();
}
string AutoContactTurn::_getTypeName () const
{ return "ContactTurn"; }
} // Katabatic namespace.