2017-12-18 11:15:14 -06:00
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
2018-01-06 10:55:44 -06:00
|
|
|
// Copyright (c) UPMC 2008-2018, All Rights Reserved
|
2017-12-18 11:15:14 -06: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 : "./NetBuilderM2.cpp" |
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <sstream>
|
|
|
|
#include "hurricane/Bug.h"
|
|
|
|
#include "hurricane/Breakpoint.h"
|
|
|
|
#include "hurricane/Error.h"
|
|
|
|
#include "hurricane/Warning.h"
|
|
|
|
#include "hurricane/DebugSession.h"
|
|
|
|
#include "hurricane/Layer.h"
|
|
|
|
#include "hurricane/BasicLayer.h"
|
|
|
|
#include "hurricane/RegularLayer.h"
|
|
|
|
#include "hurricane/Technology.h"
|
|
|
|
#include "hurricane/DataBase.h"
|
|
|
|
#include "hurricane/Net.h"
|
|
|
|
#include "hurricane/NetExternalComponents.h"
|
|
|
|
#include "hurricane/NetRoutingProperty.h"
|
|
|
|
#include "hurricane/RoutingPad.h"
|
|
|
|
#include "hurricane/RoutingPads.h"
|
|
|
|
#include "hurricane/Pad.h"
|
|
|
|
#include "hurricane/Plug.h"
|
|
|
|
#include "hurricane/Cell.h"
|
|
|
|
#include "hurricane/Instance.h"
|
|
|
|
#include "hurricane/Vertical.h"
|
|
|
|
#include "hurricane/Horizontal.h"
|
|
|
|
#include "crlcore/AllianceFramework.h"
|
|
|
|
#include "crlcore/RoutingGauge.h"
|
|
|
|
#include "crlcore/Measures.h"
|
|
|
|
#include "anabatic/AutoContactTerminal.h"
|
|
|
|
#include "anabatic/AutoContactTurn.h"
|
|
|
|
#include "anabatic/AutoContactHTee.h"
|
|
|
|
#include "anabatic/AutoContactVTee.h"
|
|
|
|
#include "anabatic/AutoSegment.h"
|
|
|
|
#include "anabatic/NetBuilderM2.h"
|
|
|
|
#include "anabatic/AnabaticEngine.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace Anabatic {
|
|
|
|
|
|
|
|
using std::swap;
|
|
|
|
|
|
|
|
|
|
|
|
NetBuilderM2::NetBuilderM2 ()
|
|
|
|
: NetBuilder()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
NetBuilderM2::~NetBuilderM2 () { }
|
|
|
|
|
|
|
|
|
|
|
|
void NetBuilderM2::doRp_AutoContacts ( GCell* gcell
|
|
|
|
, Component* rp
|
|
|
|
, AutoContact*& source
|
|
|
|
, AutoContact*& target
|
|
|
|
, uint64_t flags
|
|
|
|
)
|
|
|
|
{
|
|
|
|
cdebug_log(145,1) << "NetBuilderM2::doRp_AutoContacts()" << endl;
|
|
|
|
cdebug_log(145,0) << rp << endl;
|
|
|
|
|
|
|
|
source = target = NULL;
|
|
|
|
|
|
|
|
Point sourcePosition;
|
|
|
|
Point targetPosition;
|
|
|
|
const Layer* rpLayer = rp->getLayer();
|
|
|
|
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
|
|
|
|
Flags direction = Session::getDirection ( rpDepth );
|
|
|
|
DbU::Unit viaSide = Session::getViaWidth ( rpDepth );
|
|
|
|
|
|
|
|
getPositions( rp, sourcePosition, targetPosition );
|
|
|
|
|
|
|
|
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
|
|
|
|
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
|
|
|
|
|
|
|
|
GCell* sourceGCell = Session::getAnabatic()->getGCellUnder( sourcePosition );
|
|
|
|
GCell* targetGCell = Session::getAnabatic()->getGCellUnder( targetPosition );
|
|
|
|
|
|
|
|
if (rpDepth == 0) {
|
|
|
|
rpLayer = Session::getContactLayer(0);
|
|
|
|
direction = Flags::Horizontal;
|
|
|
|
viaSide = Session::getViaWidth( rpDepth );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Non-M1 terminal or punctual M1 protections.
|
|
|
|
if ((rpDepth != 0) or (sourcePosition == targetPosition)) {
|
|
|
|
map<Component*,AutoSegment*>::iterator irp = getRpLookup().find( rp );
|
|
|
|
if (irp == getRpLookup().end()) {
|
|
|
|
AutoContact* sourceProtect = AutoContactTerminal::create( sourceGCell
|
|
|
|
, rp
|
|
|
|
, rpLayer
|
|
|
|
, sourcePosition
|
|
|
|
, viaSide, viaSide
|
|
|
|
);
|
|
|
|
AutoContact* targetProtect = AutoContactTerminal::create( targetGCell
|
|
|
|
, rp
|
|
|
|
, rpLayer
|
|
|
|
, targetPosition
|
|
|
|
, viaSide, viaSide
|
|
|
|
);
|
|
|
|
sourceProtect->setFlags( CntFixed );
|
|
|
|
targetProtect->setFlags( CntFixed );
|
|
|
|
|
|
|
|
AutoSegment* segment = AutoSegment::create( sourceProtect, targetProtect, direction );
|
|
|
|
segment->setFlags( AutoSegment::SegFixed );
|
|
|
|
|
|
|
|
getRpLookup().insert( make_pair(rp,segment) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sourcePosition != targetPosition) {
|
|
|
|
if (flags & DoSourceContact)
|
|
|
|
source = AutoContactTerminal::create( sourceGCell
|
|
|
|
, rp
|
|
|
|
, rpLayer
|
|
|
|
, sourcePosition
|
|
|
|
, viaSide, viaSide
|
|
|
|
);
|
|
|
|
if (flags & DoTargetContact)
|
|
|
|
target = AutoContactTerminal::create( targetGCell
|
|
|
|
, rp
|
|
|
|
, rpLayer
|
|
|
|
, targetPosition
|
|
|
|
, viaSide, viaSide
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not source and not target) {
|
|
|
|
source = target = AutoContactTerminal::create( gcell
|
|
|
|
, rp
|
|
|
|
, rpLayer
|
|
|
|
, rp->getCenter()
|
|
|
|
, viaSide, viaSide
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
cdebug_tabw(145,-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoContact* NetBuilderM2::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
|
|
|
|
{
|
|
|
|
cdebug_log(145,1) << getTypeName() << "::doRp_Access()" << endl;
|
|
|
|
cdebug_log(145,0) << rp << endl;
|
|
|
|
|
|
|
|
Point sourcePosition;
|
|
|
|
Point targetPosition;
|
|
|
|
const Layer* rpLayer = rp->getLayer();
|
|
|
|
const Layer* viaLayer = Session::getDContactLayer();
|
|
|
|
DbU::Unit viaSide = Session::getDContactWidth();
|
|
|
|
DbU::Unit ypitch = Session::getDVerticalPitch();
|
|
|
|
|
|
|
|
getPositions( rp, sourcePosition, targetPosition );
|
|
|
|
|
|
|
|
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
|
|
|
|
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
|
|
|
|
|
|
|
|
Point position = rp->getCenter();
|
|
|
|
if (not (flags & Middle)) {
|
|
|
|
if (flags & NorthBound) position = targetPosition;
|
|
|
|
if (flags & SouthBound) position = sourcePosition;
|
|
|
|
}
|
|
|
|
|
|
|
|
DbU::Unit ycontact = (flags & SouthBound) ? gcell->getYMin() : gcell->getYMax()-ypitch;
|
|
|
|
|
|
|
|
AutoContact* rpContact = AutoContactTerminal::create( gcell, rp, rpLayer, position, viaSide, viaSide );
|
|
|
|
AutoContact* contact1 = AutoContactTurn::create( gcell, getNet(), viaLayer );
|
|
|
|
AutoContact* contact2 = AutoContactTurn::create( gcell, getNet(), viaLayer );
|
|
|
|
contact1->setPosition( position.getX(), ycontact );
|
|
|
|
contact2->setPosition( position.getX(), ycontact );
|
|
|
|
rpContact->setFlags( CntFixed );
|
|
|
|
contact1 ->setFlags( CntFixed );
|
|
|
|
contact2 ->setFlags( CntFixed );
|
|
|
|
|
|
|
|
AutoSegment* fixed = AutoSegment::create( rpContact, contact1, Flags::Vertical );
|
|
|
|
AutoSegment* dogleg = AutoSegment::create( contact1 , contact2, Flags::Horizontal );
|
|
|
|
fixed ->setFlags( AutoSegment::SegFixed );
|
|
|
|
dogleg->setFlags( AutoSegment::SegFixed );
|
|
|
|
|
|
|
|
cdebug_tabw(145,-1);
|
|
|
|
return contact2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool NetBuilderM2::_do_1G_1M1 ()
|
|
|
|
{
|
|
|
|
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1()" << endl;
|
|
|
|
|
|
|
|
uint64_t flags = NoFlags;
|
|
|
|
if (north()) flags |= NorthBound;
|
|
|
|
else if (south()) flags |= SouthBound;
|
|
|
|
|
|
|
|
AutoContact* contact = NULL;
|
|
|
|
contact = doRp_Access( getGCell(), getRoutingPads()[0], flags );
|
|
|
|
setNorthEastContact( contact );
|
|
|
|
push( north(), contact, SouthWest );
|
|
|
|
push( south(), contact, SouthWest );
|
|
|
|
|
|
|
|
cdebug_tabw(145,-1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool NetBuilderM2::_do_2G_1M1 ()
|
|
|
|
{
|
|
|
|
cdebug_log(145,1) << getTypeName() << "::_do_2G_1M1()" << endl;
|
|
|
|
|
|
|
|
AutoContact* contact = NULL;
|
|
|
|
contact = doRp_Access( getGCell(), getRoutingPads()[0], SouthBound|NorthBound );
|
|
|
|
push( north(), contact, SouthWest|Middle );
|
|
|
|
|
|
|
|
contact = doRp_Access( getGCell(), getRoutingPads()[0], SouthBound|NorthBound );
|
|
|
|
push( south(), contact, SouthWest|Middle );
|
|
|
|
|
|
|
|
cdebug_tabw(145,-1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool NetBuilderM2::_do_xG ()
|
|
|
|
{
|
|
|
|
cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl;
|
|
|
|
|
|
|
|
vector<Hook*> hooksNS = getNorths();
|
|
|
|
hooksNS.insert( hooksNS.end(), getSouths().begin(), getSouths().end() );
|
In Anabatic/Katana, add support for VH gauges (real technos).
* Change: In Anabatic::AutoContactTerminal::getNativeConstraintBox(),
when the anchor is a RoutingPad (which must be always the case),
perform the true computation of it's position based on the
segment occurrence. It is a important change, previously the
area was in fact the "center line" of the connector while now
it is really an area (mandatory for "half-offgrid" terminals of
real technologies).
The change is not complete yet, the area should be shrinked
by the half size of a VIA, because the area applies to the center
coordinate of the VIA (to be done quickly).
* Bug: In Anabatic::AutoContactTurn::updateTopology(), when a dogleg
is created (restore connexity after a layer change) the layer of
the VIA, based on the segments it connects to must be re-computed
*after* the dogleg has been made.
* Change: In all files of Anabatic, when comparing two layers, no longer
use the Layer pointer itself, but the layer mask. This allow a
transparent management of both real and symbolic layers (which
do share the same mask). Real metal layers (not VIAs) will be
BasicLayer and symbolic metal layers will be RegularLayer.
* New: Anabatic::Configuration::selectRpComponent(), select the best
RoutingPad component for metal1 terminals. Look for the metal1
component with the biggest accessibility on-grid.
RoutingPad using other metals are left untoucheds.
* New: New function Anabatic::Vertex::getNeighbor(Edge*) to get the
neighbor Vertex through an Edge*. This method allows to write
clearer code as we no longer need to access the neighbor through
the underlying GCell.
Also add proxies for GCell methods in Vertex.
* Bug: In Anabatic::Dijkstra::_toSources(), in the ripup stage, when
a component with multiples vertexes is reached *and* two of it's
vertexes are reached *at the same time* (one from which we backtrack
and one still in the queue) extraneous edges may be created by
_materialize(). Case occurs on snx/c35b4, "abc_5360_n903_1".
To solve this, Dijkstra::_toSource() is modificated, the "from"
edges of the newly reacheds vertexes are reset to NULL, *except*
for the one we will be backtracking from. That is, the one given
in the source argument.
* Change: In Anabatic::NetBuilder class, put the various Hooks and
RoutingPad sorting functions as class ones.
* Bug: In AutoSegment::setLayer(), raise the SegInvalidatedFayer flag.
This unset flag was causing AutoContactTurn::updateTopology()
to not work as expected and making gaps, this was the cause of
the last remaining warnings about layer connexity.
2018-01-06 09:55:53 -06:00
|
|
|
sortHookByX( hooksNS, NoFlags );
|
2017-12-18 11:15:14 -06:00
|
|
|
|
|
|
|
const Layer* viaLayer = Session::getDContactLayer();
|
|
|
|
AutoContact* contactW = NULL;
|
|
|
|
AutoContact* contactE = NULL;
|
|
|
|
|
|
|
|
// Simple turn.
|
|
|
|
if ( (west() and not east() and (hooksNS.size() == 1))
|
|
|
|
or (east() and not west() and (hooksNS.size() == 1)) ) {
|
|
|
|
contactW = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
|
|
|
|
push( west() , contactW, SouthWest );
|
|
|
|
push( east() , contactW, SouthWest );
|
|
|
|
push( hooksNS[0], contactW, SouthWest );
|
|
|
|
cdebug_tabw(145,-1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Simple HTee.
|
|
|
|
if (west() and east() and (hooksNS.size() == 1)) {
|
|
|
|
contactW = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
|
|
|
|
push( west() , contactW, SouthWest );
|
|
|
|
push( east() , contactW, SouthWest );
|
|
|
|
push( hooksNS[0], contactW, SouthWest );
|
|
|
|
cdebug_tabw(145,-1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
cdebug_log(145,0) << "West side processing." << endl;
|
|
|
|
// West side processing.
|
|
|
|
if (west()) {
|
|
|
|
contactW = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
|
|
|
|
push( west() , contactW, SouthWest );
|
|
|
|
push( hooksNS[0], contactW, SouthWest );
|
|
|
|
} else {
|
|
|
|
contactW = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
|
|
|
|
push( hooksNS[0], contactW, SouthWest );
|
|
|
|
}
|
|
|
|
|
|
|
|
cdebug_log(145,0) << "Middle processing." << endl;
|
|
|
|
// Middle (North & South) processing.
|
|
|
|
if (hooksNS.size() > 2) {
|
|
|
|
for ( size_t i=1 ; i<hooksNS.size()-1 ; ++i ) {
|
|
|
|
AutoContact* current = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
|
|
|
|
AutoSegment::create( contactW, current, Flags::Horizontal );
|
|
|
|
push( hooksNS[i], current, SouthWest );
|
|
|
|
|
|
|
|
contactW = current;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cdebug_log(145,0) << "East side processing." << endl;
|
|
|
|
// East side processing.
|
|
|
|
if (east()) {
|
|
|
|
contactE = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
|
|
|
|
push( east(), contactE, SouthWest );
|
|
|
|
if (hooksNS.size() > 1)
|
|
|
|
push( hooksNS[hooksNS.size()-1], contactE, SouthWest );
|
|
|
|
} else {
|
|
|
|
contactE = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
|
|
|
|
push( hooksNS[hooksNS.size()-1], contactE, SouthWest );
|
|
|
|
}
|
|
|
|
|
|
|
|
AutoSegment::create( contactW, contactE, Flags::Horizontal );
|
|
|
|
|
|
|
|
cdebug_tabw(145,-1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool NetBuilderM2::_do_globalSegment ()
|
|
|
|
{
|
|
|
|
cdebug_log(145,1) << getTypeName() << "::_do_globalSegment()" << endl;
|
|
|
|
|
|
|
|
if (getSourceContact()) {
|
|
|
|
Segment* segment = static_cast <Segment*> ( getFromHook()->getComponent() );
|
|
|
|
AutoSegment* globalSegment = AutoSegment::create( getSourceContact(), getSouthWestContact(), segment );
|
|
|
|
|
|
|
|
globalSegment->setFlags( (getDegree() == 2) ? AutoSegment::SegBipoint : 0 );
|
|
|
|
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
|
|
|
|
|
|
|
|
// HARDCODED VALUE.
|
Rewrite support for minimum area metal wires (stacked VIAs).
We use the segments extensions (dxTarget & dyTarget) to enlarge if
needed the segments. This new implementation is completely at
Anabatic level and should not be seen (i.e. managed) at Katana level.
* Change: In AutoHorizontal & AutoVertical, change the semantic of
getSourceU() and getTargetU(). formerly they where the end
position of the segment (with extension included), now they
gives the position of the anchor contacts, that is the axis
of the perpandiculars.
* New: AutoSegment::getLength() is still a proxy toward the
Segment::getLength() which returns the length of segment with
dxSource & dxTarget. We introduce a getAnchoredlength()
which returns the length between the centers of the S/T
anchors. That is axis to axis.
This is this length which is now used througout Anabatic.
* New: In AutoSegment::_extentionCaps, add a fourth item to hold
the segment minimal length (to respect minimal area given
the wire width).
* New: In AutoSegment::getExtensionCap(), if the segment has
a non-zero S/T extension, returns it instead of the S/T
contact extension *if it is greated*. The check of the
extension can be disabled by the Flag::NoSegExt flag.
* Change: In AutoSegment::isMiddleStack(), security check on
the presence of source and targets. More accurate detection
of perpandicular in "same layer" with a non-zero length,
So the area is OK, even with a short segment.
* New: AutoSegment::expandToMinLength(), check if a segment is
under the minimal length and expand it if need be by playing
with the dxTarget & dxSource. Tag minimal segments with the
AutoSegment::SegAtMinArea flag. Also try to keep the segment
*inside* it's former (supposedly wider) interval.
* New: AutoSegment::unexpandToMinLength(), to be called on a
formerly minimal sized segment which as grown up. Reset
it's S/T extensions to zero and unset the flag SegAtMinArea.
* Change: In AutoHorizontal::updateOrient(), when the extension
are non-zero, also swap them if needed, to keep the exact
footprint of the segment.
* New: In AutoSegment::revalidate(), check that the segment
respect the minimal length (area), and expand it if needed.
Conversely, if the segment has grown up from a minimal
length state, reset it's extensions to zero.
* Change: In Anabatic::Session::revalidate(), invalidateds
segments are now sorted in such a way that the "middle stack"
ones are revalidateds last. Not recall 100% why...
* New: In Katana::TrackCost, add a computation of the free interval
length we are into (if any). Not used yet, keep it for future
use.
* Change: In KatanaEngine::finalizeLayout(), remove the call to
segments minimum area protection. It is now obsoleted by the
new implementation in Anabatic.
* Change: In Track::check(), call the minimum size/area checker
Track::checkMinArea().
2021-04-04 17:01:54 -05:00
|
|
|
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
|
2017-12-18 11:15:14 -06:00
|
|
|
addToFixSegments( globalSegment );
|
|
|
|
|
In Anabatic/Katana, add support for VH gauges (real technos).
* Change: In Anabatic::AutoContactTerminal::getNativeConstraintBox(),
when the anchor is a RoutingPad (which must be always the case),
perform the true computation of it's position based on the
segment occurrence. It is a important change, previously the
area was in fact the "center line" of the connector while now
it is really an area (mandatory for "half-offgrid" terminals of
real technologies).
The change is not complete yet, the area should be shrinked
by the half size of a VIA, because the area applies to the center
coordinate of the VIA (to be done quickly).
* Bug: In Anabatic::AutoContactTurn::updateTopology(), when a dogleg
is created (restore connexity after a layer change) the layer of
the VIA, based on the segments it connects to must be re-computed
*after* the dogleg has been made.
* Change: In all files of Anabatic, when comparing two layers, no longer
use the Layer pointer itself, but the layer mask. This allow a
transparent management of both real and symbolic layers (which
do share the same mask). Real metal layers (not VIAs) will be
BasicLayer and symbolic metal layers will be RegularLayer.
* New: Anabatic::Configuration::selectRpComponent(), select the best
RoutingPad component for metal1 terminals. Look for the metal1
component with the biggest accessibility on-grid.
RoutingPad using other metals are left untoucheds.
* New: New function Anabatic::Vertex::getNeighbor(Edge*) to get the
neighbor Vertex through an Edge*. This method allows to write
clearer code as we no longer need to access the neighbor through
the underlying GCell.
Also add proxies for GCell methods in Vertex.
* Bug: In Anabatic::Dijkstra::_toSources(), in the ripup stage, when
a component with multiples vertexes is reached *and* two of it's
vertexes are reached *at the same time* (one from which we backtrack
and one still in the queue) extraneous edges may be created by
_materialize(). Case occurs on snx/c35b4, "abc_5360_n903_1".
To solve this, Dijkstra::_toSource() is modificated, the "from"
edges of the newly reacheds vertexes are reset to NULL, *except*
for the one we will be backtracking from. That is, the one given
in the source argument.
* Change: In Anabatic::NetBuilder class, put the various Hooks and
RoutingPad sorting functions as class ones.
* Bug: In AutoSegment::setLayer(), raise the SegInvalidatedFayer flag.
This unset flag was causing AutoContactTurn::updateTopology()
to not work as expected and making gaps, this was the cause of
the last remaining warnings about layer connexity.
2018-01-06 09:55:53 -06:00
|
|
|
if (getConnexity().fields.globals < 2) {
|
|
|
|
cdebug_tabw(145,-1);
|
|
|
|
return false;
|
|
|
|
}
|
2017-12-18 11:15:14 -06:00
|
|
|
} else
|
|
|
|
setFromHook( NULL );
|
|
|
|
|
In Anabatic/Katana, add support for VH gauges (real technos).
* Change: In Anabatic::AutoContactTerminal::getNativeConstraintBox(),
when the anchor is a RoutingPad (which must be always the case),
perform the true computation of it's position based on the
segment occurrence. It is a important change, previously the
area was in fact the "center line" of the connector while now
it is really an area (mandatory for "half-offgrid" terminals of
real technologies).
The change is not complete yet, the area should be shrinked
by the half size of a VIA, because the area applies to the center
coordinate of the VIA (to be done quickly).
* Bug: In Anabatic::AutoContactTurn::updateTopology(), when a dogleg
is created (restore connexity after a layer change) the layer of
the VIA, based on the segments it connects to must be re-computed
*after* the dogleg has been made.
* Change: In all files of Anabatic, when comparing two layers, no longer
use the Layer pointer itself, but the layer mask. This allow a
transparent management of both real and symbolic layers (which
do share the same mask). Real metal layers (not VIAs) will be
BasicLayer and symbolic metal layers will be RegularLayer.
* New: Anabatic::Configuration::selectRpComponent(), select the best
RoutingPad component for metal1 terminals. Look for the metal1
component with the biggest accessibility on-grid.
RoutingPad using other metals are left untoucheds.
* New: New function Anabatic::Vertex::getNeighbor(Edge*) to get the
neighbor Vertex through an Edge*. This method allows to write
clearer code as we no longer need to access the neighbor through
the underlying GCell.
Also add proxies for GCell methods in Vertex.
* Bug: In Anabatic::Dijkstra::_toSources(), in the ripup stage, when
a component with multiples vertexes is reached *and* two of it's
vertexes are reached *at the same time* (one from which we backtrack
and one still in the queue) extraneous edges may be created by
_materialize(). Case occurs on snx/c35b4, "abc_5360_n903_1".
To solve this, Dijkstra::_toSource() is modificated, the "from"
edges of the newly reacheds vertexes are reset to NULL, *except*
for the one we will be backtracking from. That is, the one given
in the source argument.
* Change: In Anabatic::NetBuilder class, put the various Hooks and
RoutingPad sorting functions as class ones.
* Bug: In AutoSegment::setLayer(), raise the SegInvalidatedFayer flag.
This unset flag was causing AutoContactTurn::updateTopology()
to not work as expected and making gaps, this was the cause of
the last remaining warnings about layer connexity.
2018-01-06 09:55:53 -06:00
|
|
|
cdebug_tabw(145,-1);
|
2017-12-18 11:15:14 -06:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool NetBuilderM2::_do_1G_xM1 () { return false; }
|
|
|
|
bool NetBuilderM2::_do_xG_1Pad () { return false; }
|
|
|
|
bool NetBuilderM2::_do_1G_1PinM2 () { return false; }
|
|
|
|
bool NetBuilderM2::_do_xG_xM2 () { return false; }
|
|
|
|
bool NetBuilderM2::_do_1G_1M3 () { return false; }
|
|
|
|
bool NetBuilderM2::_do_xG_xM3 () { return false; }
|
|
|
|
bool NetBuilderM2::_do_xG_1M1_1M2 () { return false; }
|
|
|
|
bool NetBuilderM2::_do_xG_xM1_xM3 () { return false; }
|
|
|
|
bool NetBuilderM2::_do_4G_1M2 () { return false; }
|
|
|
|
bool NetBuilderM2::_do_2G () { return false; }
|
|
|
|
|
|
|
|
|
|
|
|
string NetBuilderM2::getTypeName () const
|
|
|
|
{ return "NetBuilderM2"; }
|
|
|
|
|
|
|
|
|
|
|
|
} // Anabatic namespace.
|