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 : "./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 )
|
|
|
|
{
|
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
|
|
|
|
);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Basic support for FreePDK 45 completed.
* New: In Commons, inspector support for std::pair<T,U>.
* New: In Hurricane::Layer, ContactLayer & ViaLayer, support for non
square VIAs. The hole (cut) remains square, but the various metal
extensions can now be different in X and Y. The ::getEnclosure()
method now takes a flag EnclosureH / EnclosureV.
* New: In Hurricane::DbU, inspector support for:
std::pair<DbU::Unit,DbU::Unit>
std::array<DbU::Unit,3>
Must be defined here as DbU do not exists yet in Commons.h
* Bug: In Hurricane::Interval::getSize(), when the interval is "full span",
do not return the difference between min and max, but directly DbU::Max.
(the previous result was -1 !)
* New: In CRL Core Python/Technology.py, support for non square VIAs in
the configuration files. Applied to FreePDK 45.
* New: In CRL::RoutingGauge, added a "symbolic" flag to tell if a gauge
is for symbolic layout or not. Exported to Python.
* New: In Anabatic::AutoHorizontal::updatePosition(), differentiated
computation for soure or target taking account of the VIA extension
in the right segment metal (due to non-square VIAs).
* Change: In Anabatic::AutoHorizontal::_makeDogleg(), the dogleg is
UP for HV gauges and DOWN for VH.
* New: In Anabatic::AutoSegment::_initialize(), create a cache of the
various extension length for each layer (viaToTop, viaToBottom,
viaToSame).
New implementation of getExtensionCap() using the previous cached
extension table. See updatePositions().
New static functions to access the extension cache in the header:
getViaTotopCap() ...
* Change: In Anabatic::AutoSegment, in various update methods, updateOrient()
must always be called *before* updatePositions() as extensions are
dependant on source/target.
* New: In Anabatic::AutoSegment::getEndAxes() compute the position of the
first source and last target position (center/axes) on an *aligned*
set of segments.
* New: In Anabatic::AutoSegment, add a new state flag SegAxisFixed to
signal segments that can be put on only one track. Specific case
to VH gauge for a M1 vertical terminal with a M2 vertical segment.
The M2 is effectively bound to the M1 axis position.
* Bug: In Anabatic::NetBuilderVH::_do_xG_xM1_xM3(), in case of E/W global
and only one RoutingPad the connexion to the RoutingPad was duplicated.
It was valid, but totally stupid.
* Bug: In Anabatic::Session::_canonize(), for an aligned segment set,
intersect the user constraints from all segments instead of only
considering the canonical one.
Issue a warning about too tight constraints only for symbolic
gauges. It may be correct for the real ones.
* New: In Katata::DataNegociate::update(), more accurate computation
of the perpandicular free interval. Use segment extension cap
calculation. Create a special case for fixed axis segments allowing
them to find alternative free interval, try under source and under
target as they are likely to be draggable segments.
* Change: In Katana::Manipulator::relax(), use the extension cap value
to compute the axis of the perpandicular segemnts.
* Change: In Katana::Manipulator::moveUp(), now move up the whole set
of aligned segments instead of just the canonical one.
* Change: In Katana::NegociateWindow::loadRoutingPads(), more accurate
TrackMarkers insertions for fixed terminals.
* New: In Katana::RoutingEvent::Key::Compare::operator(), segments with
fixed axis are processed prior to any others.
* New: In Katana::RoutingEventLoop, store segment pointers instead of
ids to generate more accurate error messages.
* Change: In Katana::RoutingPlane::create(), perform local track
assignment only for HV gauges.
* Change: In Katana::SegmentFsm::_slackenLocal(), add a "dragMinimize"
step in the automaton. Mutliple states transitions can occurs in
a row if an action fails.
* New: In Katana::Session::_toIntervalAxis(), normalize interval
bounds so they are on track positions (by shrinking the interval).
* Bug: In Katana::TrackMarker CTOR, the weigh computation was wrong.
2018-02-17 13:27:38 -06:00
|
|
|
AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* from ) const
|
|
|
|
{
|
|
|
|
if ( (from == _horizontal1) or (from == _horizontal2) ) return _vertical1;
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-07-18 07:48:37 -05:00
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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* AutoContactHTee::getHorizontal1 () const { return _horizontal1; };
|
|
|
|
AutoHorizontal* AutoContactHTee::getHorizontal2 () const { return _horizontal2; };
|
|
|
|
AutoVertical* AutoContactHTee::getVertical1 () const { return _vertical1; };
|
|
|
|
|
|
|
|
|
2018-03-27 11:03:51 -05:00
|
|
|
void AutoContactHTee::_invalidate ( Flags flags )
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
2018-03-27 11:03:51 -05:00
|
|
|
flags |= Flags::Propagate;
|
2016-07-18 07:48:37 -05:00
|
|
|
if (_horizontal1 and _horizontal2) {
|
|
|
|
if (_horizontal1->isInvalidated() xor _horizontal2->isInvalidated())
|
2018-03-27 11:03:51 -05:00
|
|
|
flags.reset( Flags::Propagate );
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
|
2018-03-27 11:03:51 -05:00
|
|
|
cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl;
|
2016-07-18 07:48:37 -05:00
|
|
|
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() );
|
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 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 ) {
|
In Anabatic, correctly set the wire width according to the routing gauge.
* New: Anabatic::AutoContact::setLayerAndWidth() to set both layer and
VIA width/side according to the RoutingGauge. If the delta in zero,
use the metal gauge, and the VIA gauge otherwise.
* Bug: In Anabatic::AutoContactTerminal, Anabatic::AutoContactTurn,
Anabatic::AutoContactHTee & Anabatic::AutoContactVTee, in the
updateTopology() method, set both the layer and the VIA with when
there is a change of layer. Note that this default size may be
overriden later by updateSeize() in the case of non-default width
segments.
* New: In Anabatic::AutoSegment, new overload setLayer(size_t) to set
both layer and segment with according to the routing gauge.
* Bug: In Anabatic::AutoHorizontal and Anabatic::AutoVertical, in method
_makeDogleg(), make use of the new setLayer() to correctly set up
the wire width.
Idem for Anabatic::AutoSegment::changeDepth() and ::makeDogleg(),
and in Anabatic::LayerAssign.
2019-02-12 05:43:09 -06:00
|
|
|
case 0:
|
|
|
|
case 1: setLayerAndWidth( delta, minDepth ); break;
|
2016-07-18 07:48:37 -05:00
|
|
|
default:
|
In Anabatic, correctly set the wire width according to the routing gauge.
* New: Anabatic::AutoContact::setLayerAndWidth() to set both layer and
VIA width/side according to the RoutingGauge. If the delta in zero,
use the metal gauge, and the VIA gauge otherwise.
* Bug: In Anabatic::AutoContactTerminal, Anabatic::AutoContactTurn,
Anabatic::AutoContactHTee & Anabatic::AutoContactVTee, in the
updateTopology() method, set both the layer and the VIA with when
there is a change of layer. Note that this default size may be
overriden later by updateSeize() in the case of non-default width
segments.
* New: In Anabatic::AutoSegment, new overload setLayer(size_t) to set
both layer and segment with according to the routing gauge.
* Bug: In Anabatic::AutoHorizontal and Anabatic::AutoVertical, in method
_makeDogleg(), make use of the new setLayer() to correctly set up
the wire width.
Idem for Anabatic::AutoSegment::changeDepth() and ::makeDogleg(),
and in Anabatic::LayerAssign.
2019-02-12 05:43:09 -06:00
|
|
|
setLayerAndWidth( delta, depthH1 + ((depthH1==minDepth)?0:-1) );
|
2016-07-18 07:48:37 -05:00
|
|
|
_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)) {
|
In Anabatic, correctly set the wire width according to the routing gauge.
* New: Anabatic::AutoContact::setLayerAndWidth() to set both layer and
VIA width/side according to the RoutingGauge. If the delta in zero,
use the metal gauge, and the VIA gauge otherwise.
* Bug: In Anabatic::AutoContactTerminal, Anabatic::AutoContactTurn,
Anabatic::AutoContactHTee & Anabatic::AutoContactVTee, in the
updateTopology() method, set both the layer and the VIA with when
there is a change of layer. Note that this default size may be
overriden later by updateSeize() in the case of non-default width
segments.
* New: In Anabatic::AutoSegment, new overload setLayer(size_t) to set
both layer and segment with according to the routing gauge.
* Bug: In Anabatic::AutoHorizontal and Anabatic::AutoVertical, in method
_makeDogleg(), make use of the new setLayer() to correctly set up
the wire width.
Idem for Anabatic::AutoSegment::changeDepth() and ::makeDogleg(),
and in Anabatic::LayerAssign.
2019-02-12 05:43:09 -06:00
|
|
|
setLayerAndWidth( 2, depthH2 + ((depthH2<depthV1)?0:-1) );
|
2016-07-18 07:48:37 -05:00
|
|
|
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
|
|
|
|
_horizontal1->makeDogleg(this);
|
|
|
|
cdebug_log(145,0) << "New h1:" << _horizontal1 << endl;
|
|
|
|
} else {
|
In Anabatic, correctly set the wire width according to the routing gauge.
* New: Anabatic::AutoContact::setLayerAndWidth() to set both layer and
VIA width/side according to the RoutingGauge. If the delta in zero,
use the metal gauge, and the VIA gauge otherwise.
* Bug: In Anabatic::AutoContactTerminal, Anabatic::AutoContactTurn,
Anabatic::AutoContactHTee & Anabatic::AutoContactVTee, in the
updateTopology() method, set both the layer and the VIA with when
there is a change of layer. Note that this default size may be
overriden later by updateSeize() in the case of non-default width
segments.
* New: In Anabatic::AutoSegment, new overload setLayer(size_t) to set
both layer and segment with according to the routing gauge.
* Bug: In Anabatic::AutoHorizontal and Anabatic::AutoVertical, in method
_makeDogleg(), make use of the new setLayer() to correctly set up
the wire width.
Idem for Anabatic::AutoSegment::changeDepth() and ::makeDogleg(),
and in Anabatic::LayerAssign.
2019-02-12 05:43:09 -06:00
|
|
|
setLayerAndWidth( 2, depthH1 + ((depthH1<depthV1)?0:-1) );
|
2016-07-18 07:48:37 -05:00
|
|
|
//_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.
|