2016-07-18 07:48:37 -05:00
|
|
|
// -*- 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)
|
2016-09-22 07:16:53 -05:00
|
|
|
, _xMin (_gcell->getXMin())
|
|
|
|
, _xMax (_gcell->getConstraintXMax())
|
|
|
|
, _yMin (_gcell->getYMin())
|
|
|
|
, _yMax (_gcell->getConstraintYMax())
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
|
|
|
_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
|
First intergration of the Analogic router parts.
* New: In Anabatic::AutoSegment, introduce a the kind (associated to a
flag) "LongLocal". Analog GCells can be very wide, so at least some
carefuly choosen long local segments must be took into account as
attractors in the computation of the optimal axis.
* New: In Anabatic::AutoSegment::computeOptimal(), take LongLocal into
account as attractors.
* Change: In ::GCellTopology constructors compare the layers of the
RoutingPads using layer masks instead of Layer pointers. Allows to
find both "METALx" (symbolic) and "metalX" (real).
* Change: In ::GCellTopology::_doHChannel(), _doChannel(), _doStrut()
and _doDevice(), tag long locals as "LongLocal". This need to be
reviewed as it as bind done a bit too quickly.
* Change: In Anabatic::AutoSegment, due too a much bigger span of the
analogic GCells the _optimalMin & _optimalMax bitfields must use
16 bits instead of 8 (they where overflowed).
* New: In Katana, reorganisation of the initialization procedure to fit
both digital and analogic cases. Create an analogInit() method.
* Change: In Katana::RoutingEvent, the _tracksNb and _tracksFree bitfields
where too short for the Analog GCell size, now uses 16 bits instead of
6.
* Bug: In Katana::GraphicKatanEngine::drawGCell(), skip drawing of a
GCell if *both* width and height are under 150 pixels.
* New: In Katana::Session, add a new isOpen() method.
2016-10-04 10:12:58 -05:00
|
|
|
<< " <" << DbU::getValueString(getCBXMin())
|
|
|
|
<< " " << DbU::getValueString(getCBYMin())
|
|
|
|
<< " " << DbU::getValueString(getCBXMax())
|
|
|
|
<< " " << DbU::getValueString(getCBYMax()) << ">" << endl;
|
2016-07-18 07:48:37 -05:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
for ( Component* component : _contact->getSlaveComponents() ) {
|
|
|
|
message << "\n | " << component;
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
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; }
|
|
|
|
|
|
|
|
|
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
|
|
|
bool AutoContact::canDestroy ( Flags flags ) const
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
|
|
|
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; }
|
|
|
|
|
|
|
|
|
Forgot to perform Track re-order after removing zero-length segments.
* Change: In Anabatic::Autocontact, replace getMinDepth() and
getMaxDepth() by getDepthSpan().
* New: In Anabatic::AutoSegment::canMoveUp(), add an optional check of
low up density (Flags::CheckLowUpDensity). Allows to move up a
segment if the up density is (very) low, and in this case it's more
efficient than breaking it to fit in the lower layer.
canMoveUp() is now able to perform the same work as canPivotUp()
if *not* supplied the flag Flags::IgnoreContacts.
* New: In Katana, in GlobalRouting::DigitalDistance() now take into
account the cost of a VIA (currently set to 2.5). Need to known the
Net currently routed in the DigitalDistance object itself.
* Change: In Katana::Track::Element::canPivotUp(), now also takes a flag
parameter.
* Change: In Katana::Manipulator, new flag IgnoreContacts to mirror the
one of Anabatic.
* Change: In Katana::SegmentFsm, allocate once a Manipulator object instead
of many times on the fly.
In SegmentFsm::_slackenGlobal(), in the slacken state, if the up
density is (very) low, bypass to move up instead of slackening.
This solve better the routing of the control part of the register file.
The register file having a pathological case of terminal placement:
many punctual terminals aligneds in METAL2 *and* a grid of METAL2 and
METAL3 blockages near below...
* Bug: In Katana::Session::_revalidate(), after removing the zero-length
segments, forgot to re-order the track, leading to many stranges effects
as the indexes where no longer coherent in the Track.
2016-09-20 04:30:45 -05:00
|
|
|
void AutoContact::getDepthSpan ( size_t& minDepth, size_t& maxDepth ) const
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
Forgot to perform Track re-order after removing zero-length segments.
* Change: In Anabatic::Autocontact, replace getMinDepth() and
getMaxDepth() by getDepthSpan().
* New: In Anabatic::AutoSegment::canMoveUp(), add an optional check of
low up density (Flags::CheckLowUpDensity). Allows to move up a
segment if the up density is (very) low, and in this case it's more
efficient than breaking it to fit in the lower layer.
canMoveUp() is now able to perform the same work as canPivotUp()
if *not* supplied the flag Flags::IgnoreContacts.
* New: In Katana, in GlobalRouting::DigitalDistance() now take into
account the cost of a VIA (currently set to 2.5). Need to known the
Net currently routed in the DigitalDistance object itself.
* Change: In Katana::Track::Element::canPivotUp(), now also takes a flag
parameter.
* Change: In Katana::Manipulator, new flag IgnoreContacts to mirror the
one of Anabatic.
* Change: In Katana::SegmentFsm, allocate once a Manipulator object instead
of many times on the fly.
In SegmentFsm::_slackenGlobal(), in the slacken state, if the up
density is (very) low, bypass to move up instead of slackening.
This solve better the routing of the control part of the register file.
The register file having a pathological case of terminal placement:
many punctual terminals aligneds in METAL2 *and* a grid of METAL2 and
METAL3 blockages near below...
* Bug: In Katana::Session::_revalidate(), after removing the zero-length
segments, forgot to re-order the track, leading to many stranges effects
as the indexes where no longer coherent in the Track.
2016-09-20 04:30:45 -05:00
|
|
|
minDepth = (size_t)-1;
|
|
|
|
maxDepth = 0;
|
|
|
|
|
2016-07-18 07:48:37 -05:00
|
|
|
Component* anchor = getAnchor ();
|
|
|
|
if (anchor) {
|
|
|
|
minDepth = std::min( minDepth, Session::getRoutingGauge()->getLayerDepth(anchor->getLayer()) );
|
Forgot to perform Track re-order after removing zero-length segments.
* Change: In Anabatic::Autocontact, replace getMinDepth() and
getMaxDepth() by getDepthSpan().
* New: In Anabatic::AutoSegment::canMoveUp(), add an optional check of
low up density (Flags::CheckLowUpDensity). Allows to move up a
segment if the up density is (very) low, and in this case it's more
efficient than breaking it to fit in the lower layer.
canMoveUp() is now able to perform the same work as canPivotUp()
if *not* supplied the flag Flags::IgnoreContacts.
* New: In Katana, in GlobalRouting::DigitalDistance() now take into
account the cost of a VIA (currently set to 2.5). Need to known the
Net currently routed in the DigitalDistance object itself.
* Change: In Katana::Track::Element::canPivotUp(), now also takes a flag
parameter.
* Change: In Katana::Manipulator, new flag IgnoreContacts to mirror the
one of Anabatic.
* Change: In Katana::SegmentFsm, allocate once a Manipulator object instead
of many times on the fly.
In SegmentFsm::_slackenGlobal(), in the slacken state, if the up
density is (very) low, bypass to move up instead of slackening.
This solve better the routing of the control part of the register file.
The register file having a pathological case of terminal placement:
many punctual terminals aligneds in METAL2 *and* a grid of METAL2 and
METAL3 blockages near below...
* Bug: In Katana::Session::_revalidate(), after removing the zero-length
segments, forgot to re-order the track, leading to many stranges effects
as the indexes where no longer coherent in the Track.
2016-09-20 04:30:45 -05:00
|
|
|
maxDepth = std::max( maxDepth, Session::getRoutingGauge()->getLayerDepth(anchor->getLayer()) );
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
for ( AutoSegment* segment : const_cast<AutoContact*>(this)->getAutoSegments() ) {
|
|
|
|
minDepth = std::min( minDepth, Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) );
|
Forgot to perform Track re-order after removing zero-length segments.
* Change: In Anabatic::Autocontact, replace getMinDepth() and
getMaxDepth() by getDepthSpan().
* New: In Anabatic::AutoSegment::canMoveUp(), add an optional check of
low up density (Flags::CheckLowUpDensity). Allows to move up a
segment if the up density is (very) low, and in this case it's more
efficient than breaking it to fit in the lower layer.
canMoveUp() is now able to perform the same work as canPivotUp()
if *not* supplied the flag Flags::IgnoreContacts.
* New: In Katana, in GlobalRouting::DigitalDistance() now take into
account the cost of a VIA (currently set to 2.5). Need to known the
Net currently routed in the DigitalDistance object itself.
* Change: In Katana::Track::Element::canPivotUp(), now also takes a flag
parameter.
* Change: In Katana::Manipulator, new flag IgnoreContacts to mirror the
one of Anabatic.
* Change: In Katana::SegmentFsm, allocate once a Manipulator object instead
of many times on the fly.
In SegmentFsm::_slackenGlobal(), in the slacken state, if the up
density is (very) low, bypass to move up instead of slackening.
This solve better the routing of the control part of the register file.
The register file having a pathological case of terminal placement:
many punctual terminals aligneds in METAL2 *and* a grid of METAL2 and
METAL3 blockages near below...
* Bug: In Katana::Session::_revalidate(), after removing the zero-length
segments, forgot to re-order the track, leading to many stranges effects
as the indexes where no longer coherent in the Track.
2016-09-20 04:30:45 -05:00
|
|
|
maxDepth = std::max( maxDepth, Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) );
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
for ( AutoSegment* segment : getAutoSegments() ) {
|
|
|
|
bool isSourceHook = (segment->getAutoSource() == this);
|
2016-07-18 07:48:37 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
if (processeds.find(segment) != processeds.end()) continue;
|
|
|
|
processeds.insert( segment );
|
2016-07-18 07:48:37 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
size_t depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer());
|
2016-07-18 07:48:37 -05:00
|
|
|
DbU::Unit length;
|
2016-07-30 05:15:49 -05:00
|
|
|
if (segment->isLocal()) {
|
|
|
|
length = segment->getLength();
|
2016-07-18 07:48:37 -05:00
|
|
|
lengths[depth] += length;
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
DbU::Unit sideLength = (segment->isHorizontal()) ? hSideLength : vSideLength;
|
|
|
|
if ( not segment->isUnbound() and (abs(length) > sideLength) )
|
2016-07-18 07:48:37 -05:00
|
|
|
cerr << Error("Suspicious length:%.2f of %s."
|
First intergration of the Analogic router parts.
* New: In Anabatic::AutoSegment, introduce a the kind (associated to a
flag) "LongLocal". Analog GCells can be very wide, so at least some
carefuly choosen long local segments must be took into account as
attractors in the computation of the optimal axis.
* New: In Anabatic::AutoSegment::computeOptimal(), take LongLocal into
account as attractors.
* Change: In ::GCellTopology constructors compare the layers of the
RoutingPads using layer masks instead of Layer pointers. Allows to
find both "METALx" (symbolic) and "metalX" (real).
* Change: In ::GCellTopology::_doHChannel(), _doChannel(), _doStrut()
and _doDevice(), tag long locals as "LongLocal". This need to be
reviewed as it as bind done a bit too quickly.
* Change: In Anabatic::AutoSegment, due too a much bigger span of the
analogic GCells the _optimalMin & _optimalMax bitfields must use
16 bits instead of 8 (they where overflowed).
* New: In Katana, reorganisation of the initialization procedure to fit
both digital and analogic cases. Create an analogInit() method.
* Change: In Katana::RoutingEvent, the _tracksNb and _tracksFree bitfields
where too short for the Analog GCell size, now uses 16 bits instead of
6.
* Bug: In Katana::GraphicKatanEngine::drawGCell(), skip drawing of a
GCell if *both* width and height are under 150 pixels.
* New: In Katana::Session, add a new isOpen() method.
2016-10-04 10:12:58 -05:00
|
|
|
,DbU::getValueString(length).c_str()
|
|
|
|
,getString(segment).c_str()) << endl;
|
2016-07-18 07:48:37 -05:00
|
|
|
} else {
|
2016-07-30 05:15:49 -05:00
|
|
|
if (segment->isHorizontal()) {
|
2016-07-18 07:48:37 -05:00
|
|
|
if (isSourceHook)
|
2016-07-30 05:15:49 -05:00
|
|
|
lengths[depth] += _gcell->getXMax() - segment->getSourceX();
|
2016-07-18 07:48:37 -05:00
|
|
|
else
|
2016-07-30 05:15:49 -05:00
|
|
|
lengths[depth] += segment->getTargetX() - _gcell->getXMin();
|
2016-07-18 07:48:37 -05:00
|
|
|
} else {
|
|
|
|
if (isSourceHook)
|
2016-07-30 05:15:49 -05:00
|
|
|
lengths[depth] += _gcell->getYMax() - segment->getSourceY();
|
2016-07-18 07:48:37 -05:00
|
|
|
else
|
2016-07-30 05:15:49 -05:00
|
|
|
lengths[depth] += segment->getTargetY() - _gcell->getYMin();
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Box AutoContact::getNativeConstraintBox () const
|
|
|
|
{
|
|
|
|
if (isUserNativeConstraints()) return getConstraintBox();
|
|
|
|
if (isFixed()) return Box(_contact->getPosition());
|
2016-08-27 08:59:12 -05:00
|
|
|
return _gcell->getConstraintBox();
|
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
|
|
|
Interval AutoContact::getNativeUConstraints ( Flags direction ) const
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
Interval AutoContact::getUConstraints ( Flags direction ) const
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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 AutoContact::invalidate ( Flags flags )
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
|
|
|
if (not isInvalidated()) {
|
|
|
|
cdebug_log(145,1) << "AutoContact::invalidate() - " << this << endl;
|
|
|
|
setFlags( CntInvalidated );
|
|
|
|
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
|
|
|
|
Session::invalidate( this );
|
|
|
|
|
|
|
|
_invalidate( flags );
|
|
|
|
|
|
|
|
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() );
|
2016-09-22 07:16:53 -05:00
|
|
|
_xMin = _gcell->getXMin();
|
|
|
|
_yMin = _gcell->getYMin();
|
|
|
|
_xMax = _gcell->getConstraintXMax();
|
|
|
|
_yMax = _gcell->getConstraintYMax();
|
Solve the template lookup problem in tstream.
* Bug: In Hurricane, in tstream (Commons.h), in the *template* overload of
operator<<(), do not use the operator<<() of ostream as it will be
looked up in "stage 1" (template definition) and so will miss all the
overloads added later and built over getString<>(). Instead, make use
of getString<>(), which, as another template will be looked up in
"stage 2" (template instanciation) and at that point will have all the
needed template specialisation of getString<>().
We also need to define new stream manipulators to be able to create
a matching template overload not dependant from the implementation.
To avoid name clashes, we prefix a 't'. For now, only 'tsetw()' is
refined.
As a side effect, we cannot directly print bit-fields into the stream,
we must go through an intermediate variable (happens once in AutoContact).
2016-07-19 09:02:55 -05:00
|
|
|
if (cdebug.enabled()) {
|
2016-09-22 07:16:53 -05:00
|
|
|
cdebug_log(145,0) << "* deltas: [" << DbU::getValueString(_xMin)
|
|
|
|
<< " " << DbU::getValueString(_yMin)
|
|
|
|
<< " " << DbU::getValueString(_xMax)
|
|
|
|
<< " " << DbU::getValueString(_yMax)
|
|
|
|
<< "]" << endl;
|
Solve the template lookup problem in tstream.
* Bug: In Hurricane, in tstream (Commons.h), in the *template* overload of
operator<<(), do not use the operator<<() of ostream as it will be
looked up in "stage 1" (template definition) and so will miss all the
overloads added later and built over getString<>(). Instead, make use
of getString<>(), which, as another template will be looked up in
"stage 2" (template instanciation) and at that point will have all the
needed template specialisation of getString<>().
We also need to define new stream manipulators to be able to create
a matching template overload not dependant from the implementation.
To avoid name clashes, we prefix a 't'. For now, only 'tsetw()' is
refined.
As a side effect, we cannot directly print bit-fields into the stream,
we must go through an intermediate variable (happens once in AutoContact).
2016-07-19 09:02:55 -05:00
|
|
|
}
|
2016-07-18 07:48:37 -05:00
|
|
|
} 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();
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
for ( Component* component : support->getSlaveComponents() ) {
|
|
|
|
Horizontal* h = dynamic_cast<Horizontal*>(component);
|
2016-07-18 07:48:37 -05:00
|
|
|
if (h != NULL) {
|
|
|
|
if (hcount < size) horizontals[hcount++] = h;
|
|
|
|
} else {
|
2016-07-30 05:15:49 -05:00
|
|
|
Vertical* v = dynamic_cast<Vertical*>(component);
|
2016-07-18 07:48:37 -05:00
|
|
|
if ( (v != NULL) and (vcount < size) ) verticals[vcount++] = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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 AutoContact::showTopologyError ( const std::string& message, Flags flags )
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-05 16:43:07 -05:00
|
|
|
void AutoContact::forceOnGrid ( Point )
|
|
|
|
{
|
|
|
|
cerr << Warning( "AutoContact::forcedOnGrid() not implemented for this derived class.\n"
|
|
|
|
" %s\n"
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
bool AutoContact::isTee ( Flags direction ) const
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
for ( AutoSegment* segment : const_cast<AutoContact*>(this)->getAutoSegments() ) {
|
|
|
|
if (segment == moved) continue;
|
2016-07-18 07:48:37 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
size_t depth = rg->getLayerDepth(segment->getLayer());
|
2016-07-18 07:48:37 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
bool AutoContact::restrictConstraintBox ( DbU::Unit constraintMin
|
|
|
|
, DbU::Unit constraintMax
|
|
|
|
, Flags flags
|
2016-07-18 07:48:37 -05:00
|
|
|
)
|
|
|
|
{
|
|
|
|
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() )
|
2016-09-22 07:16:53 -05:00
|
|
|
cerr << Error ( "(constraintMin > CBYMax : %s > %s)"
|
|
|
|
, DbU::getValueString(constraintMin).c_str()
|
|
|
|
, DbU::getValueString(getCBYMax()).c_str() )
|
2016-07-18 07:48:37 -05:00
|
|
|
<< endl;
|
|
|
|
if ( constraintMax < getCBYMin() )
|
2016-09-22 07:16:53 -05:00
|
|
|
cerr << Error ( "(constraintMax < CBYMin : %s < %s)"
|
|
|
|
, DbU::getValueString(constraintMax).c_str()
|
|
|
|
, DbU::getValueString(getCBYMin()).c_str() )
|
2016-07-18 07:48:37 -05:00
|
|
|
<< 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() )
|
2016-09-22 07:16:53 -05:00
|
|
|
cerr << Error ( "(constraintMin > CBXMax : %s > %s)"
|
|
|
|
, DbU::getValueString(constraintMin).c_str()
|
|
|
|
, DbU::getValueString(getCBXMax()).c_str() )
|
2016-07-18 07:48:37 -05:00
|
|
|
<< endl;
|
|
|
|
if ( constraintMax < getCBXMin() )
|
2016-09-22 07:16:53 -05:00
|
|
|
cerr << Error ( "(constraintMax < CBXMin : %s < %s)"
|
|
|
|
, DbU::getValueString(constraintMax).c_str()
|
|
|
|
, DbU::getValueString(getCBXMin()).c_str() )
|
2016-07-18 07:48:37 -05:00
|
|
|
<< 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.
|