349 lines
13 KiB
C++
349 lines
13 KiB
C++
|
// -*- 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.
|