2016-07-18 07:48:37 -05:00
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
2018-01-06 10:55:44 -06:00
|
|
|
// Copyright (c) UPMC 2012-2018, All Rights Reserved
|
2016-07-18 07:48:37 -05:00
|
|
|
//
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
// | 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 )
|
|
|
|
{
|
2016-08-27 08:59:12 -05:00
|
|
|
_preCreate( gcell, net, layer );
|
|
|
|
|
2016-07-18 07:48:37 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Katana manage wide wires, and they can also be symmetric.
* New: In Anabatic::AutoContact and the derived classes, manages wide
wires. The contact self dimension itself according to the segments
it is connected to. Special case for the AutoContactTerminal which
also read the size of the component it is anchored upon.
New refresh method "updateSize()" and flag CntInvalidatedWidth.
to compute the size.
In AutoContactTerminal, compute the constraint box according to
the width of the segment.
* New: In Anabatic::AutoSegment, flags are now implemented as "static const"
attributes of the class. The flags are stored into a uint64_t as
they are more than 32.
Added new flag "SegWide" and associated predicates.
* Change: In GCellTopology::_doHChannel() and GCellTopology::_doVChannel(),
uses the simpler overload of AutoSegment::create() in order to detect
the wire width automatically.
* New: In Katana::Manipulator, split insertToTrack() and forceToTrack()
into a one-track method and a segment level method that iterate over
the track span of the segment.
* New: In Katana::SegmentFsm, for each cost in the table, now allow access
to a specific track. So the base functions have now two parameters:
"icost" and "itrack" (has a cost can have multiple tracks in the case
of wide segments).
* Change: In Katana::TrackElement, remove the index of the element inside
it's track, as for a wide segment it will not be meaningful for the
non-base track. This means that we have to use the Track::find()
method each time instead.
Remove the wide flag, as it is a duplicate of the one in AutoSegment.
Added a getTrackCount() method to tell the number of track the
segment is inserted into. Needed in the Track destroy step to delete
a segment only when the last track that refers it is destroyed.
Added getSymmetricAxis() to correct the computation of the symmetric
base track in case of wide segment as the base track is not centered
but the the leftmost one.
* Change: In Track::insert() insert wide segments in their whole track span.
* Change: In TrackCost, create an array of costs according to the segment
track span.
* Change: In TrackSegment::create(), now activate the factory and create
wide segments.
* Bug: In Katana::AutoSegments_Perpandicular, correct the debug indentation
problem (ever shifting to the right).
2017-07-28 08:30:22 -05:00
|
|
|
AutoHorizontal* AutoContactVTee::getHorizontal1 () const { return _horizontal1; };
|
|
|
|
AutoVertical* AutoContactVTee::getVertical1 () const { return _vertical1; };
|
|
|
|
AutoVertical* AutoContactVTee::getVertical2 () const { return _vertical2; };
|
|
|
|
|
|
|
|
|
Replace "unsigned int" by "Flags" in all AutoSegments collections.
* Change: In Anabatic::AutoSegments collections, change the type of all
the flags that where in "unsigned int" (32 bits) to Flags (uint64_t)
as there is now more than 32 flags for functions.
* New: In Ababatic::Constants, added new flag Flags::WithPerpands, which
makes the number of flags tip over 32 bits, thus making mandatory
to uses Flags and not unsigned int.
* New: In Anabatic::AutoSegments_Perpandiculars, manage a new flag
Flags::WithDoglegs to allow to propagate through global segments that
are connecteds via doglegs on local segments. Meaning that there is
a good chance that they could be aligned.
Slighly change the way we propagate on aligned segments: no longer
check for VTee or HTee, but only for same direction and layer as
master.
* New: In Anabatic & Katana, replace all the "int", "long" and their
variants by the less implementation ambiguous "int32_t", "int64_t"
(and variant). This should help to better detect bit trucation in
flags.
Use the type to give a hint about the flags kind:
- Type "Flags", for flags shared among Anabatic & Katana
functions/methods (may also appear in some objects states).
- Type "uint32_t" for flags belonging to an object internal
state of from Hurricane functions flags (those should be
grouped in a Flag subclass in a perfect world).
2017-05-16 07:53:33 -05:00
|
|
|
void AutoContactVTee::_invalidate ( Flags )
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
Replace "unsigned int" by "Flags" in all AutoSegments collections.
* Change: In Anabatic::AutoSegments collections, change the type of all
the flags that where in "unsigned int" (32 bits) to Flags (uint64_t)
as there is now more than 32 flags for functions.
* New: In Ababatic::Constants, added new flag Flags::WithPerpands, which
makes the number of flags tip over 32 bits, thus making mandatory
to uses Flags and not unsigned int.
* New: In Anabatic::AutoSegments_Perpandiculars, manage a new flag
Flags::WithDoglegs to allow to propagate through global segments that
are connecteds via doglegs on local segments. Meaning that there is
a good chance that they could be aligned.
Slighly change the way we propagate on aligned segments: no longer
check for VTee or HTee, but only for same direction and layer as
master.
* New: In Anabatic & Katana, replace all the "int", "long" and their
variants by the less implementation ambiguous "int32_t", "int64_t"
(and variant). This should help to better detect bit trucation in
flags.
Use the type to give a hint about the flags kind:
- Type "Flags", for flags shared among Anabatic & Katana
functions/methods (may also appear in some objects states).
- Type "uint32_t" for flags belonging to an object internal
state of from Hurricane functions flags (those should be
grouped in a Flag subclass in a perfect world).
2017-05-16 07:53:33 -05:00
|
|
|
Flags flags = Flags::Propagate;
|
2016-07-18 07:48:37 -05:00
|
|
|
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() );
|
Katana manage wide wires, and they can also be symmetric.
* New: In Anabatic::AutoContact and the derived classes, manages wide
wires. The contact self dimension itself according to the segments
it is connected to. Special case for the AutoContactTerminal which
also read the size of the component it is anchored upon.
New refresh method "updateSize()" and flag CntInvalidatedWidth.
to compute the size.
In AutoContactTerminal, compute the constraint box according to
the width of the segment.
* New: In Anabatic::AutoSegment, flags are now implemented as "static const"
attributes of the class. The flags are stored into a uint64_t as
they are more than 32.
Added new flag "SegWide" and associated predicates.
* Change: In GCellTopology::_doHChannel() and GCellTopology::_doVChannel(),
uses the simpler overload of AutoSegment::create() in order to detect
the wire width automatically.
* New: In Katana::Manipulator, split insertToTrack() and forceToTrack()
into a one-track method and a segment level method that iterate over
the track span of the segment.
* New: In Katana::SegmentFsm, for each cost in the table, now allow access
to a specific track. So the base functions have now two parameters:
"icost" and "itrack" (has a cost can have multiple tracks in the case
of wide segments).
* Change: In Katana::TrackElement, remove the index of the element inside
it's track, as for a wide segment it will not be meaningful for the
non-base track. This means that we have to use the Track::find()
method each time instead.
Remove the wide flag, as it is a duplicate of the one in AutoSegment.
Added a getTrackCount() method to tell the number of track the
segment is inserted into. Needed in the Track destroy step to delete
a segment only when the last track that refers it is destroyed.
Added getSymmetricAxis() to correct the computation of the symmetric
base track in case of wide segment as the base track is not centered
but the the leftmost one.
* Change: In Track::insert() insert wide segments in their whole track span.
* Change: In TrackCost, create an array of costs according to the segment
track span.
* Change: In TrackSegment::create(), now activate the factory and create
wide segments.
* Bug: In Katana::AutoSegments_Perpandicular, correct the debug indentation
problem (ever shifting to the right).
2017-07-28 08:30:22 -05:00
|
|
|
updateSize();
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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.
|