coriolis/anabatic/src/NetBuilderHV.cpp

1913 lines
80 KiB
C++

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, 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 : "./NetBuilderHV.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/Pin.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/NetBuilderHV.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::swap;
using Hurricane::Transformation;
using Hurricane::Warning;
using Hurricane::Error;
using Hurricane::Pin;
NetBuilderHV::NetBuilderHV ()
: NetBuilder()
{ }
NetBuilderHV::~NetBuilderHV () { }
void NetBuilderHV::doRp_AutoContacts ( GCell* gcell
, Component* rp
, AutoContact*& source
, AutoContact*& target
, uint64_t flags
)
{
cdebug_log(145,1) << getTypeName() << "::doRp_AutoContacts()" << endl;
cdebug_log(145,0) << rp << endl;
RoutingPad* rrp = dynamic_cast<RoutingPad*>( rp );
if (not rrp) {
cerr << Warning( "%s::doRp_AutoContacts(): %s is *not* a RoutingPad."
, getTypeName().c_str()
, getString(rp).c_str() ) << 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 );
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)) and not (flags & NoProtect) ) {
map<Component*,AutoSegment*>::iterator irp = getRpLookup().find( rp );
if (irp == getRpLookup().end()) {
Box rpBb = rp->getBoundingBox();
if (rpDepth != 0) {
DbU::Unit hborder = 0;
DbU::Unit vborder = 0;
if (direction.contains(Flags::Horizontal)) {
vborder = Session::getWireWidth(rpDepth) / 2;
rpBb.inflate( hborder, vborder );
if (not rpBb.isEmpty()) {
DbU::Unit trackAxis = Session::getNearestTrackAxis( rp->getLayer()
, sourcePosition.getY()
, Constant::Nearest );
if (trackAxis != sourcePosition.getY()) {
cerr << Warning( "NetBuilderHV::doRp_AutoContacts(): Adjust Y position to nearest H track of %s\n"
" (%s -> %s)"
, getString(rp).c_str()
, DbU::getValueString(sourcePosition.getY()).c_str()
, DbU::getValueString(trackAxis).c_str()
) << endl;
sourcePosition.setY( trackAxis );
targetPosition.setY( trackAxis );
}
} else {
cdebug_log(145,0) << "rpBb is too narrow to adjust: " << rp->getBoundingBox() << endl;
}
} else {
hborder = Session::getWireWidth(rpDepth) / 2;
rpBb.inflate( hborder, vborder );
if (not rpBb.isEmpty()) {
DbU::Unit trackAxis = Session::getNearestTrackAxis( rp->getLayer()
, sourcePosition.getX()
, Constant::Nearest );
if (trackAxis != sourcePosition.getX()) {
cerr << Warning( "NetBuilderHV::doRp_AutoContacts(): Adjust X position to nearest V track of %s\n"
" (%s -> %s)"
, getString(rp).c_str()
, DbU::getValueString(sourcePosition.getX()).c_str()
, DbU::getValueString(trackAxis).c_str()
) << endl;
sourcePosition.setX( trackAxis );
targetPosition.setX( trackAxis );
}
} else {
cdebug_log(145,0) << "rpBb is too narrow to adjust: " << rp->getBoundingBox() << endl;
}
}
}
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 );
if (rpDepth == 0) rpDepth = 1;
AutoSegment* segment = AutoSegment::create( sourceProtect, targetProtect, direction, rpDepth );
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* NetBuilderHV::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access() - flags:" << flags << endl;
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
Flags useNonPref = Flags::NoFlags;
if (flags & UseNonPref) useNonPref |= Flags::UseNonPref;
flags |= checkRoutingPadSize( rp );
doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, flags );
cdebug_log(145,0) << "flags: " << flags << endl;
if ((rpDepth == 0) or (rpDepth == 2)) {
cdebug_log(145,0) << "case: METAL1 or METAL3 RoutingPad." << endl;
if (flags & HAccess) {
cdebug_log(145,0) << "case: HAccess" << endl;
if ( ((flags & VSmall) and not ((flags & UseNonPref))) or (flags & Punctual) ) {
cdebug_log(145,0) << "case: VSmall and *not* UseNonPref" << endl;
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, subContact1, Flags::Horizontal );
rpSourceContact = subContact1;
flags &= ~UseNonPref;
useNonPref.reset( Flags::UseNonPref );
}
if (flags & (VSmall|UseNonPref)) {
cdebug_log(145,0) << "case: UseNonPref" << endl;
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical|useNonPref );
rpSourceContact = subContact1;
}
} else {
if (flags & HSmall) {
cdebug_log(145,0) << "case: HSmall" << endl;
AutoContact* subContact1 = rpSourceContact;
AutoContact* subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( subContact1, subContact2, Flags::Horizontal );
rpSourceContact = subContact2;
if (flags & Punctual) {
cdebug_log(145,0) << "case: HSmall + Punctual" << endl;
subContact1 = subContact2;
subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( subContact1, subContact2, Flags::Vertical );
subContact1 = subContact2;
subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( subContact1, subContact2, Flags::Horizontal );
rpSourceContact = subContact2;
}
}
}
} else {
cdebug_log(145,0) << "case: METAL2." << endl;
AutoContact* subContact1 = NULL;
if (flags & HAccess) {
if (flags & HAccessEW)
subContact1 = AutoContactHTee::create( gcell, rp->getNet(), Session::getContactLayer(1) );
else
subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical );
} else {
#if OFFGRID_M2_DISABLED
Box cellAb = getAnabatic()->getCell()->getAbutmentBox();
RoutingLayerGauge* lgM2 = Session::getLayerGauge( 1 );
DbU::Unit trackAxis = lgM2->getTrackPosition( cellAb.getYMin()
, cellAb.getYMax()
, rp->getY()
, Constant::Nearest );
bool offGrid = (trackAxis != rp->getY());
if (offGrid) {
cdebug_log(145,0) << "Off grid, Misaligned M2 RoutingPad, add vertical strap" << endl;
subContact1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical );
rpSourceContact = subContact1;
}
#endif
subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, subContact1, Flags::Horizontal );
}
rpSourceContact = subContact1;
}
cdebug_tabw(145,-1);
return rpSourceContact;
}
AutoContact* NetBuilderHV::doRp_AccessNorthPin ( GCell* gcell, RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_AccessNorthPin() " << rp << endl;
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
AutoContact* turn = NULL;
doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, NoProtect );
Net* net = rp->getNet();
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
if (pinDir == Pin::AccessDirection::NORTH) {
turn = AutoContactTurn::create( gcell, net, Session::getRoutingLayer(1) );
AutoSegment* segment = AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
segment->setAxis( rp->getX(), Flags::Force );
segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
rpSourceContact = turn;
turn = AutoContactTurn::create( gcell, net, Session::getContactLayer(1) );
segment = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
rpSourceContact = turn;
DbU::Unit axis = gcell->getYMax() - Session::getDHorizontalPitch();
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
segment->setAxis( axis, Flags::Force );
//segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
cdebug_log(145,0) << segment << endl;
} else {
turn = rpSourceContact;
}
cdebug_tabw(145,-1);
return turn;
}
AutoContact* NetBuilderHV::doRp_AccessEastWestPin ( GCell* gcell, RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_AccessNorthPin() " << rp << endl;
Net* net = rp->getNet();
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
AutoContact* turn = NULL;
AutoSegment* segment = NULL;
doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, NoProtect );
turn = AutoContactTurn::create( gcell, net, Session::getContactLayer(1) );
segment = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
segment->setAxis( pin->getCenter().getY(), Flags::Force );
rpSourceContact = turn;
turn = AutoContactTurn::create( gcell, net, Session::getContactLayer(1) );
segment = AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
DbU::Unit axis = 0;
if (pinDir == Pin::AccessDirection::EAST)
axis = gcell->getXMax() - Session::getDVerticalPitch();
else
axis = gcell->getXMin() + Session::getDVerticalPitch();
segment->setAxis( axis );
cdebug_tabw(145,-1);
return turn;
}
bool NetBuilderHV::_do_1G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1() [Managed Configuration - Optimized] " << getTopology() << endl;
#if THIS_IS_DISABLED
uint64_t flags = NoFlags;
if (east() ) { flags |= HAccess; }
else if (west() ) { flags |= HAccess; }
else if (north()) { flags |= VSmall; }
else if (south()) { flags |= VSmall; }
setBothCornerContacts( doRp_Access(getGCell(),getRoutingPads()[0],flags) );
#endif
if (north() or south()) {
setBothCornerContacts( doRp_Access(getGCell(),getRoutingPads()[0],VSmall) );
} else {
setBothCornerContacts( doRp_Access( getGCell(), getRoutingPads()[0], UseNonPref|HAccess ) );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_1G_xM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_" << (int)getConnexity().fields.M1 << "M1() [Managed Configuration]" << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
for ( size_t i=1 ; i<getRoutingPads().size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess|UseNonPref );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess|UseNonPref );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
Component* globalRp = NULL;
if (east()) globalRp = getRoutingPads()[getRoutingPads().size()-1];
else if (west()) globalRp = getRoutingPads()[0];
else {
globalRp = getRoutingPads()[0];
cdebug_log(145,0) << "| Initial N/S Global RP: " << globalRp << endl;
for ( size_t i=1 ; i<getRoutingPads().size() ; ++i ) {
if (getRoutingPads()[i]->getBoundingBox().getHeight() > globalRp->getBoundingBox().getHeight()) {
cdebug_log(145,0) << "| Better RP: " << globalRp << endl;
globalRp = getRoutingPads()[i];
}
}
}
AutoContact* globalContact = doRp_Access( getGCell(), globalRp, HAccess );
if (north() or south()) {
AutoContact* turn = globalContact;
globalContact = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( globalContact, turn, Flags::Horizontal );
}
setBothCornerContacts( globalContact );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_xG ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl;
const Layer* viaLayer = Session::getDContactLayer();
if (getConnexity().fields.globals == 2) {
setBothCornerContacts( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
} else if (getConnexity().fields.globals == 3) {
if (east() and west()) {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer ) );
if (south()) swapCornerContacts();
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Vertical );
} else {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer ) );
if (west()) swapCornerContacts();
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Horizontal );
}
} else { // fields.globals == 4.
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
setSouthWestContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer ) );
AutoSegment::create( getSouthWestContact(), turn, Flags::Horizontal );
AutoSegment::create( turn, getNorthEastContact(), Flags::Vertical );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_2G ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G()" << endl;
const Layer* viaLayer = Session::getDContactLayer();
if (east() and west()) {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Vertical );
} else if (south() and north()) {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Horizontal );
} else {
setBothCornerContacts( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_xG_1Pad ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1Pad() [Managed Configuration - Optimized] " << getTopology() << endl;
cdebug_log(145,0) << "getConnexity().globals:" << (int)getConnexity().fields.globals << endl;
uint64_t flags = NoFlags;
bool eastPad = false;
bool westPad = false;
bool northPad = false;
bool southPad = false;
Instance* padInstance = getRoutingPads()[0]->getOccurrence().getPath().getHeadInstance();
switch ( padInstance->getTransformation().getOrientation() ) {
case Transformation::Orientation::ID: northPad = true; break;
case Transformation::Orientation::MY: southPad = true; break;
case Transformation::Orientation::YR:
case Transformation::Orientation::R3: eastPad = true; flags |= HAccess; break;
case Transformation::Orientation::R1: westPad = true; flags |= HAccess; break;
default:
cerr << Warning( "Unmanaged orientation %s for pad <%s>."
, getString(padInstance->getTransformation().getOrientation()).c_str()
, getString(padInstance).c_str() ) << endl;
break;
}
cdebug_log(145,0) << "eastPad:" << eastPad << ", "
<< "westPad:" << westPad << ", "
<< "northPad:" << northPad << ", "
<< "southPad:" << southPad
<< endl;
AutoContact* source = doRp_AccessPad( getRoutingPads()[0], flags );
// Point position = getRoutingPads()[0]->getCenter();
// AutoContact* source = NULL;
// GCell* gcell = Session::getAnabatic()->getGCellGrid()->getGCell(position);
// source = AutoContactTerminal::create ( gcell
// , getRoutingPads()[0]
// , Session::getContactLayer(3)
// , position
// , Session::getViaWidth(3), Session::getViaWidth(3)
// );
// source->setFlags( CntFixed );
// if (northPad or eastPad) {
// getSouthWestContact() = getNorthEastContact() = source;
// cdebug_tabw(145,-1);
// return;
// }
// Check for straight lines, which are not managed by _do_xG().
if (getConnexity().fields.globals == 1) {
if ( (westPad and (east() != NULL))
or (eastPad and (west() != NULL)) ) {
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
setBothCornerContacts( AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ) );
AutoSegment::create( source, turn, Flags::Horizontal );
AutoSegment::create( turn, getNorthEastContact(), Flags::Vertical );
cdebug_tabw(145,-1);
return true;
} else if ( (southPad and (north() != NULL))
or (northPad and (south() != NULL)) ) {
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
setBothCornerContacts( AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ) );
AutoSegment::create( source, turn, Flags::Vertical );
AutoSegment::create( turn, getNorthEastContact(), Flags::Horizontal );
cdebug_tabw(145,-1);
return true;
}
}
++getConnexity().fields.globals;
--getConnexity().fields.Pad;
if (westPad ) addToWests ( source->getBodyHook() );
if (eastPad ) addToEasts ( source->getBodyHook() );
if (southPad) addToSouths( source->getBodyHook() );
if (northPad) addToNorths( source->getBodyHook() );
_do_xG();
if (westPad) {
AutoSegment::create( source, getSouthWestContact(), Flags::Horizontal );
clearWests();
}
if (eastPad) {
AutoSegment::create( source, getNorthEastContact(), Flags::Horizontal );
clearEasts();
}
if (southPad) {
AutoSegment::create( source, getSouthWestContact(), Flags::Vertical );
clearSouths();
}
if (northPad) {
AutoSegment::create( source, getNorthEastContact(), Flags::Vertical );
clearNorths();
}
--(getConnexity().fields.globals);
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_1G_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoFlags );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Horizontal );
if (east() or west()) {
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( turn1, turn2, Flags::Vertical );
turn1 = turn2;
}
setBothCornerContacts( turn1 );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_1G_1PinM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
AutoContact* turn = NULL;
doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoProtect );
Pin* pin = dynamic_cast<Pin*>( getRoutingPads()[0]->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
if ( (pinDir == Pin::AccessDirection::NORTH)
or (pinDir == Pin::AccessDirection::SOUTH) ) {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getRoutingLayer(1) );
AutoSegment::create( rpSourceContact, turn, Flags::Vertical|Flags::UseNonPref );
rpSourceContact = turn;
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment* horizontal = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
rpSourceContact = turn;
DbU::Unit axis = getGCell()->getYMax() - Session::getDHorizontalPitch();
if (pinDir == Pin::AccessDirection::SOUTH)
axis = getGCell()->getYMin() + Session::getDHorizontalPitch();
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
horizontal->setAxis( axis, Flags::Force );
horizontal->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
cdebug_log(145,0) << horizontal << endl;
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getRoutingLayer(1) );
AutoSegment* vertical = AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
rpSourceContact = turn;
vertical->setAxis( pin->getX(), Flags::Force );
vertical->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
cdebug_log(145,0) << vertical << endl;
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
horizontal = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
horizontal->setAxis( axis, Flags::Force );
rpSourceContact = turn;
} else {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
rpSourceContact = turn;
}
if (east() or west()) {
rpSourceContact = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment* vertical = AutoSegment::create( turn, rpSourceContact, Flags::Vertical );
DbU::Unit axis = getGCell()->getXMax() - Session::getDVerticalPitch();
if (pinDir == Pin::AccessDirection::WEST)
axis = getGCell()->getXMin() + Session::getDVerticalPitch();
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
vertical->setAxis( axis, Flags::Force );
vertical->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
turn = rpSourceContact;
}
setBothCornerContacts( turn );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_2G_1PinM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
AutoContact* tee = NULL;
AutoContact* turn = NULL;
doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoProtect );
Pin* pin = dynamic_cast<Pin*>( getRoutingPads()[0]->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
if ( (pinDir == Pin::AccessDirection::NORTH)
or (pinDir == Pin::AccessDirection::SOUTH) ) {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getRoutingLayer(1) );
AutoSegment::create( rpSourceContact, turn, Flags::Vertical|Flags::UseNonPref );
rpSourceContact = turn;
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment* horizontal = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
rpSourceContact = turn;
DbU::Unit axis = getGCell()->getYMax() - Session::getDHorizontalPitch();
if (pinDir == Pin::AccessDirection::SOUTH)
axis = getGCell()->getYMin() + Session::getDHorizontalPitch();
horizontal->setAxis( axis, Flags::Force );
horizontal->setFlags( AutoSegment::SegFixed );
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getRoutingLayer(1) );
AutoSegment* vertical = AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
rpSourceContact = turn;
vertical->setFlags( AutoSegment::SegFixed );
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
horizontal = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
horizontal->setAxis( axis, Flags::Force );
rpSourceContact = turn;
turn = NULL;
}
if (east() and west()) {
// Pin must be North or South.
tee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, tee, Flags::Vertical );
} else if (north() and south()) {
// Pin must be East or West.
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, tee, Flags::Horizontal );
} else {
if ( (pinDir == Pin::AccessDirection::EAST)
or (pinDir == Pin::AccessDirection::WEST) ) {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
rpSourceContact = turn;
}
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment* vertical = AutoSegment::create( rpSourceContact, tee, Flags::Vertical );
if ( (pinDir == Pin::AccessDirection::EAST)
or (pinDir == Pin::AccessDirection::WEST) ) {
DbU::Unit axis = getGCell()->getXMax() - Session::getDVerticalPitch();
if (pinDir == Pin::AccessDirection::WEST)
axis = getGCell()->getXMin() + Session::getDVerticalPitch();
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
vertical->setAxis( axis, Flags::Force );
vertical->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
}
}
setBothCornerContacts( tee );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_xG_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
AutoContact* turn = NULL;
doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoFlags );
Pin* pin = dynamic_cast<Pin*>( getRoutingPads()[0]->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
if ( (pinDir == Pin::AccessDirection::EAST)
or (pinDir == Pin::AccessDirection::WEST) ) {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
rpSourceContact = turn;
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment* vertical = AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
rpSourceContact = turn;
Box cellAb = getAnabatic()->getCell()->getAbutmentBox();
RoutingLayerGauge* lgM3 = Session::getLayerGauge( 2 );
DbU::Unit axis = lgM3->getTrackPosition( cellAb.getXMin()
, cellAb.getXMax()
, getGCell()->getXMax() - Session::getDVerticalPitch()
, Constant::Superior );
if (pinDir == Pin::AccessDirection::WEST)
axis = lgM3->getTrackPosition( cellAb.getXMin()
, cellAb.getXMax()
, getGCell()->getXMin() + Session::getDVerticalPitch()
, Constant::Inferior );
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
vertical->setAxis( axis, Flags::Force );
vertical->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
}
if (getConnexity().fields.globals == 2) {
if (west() and south()) {
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Horizontal );
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( turn1, vtee1, Flags::Vertical );
setBothCornerContacts( vtee1 );
} else if (west() and north()) {
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, vtee1, Flags::Horizontal );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee1, turn1, Flags::Vertical );
setSouthWestContact( turn1 );
setNorthEastContact( vtee1 );
} else if (south() and north()) {
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, vtee1, Flags::Horizontal );
setBothCornerContacts( vtee1 );
} else if (east() and north()) {
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, htee1, Flags::Horizontal );
setBothCornerContacts( htee1 );
} else if (east() and south()) {
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, htee1, Flags::Horizontal );
setBothCornerContacts( htee1 );
} else if (east() and west()) {
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Horizontal );
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( turn1, htee1, Flags::Vertical );
setBothCornerContacts( htee1 );
}
} else {
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, htee1, Flags::Horizontal );
AutoContact* htee2 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( htee1, htee2, Flags::Horizontal );
if (pinDir == Pin::AccessDirection::EAST)
std::swap( htee1, htee2 );
setSouthWestContact( htee1 );
setNorthEastContact( htee2 );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_1G_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
rpSourceContact = doRp_AccessNorthPin( getGCell(), getRoutingPads()[0] );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
if (north() or south()) {
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( turn1, turn2, Flags::Horizontal );
turn1 = turn2;
}
setBothCornerContacts( turn1 );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_xG_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoFlags );
if (getConnexity().fields.globals == 2) {
if (west() and south()) {
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( turn1, htee1, Flags::Horizontal );
setBothCornerContacts( htee1 );
} else if (west() and north()) {
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, htee1, Flags::Vertical );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( turn1, htee1, Flags::Horizontal );
setSouthWestContact( htee1 );
setNorthEastContact( turn1 );
} else if (east() and north()) {
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, vtee1, Flags::Vertical );
setBothCornerContacts( vtee1 );
} else if (east() and south()) {
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, htee1, Flags::Vertical );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( htee1, turn1, Flags::Horizontal );
setSouthWestContact( turn1 );
setNorthEastContact( htee1 );
} else if (north() and south()) {
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( turn1, vtee1, Flags::Horizontal );
setBothCornerContacts( vtee1 );
} else { // Remaining case is East & West.
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, htee1, Flags::Vertical );
setBothCornerContacts( htee1 );
}
} else {
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
AutoSegment::create( turn1, turn2, Flags::Horizontal );
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( turn2, vtee1, Flags::Vertical );
AutoContact* vtee2 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee1, vtee2, Flags::Vertical );
setSouthWestContact( vtee1 );
setNorthEastContact( vtee2 );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_2G_xM1_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_xM1_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
RoutingPad* pinM3 = NULL;
AutoContact* pinContact = NULL;
AutoContact* dummy = NULL;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM3 = rp;
else rpsM1.push_back( rp );
}
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
doRp_AutoContacts( getGCell(), pinM3, pinContact, dummy, NoFlags );
AutoContact* m1contact = doRp_Access( getGCell(), rpsM1.back(), HAccess );
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( m1contact , vtee1, Flags::Horizontal );
AutoSegment::create( pinContact, vtee1, Flags::Vertical );
AutoContact* vtee2 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee1, vtee2, Flags::Vertical );
setBothCornerContacts( vtee2 );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_3G_xM1_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_3G_1M1_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
RoutingPad* pinM3 = NULL;
AutoContact* pinContact = NULL;
AutoContact* dummy = NULL;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM3 = rp;
else rpsM1.push_back( rp );
}
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
doRp_AutoContacts( getGCell(), pinM3, pinContact, dummy, NoFlags );
AutoContact* m1contact = doRp_Access( getGCell(), rpsM1.back(), HAccess );
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( m1contact , vtee1, Flags::Horizontal );
AutoContact* vtee2 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee1, vtee2, Flags::Vertical );
AutoContact* vtee3 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee2, vtee3, Flags::Vertical );
if (not south() or not north()) {
AutoSegment::create( pinContact, vtee1, Flags::Vertical );
}
if (not east() or not west()) {
AutoSegment::create( pinContact, vtee2, Flags::Horizontal );
}
if (not south()) {
setSouthWestContact( vtee2 );
setNorthEastContact( vtee3 );
} else if (not north()) {
setSouthWestContact( vtee3 );
setNorthEastContact( vtee2 );
} else if (not east()) {
setSouthWestContact( vtee3 );
setNorthEastContact( vtee1 );
} else if (not west()) {
setSouthWestContact( vtee1 );
setNorthEastContact( vtee3 );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_1G_xM1_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
RoutingPad* pinM2 = NULL;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM2 = rp;
else rpsM1.push_back( rp );
}
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
AutoContact* turn = NULL;
AutoContact* tee = NULL;
AutoContact* pinM2Contact = NULL;
AutoContact* rpM1Contact = NULL;
doRp_AutoContacts( getGCell(), pinM2, pinM2Contact, rpM1Contact, NoProtect );
rpM1Contact = doRp_Access( getGCell(), rpsM1[0], (north() or south()) ? HAccess : NoFlags );
if (north() or south()) {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpM1Contact , tee , Flags::Horizontal );
AutoSegment::create( pinM2Contact, turn, Flags::Horizontal );
AutoSegment::create( tee , turn, Flags::Vertical );
setBothCornerContacts( tee );
} else {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpM1Contact , tee , Flags::Vertical );
AutoSegment::create( pinM2Contact, tee , Flags::Horizontal );
AutoSegment::create( tee , turn, Flags::Vertical );
setBothCornerContacts( turn );
}
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_2G_xM1_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_xM1_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
RoutingPad* pinM2 = NULL;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM2 = rp;
else rpsM1.push_back( rp );
}
AutoContact* pinM2Contact = NULL;
AutoContact* rpM1Contact = NULL;
doRp_AutoContacts( getGCell(), pinM2, pinM2Contact, rpM1Contact, NoFlags );
rpM1Contact = doRp_Access( getGCell(), rpsM1[0], NoFlags );
if (north() and south()) {
cdebug_log(145,0) << "Case north & south." << endl;
AutoContact* htee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* vtee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinM2Contact, htee, Flags::Horizontal );
AutoSegment::create( rpM1Contact , htee, Flags::Vertical );
AutoSegment::create( htee , vtee, Flags::Horizontal );
setBothCornerContacts( vtee );
} else if (east() and west()) {
cdebug_log(145,0) << "Case east & west." << endl;
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* htee2 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinM2Contact, htee1, Flags::Horizontal );
AutoSegment::create( rpM1Contact , htee1, Flags::Vertical );
AutoSegment::create( htee1 , turn , Flags::Horizontal );
AutoSegment::create( htee2 , turn , Flags::Vertical );
setBothCornerContacts( htee2 );
} else {
cdebug_log(145,0) << "Case bend." << endl;
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* htee2 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinM2Contact, vtee1, Flags::Horizontal );
AutoSegment::create( rpM1Contact , vtee1, Flags::Vertical );
AutoSegment::create( vtee1 , turn1, Flags::Vertical );
AutoSegment::create( turn1 , htee2, Flags::Horizontal );
setBothCornerContacts( htee2 );
}
cdebug_log(145,0) << "Wiring all M1 together." << endl;
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_1G_1M1_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
RoutingPad* pinM3 = getRoutingPads()[0];
RoutingPad* rpM1 = getRoutingPads()[1];
if (dynamic_cast<Pin*>(rpM1->getOccurrence().getEntity())) std::swap( rpM1, pinM3 );
AutoContact* contact1 = doRp_Access( getGCell(), rpM1, HAccess );
AutoContact* htee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( contact1, htee, Flags::Horizontal );
rpSourceContact = doRp_AccessNorthPin( getGCell(), pinM3 );
if (north() or south()) {
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
AutoSegment::create( turn , htee, Flags::Horizontal );
} else {
AutoSegment::create( rpSourceContact, htee, Flags::Vertical );
}
setBothCornerContacts( htee );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_2G_1M1 ()
{
return _do_xG_1M1();
}
bool NetBuilderHV::_do_xG_1M1 ()
{
if ((int)getConnexity().fields.M1 != 1) return false;
cdebug_log(145,1) << getTypeName()
<< "::_do_xG_" << (int)getConnexity().fields.M1
<< "M1() [G:" << (int)getConnexity().fields.globals << " Managed Configuration]" << endl;
cdebug_log(145,0) << "getConnexity(): " << getConnexity().connexity << endl;
cdebug_log(145,0) << "north: " << north() << endl;
cdebug_log(145,0) << "south: " << south() << endl;
cdebug_log(145,0) << "east: " << east () << endl;
cdebug_log(145,0) << "west: " << west () << endl;
const Layer* viaLayer1 = Session::getContactLayer(1);
if (getConnexity().fields.globals == 2) {
if (north() and south()) {
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
AutoContact* contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Horizontal );
contact1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Horizontal );
setNorthEastContact( contact1 );
setSouthWestContact( contact2 );
} else if (east() and west()) {
// AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], NoFlags );
// AutoContact* contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
// AutoSegment::create( contact1, contact2, Flags::Vertical );
// setBothCornerContacts( contact2 );
AutoContact* contact1 = NULL;
AutoContact* contact2 = NULL;
uint64_t flags = checkRoutingPadSize( getRoutingPads()[0] );
if (flags & VSmall) {
doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags );
contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Vertical );
setBothCornerContacts( contact2 );
} else {
doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags );
setSouthWestContact( contact1 );
doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags );
setNorthEastContact( contact1 );
}
} else {
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
AutoContact* contact2 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Horizontal );
contact1 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Vertical );
setBothCornerContacts( contact1 );
}
} else if (getConnexity().fields.globals == 3) {
if (not west() or not east()) {
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
AutoContact* contact2 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Horizontal );
AutoContact* contact3 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact2, contact3, Flags::Vertical );
setSouthWestContact( (east()) ? contact2 : contact3 );
setNorthEastContact( (east()) ? contact3 : contact2 );
} else {
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], NoFlags );
AutoContact* contact2 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Vertical );
AutoContact* contact3 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact2, contact3, Flags::Vertical );
setSouthWestContact( (north()) ? contact2 : contact3 );
setNorthEastContact( (north()) ? contact3 : contact2 );
}
} else {
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
AutoContact* contact2 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Horizontal );
AutoContact* contact3 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact2, contact3, Flags::Vertical );
AutoContact* contact4 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact2, contact4, Flags::Vertical );
setSouthWestContact( contact3 );
setNorthEastContact( contact4 );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_xG_1M1_1M2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1M1_1M2() [Managed Configuration]" << endl;
Component* rpL1;
Component* rpL2;
if (getRoutingPads()[0]->getLayer() == Session::getRoutingLayer(0)) {
rpL1 = getRoutingPads()[0];
rpL2 = getRoutingPads()[1];
} else {
rpL1 = getRoutingPads()[1];
rpL2 = getRoutingPads()[0];
}
cdebug_log(145,0) << "rpL1 := " << rpL1 << endl;
cdebug_log(145,0) << "rpL2 := " << rpL2 << endl;
AutoContact* rpL1ContactSource = NULL;
AutoContact* rpL1ContactTarget = NULL;
AutoContact* rpL2ContactSource = NULL;
AutoContact* rpL2ContactTarget = NULL;
doRp_AutoContacts( getGCell(), rpL1, rpL1ContactSource, rpL1ContactTarget, NoFlags );
doRp_AutoContacts( getGCell(), rpL2, rpL2ContactSource, rpL2ContactTarget, NoFlags );
const Layer* viaLayer1 = Session::getContactLayer(1);
const Layer* viaLayer2 = Session::getContactLayer(2);
AutoContact* subContact = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( rpL1ContactSource, subContact, Flags::Horizontal );
AutoSegment::create( rpL2ContactSource, subContact, Flags::Vertical );
if (south() or west()) {
doRp_AutoContacts( getGCell(), rpL2, rpL2ContactSource, rpL2ContactTarget, DoSourceContact );
if (south() and west()) {
setSouthWestContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer2 ) );
AutoSegment::create( rpL2ContactSource, getSouthWestContact(), Flags::Horizontal );
} else {
if (south()) {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer2 ) );
AutoSegment::create( rpL2ContactSource, getSouthWestContact(), Flags::Horizontal );
} else {
setSouthWestContact( rpL2ContactSource );
}
}
}
if (north() or east()) {
doRp_AutoContacts( getGCell(), rpL2, rpL2ContactSource, rpL2ContactTarget, DoTargetContact );
if (north() and east()) {
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer2 ) );
AutoSegment::create( rpL2ContactTarget, getNorthEastContact(), Flags::Horizontal );
} else {
if (north()) {
setNorthEastContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer2 ) );
AutoSegment::create( rpL2ContactTarget, getNorthEastContact(), Flags::Horizontal );
} else {
setNorthEastContact( rpL2ContactTarget );
}
}
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_xG_xM1_xM3 ()
{
cdebug_log(145,1) << getTypeName()
<< "::_do_xG_" << (int)getConnexity().fields.M1
<< "M1_" << (int)getConnexity().fields.M3
<< "M3() [G:" << (int)getConnexity().fields.globals << " Managed Configuration]" << endl;
cdebug_log(145,0) << "getConnexity(): " << getConnexity().connexity << endl;
cdebug_log(145,0) << "north: " << north() << endl;
cdebug_log(145,0) << "south: " << south() << endl;
cdebug_log(145,0) << "east: " << east() << endl;
cdebug_log(145,0) << "west: " << west() << endl;
Component* rpM3 = NULL;
if (getRoutingPads()[0]->getLayer() == Session::getRoutingLayer(2))
rpM3 = getRoutingPads()[0];
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
for ( size_t i=1 ; i<getRoutingPads().size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
if (not rpM3 and (getRoutingPads()[i]->getLayer() == Session::getRoutingLayer(2)))
rpM3 = getRoutingPads()[i];
}
const Layer* viaLayer1 = Session::getContactLayer(1);
AutoContact* subContact1 = NULL;
if (rpM3) {
// At least one M3 RoutingPad is present: use it.
if (west() and not south()) {
setSouthWestContact( doRp_Access( getGCell(), getRoutingPads()[0], HAccess ) );
} else if (not west() and south()) {
doRp_AutoContacts( getGCell(), rpM3, getSouthWestContact(), subContact1, DoSourceContact );
} else if (west() and south()) {
AutoContact* rpContact = NULL;
doRp_AutoContacts( getGCell(), rpM3, rpContact, subContact1, DoSourceContact );
setSouthWestContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getSouthWestContact(), Flags::Vertical );
}
if (east() and not north()) {
setNorthEastContact( doRp_Access( getGCell(), getRoutingPads()[getRoutingPads().size()-1], HAccess ) );
} else if (not east() and north()) {
doRp_AutoContacts( getGCell(), rpM3, subContact1, getNorthEastContact(), DoTargetContact );
} else if (east() and north()) {
AutoContact* rpContact = NULL;
doRp_AutoContacts( getGCell(), rpM3, subContact1, rpContact, DoTargetContact );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getNorthEastContact(), Flags::Vertical );
}
} else {
cdebug_log(145,0) << "getRoutingPads().size():" << getRoutingPads().size()<< endl;
if (getRoutingPads().size() == 1) {
if ( ((east () != NULL) xor (west () != NULL))
and ((north() != NULL) xor (south() != NULL)) ) {
cdebug_log(145,0) << "case: One M1, with global turn." << endl;
AutoContact* rpContact = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
subContact1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( rpContact, subContact1, Flags::Horizontal );
rpContact = subContact1;
subContact1 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( rpContact, subContact1, Flags::Vertical );
setBothCornerContacts( subContact1 );
cdebug_tabw(145,-1);
return true;
}
}
// All RoutingPad are M1.
Component* southWestRp = getRoutingPads()[0];
cdebug_log(145,0) << "| Initial S-W Global RP: " << southWestRp << endl;
// for ( size_t i=1 ; i<getRoutingPads().size() ; ++i ) {
// if (southWestRp->getBoundingBox().getHeight() >= 4*Session::getPitch(1)) break;
// if (getRoutingPads()[i]->getBoundingBox().getHeight() > southWestRp->getBoundingBox().getHeight()) {
// southWestRp = getRoutingPads()[i];
// cdebug_log(145,0) << "| Better RP: " << southWestRp << endl;
// }
// }
if (west() and not south()) {
setSouthWestContact( doRp_Access( getGCell(), southWestRp, HAccess ) );
} else if (not west() and south()) {
AutoContact* rpContact = doRp_Access( getGCell(), southWestRp, HAccess );
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getSouthWestContact(), Flags::Horizontal );
} else if (west() and south()) {
AutoContact* rpContact = doRp_Access( getGCell(), southWestRp, HAccess );
setSouthWestContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getSouthWestContact(), Flags::Horizontal );
}
Component* northEastRp = getRoutingPads()[getRoutingPads().size()-1];
cdebug_log(145,0) << "| Initial N-E Global RP: " << northEastRp << endl;
if (getRoutingPads().size() > 1) {
for ( size_t i=getRoutingPads().size()-1; i != 0 ; ) {
i -= 1;
if (northEastRp->getBoundingBox().getHeight() >= 4*Session::getPitch(1)) break;
if (getRoutingPads()[i]->getBoundingBox().getHeight() > northEastRp->getBoundingBox().getHeight()) {
cdebug_log(145,0) << "| Better RP: " << northEastRp << endl;
northEastRp = getRoutingPads()[i];
}
}
}
if (east() and not north()) {
setNorthEastContact( doRp_Access( getGCell(), northEastRp, HAccess ) );
} else if (not east() and north()) {
AutoContact* rpContact = doRp_Access( getGCell(), northEastRp, HAccess );
setNorthEastContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getNorthEastContact(), Flags::Horizontal );
} else if (east() and north()) {
AutoContact* rpContact = doRp_Access( getGCell(), northEastRp, HAccess );
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getNorthEastContact(), Flags::Horizontal );
}
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_4G_1M2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_4G_1M2() [Managed Configuration]" << endl;
Component* rpL2 = getRoutingPads()[0];
cdebug_log(145,0) << "rpL2 := " << rpL2 << endl;
AutoContact* rpL2ContactSource = NULL;
AutoContact* rpL2ContactTarget = NULL;
doRp_AutoContacts( getGCell(), rpL2, rpL2ContactSource, rpL2ContactTarget, DoSourceContact|DoTargetContact );
const Layer* viaLayer2 = Session::getContactLayer(2);
setSouthWestContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer2 ) );
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer2 ) );
AutoSegment::create( getSouthWestContact(), rpL2ContactSource, Flags::Horizontal );
AutoSegment::create( rpL2ContactTarget, getNorthEastContact(), Flags::Horizontal );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_xG_xM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_"
<< (int)getConnexity().fields.globals << "G_"
<< (int)getConnexity().fields.M2 << "M2() [Managed Configuration - x]" << endl;
Component* biggestRp = getRoutingPads()[0];
for ( size_t i=1 ; i<getRoutingPads().size() ; ++i ) {
doRp_StairCaseH( getGCell(), getRoutingPads()[i-1], getRoutingPads()[i] );
if (getRoutingPads()[i]->getBoundingBox().getWidth() > biggestRp->getBoundingBox().getWidth())
biggestRp = getRoutingPads()[i];
}
const Layer* viaLayer1 = Session::getContactLayer(1);
if (east() and west() and not south() and not north()) {
AutoContact* rpContact = doRp_Access( getGCell(), biggestRp, HBothAccess );
setBothCornerContacts( rpContact );
cdebug_tabw(145,-1);
return true;
}
if (west() and not south()) {
setSouthWestContact( doRp_Access( getGCell(), getRoutingPads()[0], HAccess ) );
} else if (not west() and south()) {
setSouthWestContact( doRp_Access( getGCell(), biggestRp, NoFlags ) );
} else if (west() and south()) {
AutoContact* rpContact = doRp_Access( getGCell(), biggestRp, NoFlags );
setSouthWestContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getSouthWestContact(), Flags::Vertical );
}
if (east() and not north()) {
setNorthEastContact( doRp_Access( getGCell(), getRoutingPads()[getRoutingPads().size()-1], HAccess ) );
} else if (not east() and north()) {
setNorthEastContact( doRp_Access( getGCell(), biggestRp, NoFlags ) );
} else if (east() and north()) {
AutoContact* rpContact = doRp_Access( getGCell(), biggestRp, NoFlags );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getNorthEastContact(), Flags::Vertical );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_1G_1M3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M3() [Optimised Configuration]" << endl;
uint64_t flags = (east() or west()) ? HAccess : NoFlags;
flags |= (north()) ? DoTargetContact : NoFlags;
flags |= (south()) ? DoSourceContact : NoFlags;
doRp_AutoContacts( getGCell()
, getRoutingPads()[0]
, getSouthWestContact()
, getNorthEastContact()
, flags
);
if (not getSouthWestContact()) setSouthWestContact( getNorthEastContact() );
if (not getNorthEastContact()) setNorthEastContact( getSouthWestContact() );
cdebug_log(145,0) << "_southWest: " << getSouthWestContact() << endl;
cdebug_log(145,0) << "_northEast: " << getNorthEastContact() << endl;
const Layer* viaLayer1 = Session::getContactLayer(1);
Box cellAb = getAnabatic()->getCell()->getAbutmentBox();
RoutingLayerGauge* lgM3 = Session::getLayerGauge( 2 );
DbU::Unit trackAxis = lgM3->getTrackPosition( cellAb.getXMin()
, cellAb.getXMax()
, getRoutingPads()[0]->getX()
, Constant::Nearest );
bool offGrid = (trackAxis != getRoutingPads()[0]->getX());
if (offGrid) {
cdebug_log(145,0) << "Off grid, Misaligned M3, add horizontal strap" << endl;
AutoContactTurn* turn1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( getSouthWestContact(), turn1, Flags::Horizontal );
setBothCornerContacts( turn1 );
}
if (flags & HAccess) {
// HARDCODED VALUE.
if (getRoutingPads()[0]->getBoundingBox().getHeight() < 3*Session::getPitch(1)) {
AutoContact* subContact = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( getSouthWestContact(), subContact, Flags::Vertical );
setBothCornerContacts( subContact );
}
} else {
if (getSourceContact() and (getSourceContact()->getX() != getSouthWestContact()->getX())) {
cdebug_log(145,0) << "On grid, Misaligned M3, add dogleg" << endl;
AutoContactTurn* turn1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoContactTurn* turn2 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment* v1 = AutoSegment::create( getSouthWestContact(), turn1, Flags::Vertical );
AutoSegment::create( turn1, turn2, Flags::Horizontal );
v1->setAxis( getSouthWestContact()->getX(), Flags::Force );
v1->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
setBothCornerContacts( turn2 );
}
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_xG_xM3 ()
{
cdebug_log(145,1) << getTypeName()
<< "::_do_xG_" << (int)getConnexity().fields.M3
<< "M3() [Managed Configuration]" << endl;
cdebug_log(145,0) << "west:" << west() << endl;
cdebug_log(145,0) << "east:" << east() << endl;
cdebug_log(145,0) << "south:" << south() << endl;
cdebug_log(145,0) << "north:" << north() << endl;
sortRpByY( getRoutingPads(), NoFlags ); // increasing Y.
for ( size_t i=1 ; i<getRoutingPads().size() ; i++ ) {
doRp_StairCaseV( getGCell(), getRoutingPads()[i-1], getRoutingPads()[i] );
}
const Layer* viaLayer1 = Session::getContactLayer(1);
AutoContact* unusedContact = NULL;
Component* rp = getRoutingPads()[0];
if (west() and not south()) {
setSouthWestContact( doRp_Access( getGCell(), rp, HAccess ) );
} else if (not west() and south()) {
doRp_AutoContacts( getGCell(), rp, getSouthWestContact(), unusedContact, DoSourceContact );
if (getSourceContact()) {
if (getSourceContact()->getX() != getSouthWestContact()->getX()) {
cdebug_log(149,0) << "Misaligned South: _source:" << DbU::getValueString(getSourceContact()->getX())
<< "_southWest:" << DbU::getValueString(getSouthWestContact()->getX()) << endl;
AutoContactTurn* turn1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoContactTurn* turn2 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( getSouthWestContact(), turn1, Flags::Vertical );
AutoSegment::create( turn1 , turn2, Flags::Horizontal );
setSouthWestContact( turn2 );
}
}
} else if (west() and south()) {
AutoContact* rpContact = NULL;
doRp_AutoContacts( getGCell(), rp, rpContact, unusedContact, DoSourceContact );
setSouthWestContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getSouthWestContact(), Flags::Vertical );
}
rp = getRoutingPads()[getRoutingPads().size()-1];
if (east() and not north()) {
setNorthEastContact( doRp_Access( getGCell(), rp, HAccess ) );
} else if (not east() and north()) {
doRp_AutoContacts( getGCell(), rp, unusedContact, getNorthEastContact(), DoTargetContact );
if (getSourceContact()) {
if (getSourceContact()->getX() != getNorthEastContact()->getX()) {
cdebug_log(149,0) << "Misaligned North: _source:" << DbU::getValueString(getSourceContact()->getX())
<< "_southWest:" << DbU::getValueString(getNorthEastContact()->getX()) << endl;
AutoContactTurn* turn1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoContactTurn* turn2 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( getNorthEastContact(), turn1, Flags::Vertical );
AutoSegment::create( turn1 , turn2, Flags::Horizontal );
setNorthEastContact( turn2 );
}
}
} else if (east() and north()) {
AutoContact* rpContact = NULL;
doRp_AutoContacts( getGCell(), rp, unusedContact, rpContact, DoTargetContact );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getNorthEastContact(), Flags::Vertical );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_globalSegment ()
{
cdebug_log(145,1) << getTypeName() << "::_do_globalSegment()" << endl;
if (getSourceContact()) {
AutoContact* targetContact
= ( getSegmentHookType(getFromHook()) & (NorthBound|EastBound) )
? getNorthEastContact() : getSouthWestContact() ;
if (not getFromHook()) cerr << "getFromHook() is NULL !" << endl;
Segment* baseSegment = static_cast<Segment*>( getFromHook()->getComponent() );
AutoSegment* globalSegment = AutoSegment::create( getSourceContact()
, targetContact
, baseSegment
);
globalSegment->setFlags( (getDegree() == 2) ? AutoSegment::SegBipoint : 0 );
if (getNetData() and getNetData()->isNoMoveUp(baseSegment)) {
globalSegment->setFlags( AutoSegment::SegNoMoveUp );
}
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) {
cdebug_tabw(145,-1);
return false;
}
} else
setFromHook( NULL );
push( east (), getNorthEastContact() );
push( west (), getSouthWestContact() );
push( north(), getNorthEastContact() );
push( south(), getSouthWestContact() );
cdebug_tabw(145,-1);
return true;
}
void NetBuilderHV::singleGCell ( AnabaticEngine* anbt, Net* net )
{
cdebug_log(145,1) << "NetBuilderHV::singleGCell() " << net << endl;
vector<RoutingPad*> rpM1s;
Component* rpM2 = NULL;
RoutingPad* rpPin = NULL;
for ( RoutingPad* rp : net->getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) {
rpPin = rp;
continue;
}
if (Session::getRoutingGauge()->getLayerDepth(rp->getLayer()) == 1)
rpM2 = rp;
else
rpM1s.push_back( rp );
}
if ( (rpM1s.size() < 2) and not (rpM2 or rpPin) ) {
cerr << Error( "For %s, less than two Plugs/Pins (%d)."
, getString(net).c_str()
, rpM1s.size() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (rpM1s.empty()) {
cerr << Error( "No METAL1 in Single GCell for Net \"%s\".", getString(net->getName()).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
sortRpByX( rpM1s, NetBuilder::NoFlags ); // increasing X.
GCell* gcell1 = anbt->getGCellUnder( (*rpM1s.begin ())->getCenter() );
GCell* gcell2 = anbt->getGCellUnder( (*rpM1s.rbegin())->getCenter() );
if (not gcell1) {
cerr << Error( "No GCell under %s.", getString(*(rpM1s.begin())).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (gcell1 != gcell2) {
cerr << Error( "Not under a single GCell %s.", getString(*(rpM1s.rbegin())).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
cdebug_log(145,0) << "singleGCell " << gcell1 << endl;
AutoContact* turn1 = NULL;
AutoContact* turn2 = NULL;
AutoContact* source = NULL;
AutoContact* target = NULL;
for ( size_t irp=1 ; irp<rpM1s.size() ; ++irp ) {
doRp_AutoContacts( gcell1, rpM1s[irp-1], source, turn1, DoSourceContact );
doRp_AutoContacts( gcell1, rpM1s[irp ], target, turn1, DoSourceContact );
if (source->getUConstraints(Flags::Vertical).intersect(target->getUConstraints(Flags::Vertical))) {
uint64_t flags = checkRoutingPadSize( rpM1s[irp-1] );
if ((flags & VSmall) or Session::getConfiguration()->isVH()) {
if (Session::getConfiguration()->isHV()) {
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( source, turn1, Flags::Horizontal );
source = turn1;
}
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( source, turn1 , Flags::Vertical );
source = turn1;
}
flags = checkRoutingPadSize( rpM1s[irp] );
if ((flags & VSmall) or Session::getConfiguration()->isVH()) {
if (Session::getConfiguration()->isHV()) {
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( target, turn1, Flags::Horizontal );
target = turn1;
}
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( target, turn1 , Flags::Vertical );
target = turn1;
}
AutoSegment::create( source, target, Flags::Horizontal );
} else {
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
turn2 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( source, turn1 , Flags::Horizontal );
AutoSegment::create( turn1 , turn2 , Flags::Vertical );
AutoSegment::create( turn2 , target, Flags::Horizontal );
}
}
if (rpM2) {
doRp_AutoContacts( gcell1, rpM1s[0], source, turn1, DoSourceContact );
doRp_AutoContacts( gcell1, rpM2 , target, turn1, DoSourceContact );
turn1 = AutoContactTurn::create( gcell1, rpM2->getNet(), Session::getContactLayer(1) );
AutoSegment::create( source, turn1 , Flags::Horizontal );
AutoSegment::create( turn1 , target, Flags::Vertical );
}
if (rpPin) {
Pin* pin = dynamic_cast<Pin*>( rpPin->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
if ( (pinDir == Pin::AccessDirection::NORTH)
or (pinDir == Pin::AccessDirection::SOUTH) ) {
doRp_AutoContacts( gcell1, rpM1s[0], source, turn1, DoSourceContact );
target = doRp_AccessNorthPin( gcell1, rpPin );
turn1 = AutoContactTurn::create( gcell1, rpPin->getNet(), Session::getContactLayer(1) );
AutoSegment::create( source, turn1 , Flags::Horizontal );
AutoSegment::create( turn1 , target, Flags::Vertical );
} else {
RoutingPad* closest = NULL;
if (pinDir == Pin::AccessDirection::EAST) closest = rpM1s.back();
else closest = rpM1s.front();
doRp_AutoContacts( gcell1, closest, source, turn1, DoSourceContact );
target = doRp_AccessEastWestPin( gcell1, rpPin );
AutoSegment::create( source, target , Flags::Horizontal );
}
}
cdebug_tabw(145,-1);
}
string NetBuilderHV::getTypeName () const
{ return "NetBuilderHV"; }
} // Anabatic namespace.