coriolis/anabatic/src/NetBuilderHV.cpp

910 lines
38 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/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;
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 );
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* NetBuilderHV::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access() - flags:" << flags << endl;
AutoContact* rpContactSource;
AutoContact* rpContactTarget;
flags |= checkRoutingPadSize( rp );
doRp_AutoContacts( gcell, rp, rpContactSource, rpContactTarget, flags );
if (flags & HAccess) {
if (flags & VSmall) {
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoContact* subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpContactSource, subContact1, Flags::Horizontal );
AutoSegment::create( subContact1, subContact2, Flags::Vertical );
rpContactSource = subContact2;
}
} else {
if (flags & HSmall) {
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpContactSource, subContact1, Flags::Horizontal );
rpContactSource = subContact1;
}
}
cdebug_tabw(145,-1);
return rpContactSource;
}
bool NetBuilderHV::_do_1G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1() [Managed Configuration - Optimized] " << getTopology() << endl;
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) );
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 );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
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* rpContact = doRp_Access( getGCell(), getRoutingPads()[0], NoFlags );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpContact, 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_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_" << (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;
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 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Horizontal );
setBothCornerContacts( 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 );
} else {
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
AutoContact* contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Horizontal );
setBothCornerContacts( contact2 );
}
} else if (getConnexity().fields.globals == 3) {
if (not west() or not east()) {
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
AutoContact* contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Horizontal );
AutoContact* contact3 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact2, contact3, Flags::Horizontal );
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* unusedContact = 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(), unusedContact, DoSourceContact );
} else if (west() and south()) {
AutoContact* rpContact = NULL;
doRp_AutoContacts( getGCell(), rpM3, rpContact, unusedContact, 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, unusedContact, getNorthEastContact(), DoTargetContact );
} else if (east() and north()) {
AutoContact* rpContact = NULL;
doRp_AutoContacts( getGCell(), rpM3, unusedContact, rpContact, DoTargetContact );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ) );
AutoSegment::create( rpContact, getNorthEastContact(), Flags::Vertical );
}
} else {
// 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()) {
cdebug_log(145,0) << "| Better RP: " << southWestRp << endl;
southWestRp = getRoutingPads()[i];
}
}
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);
AutoContact* unusedContact = NULL;
if (west() and not south()) {
doRp_AutoContacts( getGCell(), getRoutingPads()[0], getSouthWestContact(), unusedContact, DoSourceContact );
} 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()) {
doRp_AutoContacts( getGCell(), getRoutingPads()[getRoutingPads().size()-1], getNorthEastContact(), unusedContact, DoSourceContact );
} 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);
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()) {
if (getSourceContact()->getX() != getSouthWestContact()->getX()) {
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 );
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() ;
AutoSegment* globalSegment = AutoSegment::create( getSourceContact()
, targetContact
, static_cast<Segment*>( getFromHook()->getComponent() )
);
globalSegment->setFlags( (getDegree() == 2) ? AutoSegment::SegBipoint : 0 );
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getLength() < 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;
}
string NetBuilderHV::getTypeName () const
{ return "NetBuilderHV"; }
} // Anabatic namespace.