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 );
|
Update the channel routing feature to integrate with the OTC P&R.
* Update: In CRL/node600/phenitec/kite.py, update the routing gauge to
the new format. So now we can use again SxLib-2M (channel routing
SxLib for two metal technologies).
* Change: In CRL::BlifParser, if a master cell is not found in the
AllianceFramework, then try in the Blif supplied libraries.
This is used to load the zero, one and tie cells.
Add a Blif::getCell() static function to look into the Blif
supplied libraries.
* Change: In CRL::LefImport, sometimes there can be discrepencies between
the LEF ROUTING layers and the Coriolis routing gauge. Now ignore
routing layers that are *not* presents in the Coriolis gauge.
* Change: In AnabaticEngine, moved routingMode attribute from KatanaEngine,
as some setup operations needs it.
* Change: In AutoSegment::canReduce(), allow fixed segments to be reduced
if they are "jumpers" (turn+turn and top+top or bot+bot).
This case arise on the edge of routing channels for fixed wires
to connect terminals.
* Change: In AutoSegment::getTopologicalinfos(), compute differently the
(leftBound,rightBound) interval when in channel mode.
In over-the-cell mode, this interval is the one of the whole
GCells under the wire. In channel mode, for fixed wires (that is,
verticals connecteds to cells) this interval is reduced to half
the GCell height, on the connected side of said channel.
This allows Manipulator::_insertToTrack() to issue disantangling
requests (push left/push right) for fixed segments that are face
to face in the channel.
* Change: In Anabatic::Configuration CTOR, allow the cellGauge to have a
different name from the routingGauge. Now if the cell gauge that
should match the routing gauge is not found, fallback to the
name set in "anabatic.cellGauge" parameter.
Case occur when we try to match with CORE sites from LEF files.
* Change: In Etesian::Configuration CTOR, same change as in the
Anabatic configuration.
* Change: In Anabatic::GCell::updateDensity(), never set the GoStraight
flag in channel mode. This flag makes sense when there is at least
4 routing layers (so we have 2 contiguous free of blockages).
* Bug: In Anabatic::Session::_getNearestGridpoint(), sometimes the nearest on
grid point is outside the constraint box. Now force the point
to remains inside constraints even if offgrid.
* Change: In Katana::DataNegociate::update(), perpandiculars that are
either reduced or in non-preferred routing direction should not
trigger a bug message.
* Change: In KatanaEngine::_check(), do not check for fixed, horizontal
non-prefs AutoSegments in channel mode (avoid false bug display).
* Bug: In Manipulator::_forceToTrack(), slighty shrink (-1) the interval
to free. The intersection function of intervals returns true when
the two intervals *exactly* touches (1.vMax == 2.vMin). But in
this specific case, they are not *overlapping* and no action
should be taken...
* Bug: In Manipulator::_insertInTrack(), do not reject the track when
we are overlapping a fixed vertical segment in channel mode.
(Hmm, maybe already corrected by the previous one).
* Change: In Katana::NegociateOverlapCost(), in channel mode, do
not put two overlaping vertical fixed segments into infinite cost.
This happens when two cell connected verticals are face to face in
a channel. We want them negociated the track (by shrinking their
length) instead of excluding it right away.
* Change: In NegociateWindow::createTrackSegment(), in channel mode,
do not attempt to create a track segment over a fixed and reduced
AutoSegment.
Do not attempt to put a non-preferred AutoSegment on a Track
either.
* Bug: In RoutingEvent::revalidate(), the number of availables tracks
was badly computed when in the pure constraint case, when there
was only one it was reporting zero.
* Change: In TrackElements::TrackElements_Perpandicular::Locator,
do not issue a bug when an non-pref or reduced AutoSegment do not
have an associated TrackElement.
* Change: In TrackSegmentCost::update(), do not issue a bug when a
perpandicular is reduded or non-pref and do not have a TrackElement.
2022-10-22 09:39:22 -05:00
|
|
|
AutoSegment* dogleg = AutoSegment::create( contact1 , contact2, Flags::Horizontal|Flags::UseNonPref );
|
2017-12-18 11:15:14 -06:00
|
|
|
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.
|