// -*- 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 #include #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( 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::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 ; igetBoundingBox().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 ; igetLayer() == 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 ; igetBoundingBox().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 ; igetBoundingBox().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 ; igetX() != 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( 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.