coriolis/anabatic/src/NetBuilderM2.cpp

349 lines
13 KiB
C++
Raw Normal View History

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, 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 : "./NetBuilderM2.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DebugSession.h"
#include "hurricane/Layer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/NetRoutingProperty.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/RoutingPads.h"
#include "hurricane/Pad.h"
#include "hurricane/Plug.h"
#include "hurricane/Cell.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "crlcore/AllianceFramework.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/Measures.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/NetBuilderM2.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::swap;
NetBuilderM2::NetBuilderM2 ()
: NetBuilder()
{ }
NetBuilderM2::~NetBuilderM2 () { }
void NetBuilderM2::doRp_AutoContacts ( GCell* gcell
, Component* rp
, AutoContact*& source
, AutoContact*& target
, uint64_t flags
)
{
cdebug_log(145,1) << "NetBuilderM2::doRp_AutoContacts()" << endl;
cdebug_log(145,0) << rp << endl;
source = target = NULL;
Point sourcePosition;
Point targetPosition;
const Layer* rpLayer = rp->getLayer();
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
Flags direction = Session::getDirection ( rpDepth );
DbU::Unit viaSide = Session::getViaWidth ( rpDepth );
getPositions( rp, sourcePosition, targetPosition );
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
GCell* sourceGCell = Session::getAnabatic()->getGCellUnder( sourcePosition );
GCell* targetGCell = Session::getAnabatic()->getGCellUnder( targetPosition );
if (rpDepth == 0) {
rpLayer = Session::getContactLayer(0);
direction = Flags::Horizontal;
viaSide = Session::getViaWidth( rpDepth );
}
// Non-M1 terminal or punctual M1 protections.
if ((rpDepth != 0) or (sourcePosition == targetPosition)) {
map<Component*,AutoSegment*>::iterator irp = getRpLookup().find( rp );
if (irp == getRpLookup().end()) {
AutoContact* sourceProtect = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
, sourcePosition
, viaSide, viaSide
);
AutoContact* targetProtect = AutoContactTerminal::create( targetGCell
, rp
, rpLayer
, targetPosition
, viaSide, viaSide
);
sourceProtect->setFlags( CntFixed );
targetProtect->setFlags( CntFixed );
AutoSegment* segment = AutoSegment::create( sourceProtect, targetProtect, direction );
segment->setFlags( AutoSegment::SegFixed );
getRpLookup().insert( make_pair(rp,segment) );
}
}
if (sourcePosition != targetPosition) {
if (flags & DoSourceContact)
source = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
, sourcePosition
, viaSide, viaSide
);
if (flags & DoTargetContact)
target = AutoContactTerminal::create( targetGCell
, rp
, rpLayer
, targetPosition
, viaSide, viaSide
);
}
if (not source and not target) {
source = target = AutoContactTerminal::create( gcell
, rp
, rpLayer
, rp->getCenter()
, viaSide, viaSide
);
}
cdebug_tabw(145,-1);
return;
}
AutoContact* NetBuilderM2::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access()" << endl;
cdebug_log(145,0) << rp << endl;
Point sourcePosition;
Point targetPosition;
const Layer* rpLayer = rp->getLayer();
const Layer* viaLayer = Session::getDContactLayer();
DbU::Unit viaSide = Session::getDContactWidth();
DbU::Unit ypitch = Session::getDVerticalPitch();
getPositions( rp, sourcePosition, targetPosition );
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
Point position = rp->getCenter();
if (not (flags & Middle)) {
if (flags & NorthBound) position = targetPosition;
if (flags & SouthBound) position = sourcePosition;
}
DbU::Unit ycontact = (flags & SouthBound) ? gcell->getYMin() : gcell->getYMax()-ypitch;
AutoContact* rpContact = AutoContactTerminal::create( gcell, rp, rpLayer, position, viaSide, viaSide );
AutoContact* contact1 = AutoContactTurn::create( gcell, getNet(), viaLayer );
AutoContact* contact2 = AutoContactTurn::create( gcell, getNet(), viaLayer );
contact1->setPosition( position.getX(), ycontact );
contact2->setPosition( position.getX(), ycontact );
rpContact->setFlags( CntFixed );
contact1 ->setFlags( CntFixed );
contact2 ->setFlags( CntFixed );
AutoSegment* fixed = AutoSegment::create( rpContact, contact1, Flags::Vertical );
AutoSegment* dogleg = AutoSegment::create( contact1 , contact2, Flags::Horizontal );
fixed ->setFlags( AutoSegment::SegFixed );
dogleg->setFlags( AutoSegment::SegFixed );
cdebug_tabw(145,-1);
return contact2;
}
bool NetBuilderM2::_do_1G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1()" << endl;
uint64_t flags = NoFlags;
if (north()) flags |= NorthBound;
else if (south()) flags |= SouthBound;
AutoContact* contact = NULL;
contact = doRp_Access( getGCell(), getRoutingPads()[0], flags );
setNorthEastContact( contact );
push( north(), contact, SouthWest );
push( south(), contact, SouthWest );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_2G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_1M1()" << endl;
AutoContact* contact = NULL;
contact = doRp_Access( getGCell(), getRoutingPads()[0], SouthBound|NorthBound );
push( north(), contact, SouthWest|Middle );
contact = doRp_Access( getGCell(), getRoutingPads()[0], SouthBound|NorthBound );
push( south(), contact, SouthWest|Middle );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_xG ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl;
vector<Hook*> hooksNS = getNorths();
hooksNS.insert( hooksNS.end(), getSouths().begin(), getSouths().end() );
sort( hooksNS.begin(), hooksNS.end(), SortHookByX(NoFlags) );
const Layer* viaLayer = Session::getDContactLayer();
AutoContact* contactW = NULL;
AutoContact* contactE = NULL;
// Simple turn.
if ( (west() and not east() and (hooksNS.size() == 1))
or (east() and not west() and (hooksNS.size() == 1)) ) {
contactW = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
push( west() , contactW, SouthWest );
push( east() , contactW, SouthWest );
push( hooksNS[0], contactW, SouthWest );
cdebug_tabw(145,-1);
return true;
}
// Simple HTee.
if (west() and east() and (hooksNS.size() == 1)) {
contactW = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
push( west() , contactW, SouthWest );
push( east() , contactW, SouthWest );
push( hooksNS[0], contactW, SouthWest );
cdebug_tabw(145,-1);
return true;
}
cdebug_log(145,0) << "West side processing." << endl;
// West side processing.
if (west()) {
contactW = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
push( west() , contactW, SouthWest );
push( hooksNS[0], contactW, SouthWest );
} else {
contactW = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
push( hooksNS[0], contactW, SouthWest );
}
cdebug_log(145,0) << "Middle processing." << endl;
// Middle (North & South) processing.
if (hooksNS.size() > 2) {
for ( size_t i=1 ; i<hooksNS.size()-1 ; ++i ) {
AutoContact* current = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
AutoSegment::create( contactW, current, Flags::Horizontal );
push( hooksNS[i], current, SouthWest );
contactW = current;
}
}
cdebug_log(145,0) << "East side processing." << endl;
// East side processing.
if (east()) {
contactE = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
push( east(), contactE, SouthWest );
if (hooksNS.size() > 1)
push( hooksNS[hooksNS.size()-1], contactE, SouthWest );
} else {
contactE = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
push( hooksNS[hooksNS.size()-1], contactE, SouthWest );
}
AutoSegment::create( contactW, contactE, Flags::Horizontal );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_globalSegment ()
{
cdebug_log(145,1) << getTypeName() << "::_do_globalSegment()" << endl;
if (getSourceContact()) {
Segment* segment = static_cast <Segment*> ( getFromHook()->getComponent() );
AutoSegment* globalSegment = AutoSegment::create( getSourceContact(), getSouthWestContact(), segment );
globalSegment->setFlags( (getDegree() == 2) ? AutoSegment::SegBipoint : 0 );
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) return false;
} else
setFromHook( NULL );
return true;
}
bool NetBuilderM2::_do_1G_xM1 () { return false; }
bool NetBuilderM2::_do_xG_1Pad () { return false; }
bool NetBuilderM2::_do_1G_1PinM2 () { return false; }
bool NetBuilderM2::_do_xG_xM2 () { return false; }
bool NetBuilderM2::_do_1G_1M3 () { return false; }
bool NetBuilderM2::_do_xG_xM3 () { return false; }
bool NetBuilderM2::_do_xG_1M1_1M2 () { return false; }
bool NetBuilderM2::_do_xG_xM1_xM3 () { return false; }
bool NetBuilderM2::_do_4G_1M2 () { return false; }
bool NetBuilderM2::_do_2G () { return false; }
string NetBuilderM2::getTypeName () const
{ return "NetBuilderM2"; }
} // Anabatic namespace.