diff --git a/anabatic/doc/NetBuilder.dox b/anabatic/doc/NetBuilder.dox
new file mode 100644
index 00000000..1308cf6f
--- /dev/null
+++ b/anabatic/doc/NetBuilder.dox
@@ -0,0 +1,346 @@
+
+// -*- C++ -*-
+
+namespace Anabatic {
+
+/*! \defgroup LoadGlobalRouting Global Routing Loading
+ * \brief Translation rules to build detailed routing from global
+ *
+ * This module documents how the global routing built by \c Knik is
+ * loaded into the \c Anabatic data-base. It is intented for developpers
+ * only.
+ */
+
+//! \addtogroup LoadGlobalRouting
+//! \{
+
+//! \enum LocalFunctionFlag
+//! A set of flags for all functions of the LoadGlobalRouting module.
+//! They can be combined to form the \e flags argument of functions.
+//! the functions will ignore flags that are not intended to them.
+//!
+//! For \c HSmall, \c VSmall & \c Punctual see checkRoutingPadSize().
+
+//! \var LocalFunctionFlag::NoFlags
+//! A simple alias over zero to explicitly tell that no flag at all is
+//! passed to the function.
+
+//! \var LocalFunctionFlag::HAccess
+//! The constructed topology will be accessed through an horizontal
+//! segment. The absence of this flag tell that the access will be done
+//! trough a vertical.
+
+//! \var LocalFunctionFlag::VSmall
+//! The RoutingPad vertically covers a very small number of access points,
+//! so it is likely overconstrained for direct horizontal connexion.
+
+//! \var LocalFunctionFlag::HSmall
+//! The RoutingPad horizontally covers a very small number of access points,
+//! so it is likely overconstrained for direct vertical connexion.
+
+//! \var LocalFunctionFlag::Punctual
+//! The RoutingPad covers only an access point in either direction.
+
+//! \var LocalFunctionFlag::DoSourceContact
+//! When creating Anabatic::AutoContactTerminal on non-punctual RoutingPad, this flag
+//! request the creation of a contact on the source point.
+
+//! \var LocalFunctionFlag::DoTargetContact
+//! When creating Anabatic::AutoContactTerminal on non-punctual RoutingPad, this flag
+//! request the creation of a contact on the target point.
+
+
+//! \function uint64_t checkRoutingPadSize ( Component* rp );
+//!
+//! Look at the geometrical size of the Component and assess if
+//! it's span is too narrow either horizontally or vertically.
+//! Return a combination of flags indicating it's state:
+//! - HSmall : less than 3 pitches in horizontal direction.
+//! - VSmall : less than 3 pitches in vertical direction.
+//! - Punctual : one pitch in either directions.
+//!
+//! The component can be a RoutingPad, a Vertical or an Horizontal.
+//!
+//! \image html checkRoutingPadSize.png "checkRoutingPadSize()"
+
+/*! \class NetBuilder
+ *
+ * \brief Build the wiring for a Net inside a GCell (\b internal).
+ *
+ * As this class is called to initially construct the Anabatic wiring,
+ * it must build a \b connex wiring. That is without gaps in layer depth,
+ * because the topology restauration mechanism (AutoContact::updateTopology())
+ * of the AutoContact cannot work until all AutoSegments are revalidated at
+ * least once. The topology restauration work by creating doglegs which in turn,
+ * call the canonization, which needs all the caches to be up to date.
+ */
+
+//! \function void NetBuilder::doRp_AutoContacts ( GCell* gcell, Component* rp, AutoContact*& source, AutoContact*& target, uint64_t flags );
+//! \param gcell The GCell into which create the AutoContact.
+//! \param rp The Component we want to access.
+//! \param source The AutoContact created on the \c source (\e returned).
+//! \param target The AutoContact created on the \c target (\e returned).
+//! \param flags Managed by this function:
+//! - LocalFunctionFlag::DoSourceContact
+//! - LocalFunctionFlag::DoTargetContact
+//!
+//! Create the AutoContact directly anchored on the Component (terminal).
+//! Three cases are manageds:
+//! -# Ordinary (non-punctual) \c METAL1 terminal: an AutoContactTerminal
+//! is anchored on the RoutingPad.
+//! -# Punctual \c METAL1 terminal, the access must never be blocked
+//! by other routing. To ensure it, we create a fixed AutoSegment (anchored
+//! on two AutoContactTerminal) to cover it. The \e normal AutoContactTerminal
+//! is also created.
+//! -# non \c METAL1 terminal, as for the punctual \c METAL1, a
+//! fixed protection is added over the RoutingPad. If we access
+//! horizontally a vertical RoutingPad or vertically an horizontal
+//! one, an extra AutoContactTerminal is added (to allow is displacement
+//! along the RoutingPad).
+//!
+//! To avoid creating a fixed protection over a RoutingPad multiple times,
+//! the RoutingPad and it's associated protection is stored in a static
+//! \c map : \c __routingPadAutoSegments.
+//!
+//! Conversely, because an AutoContactTerminal can only be connected to one
+//! segment, each time this function is called a new terminal will be created
+//! (or maybe two in case of non-punctual terminals). If only one AutoContact
+//! is requested, it is created centered on the RoutingPad. The initial
+//! position of AutoContact do not prevent them to move afterwards,
+//! even those created on source/target on a non-punctual RoutingPad.
+//!
+//! \remark For clarity we describe the layer management of this function in term
+//! of \c METAL, but it is the RoutingGauge depth which is actually used.
+//!
+//! \image html doRp_AutoContacts.png "doRp_AutoContacts()"
+
+//! \function AutoContact* NetBuilder::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags );
+//! \param gcell The GCell into which create the AutoContact.
+//! \param rp The Component onto which anchor the access contact.
+//! \param flags Relevant flags are:
+//! - HAccess, the terminal is to be accessed through an horizontal
+//! segment.
+//! - VSmall, force the terminal to be considered as small in the
+//! vertical direction.
+//!
+//! If \c HAccess is set, the Component is to be accessed trough an horizontal
+//! segment. If unset, the access is done vertically.
+//!
+//! Create an AutoContact to access a Component (terminal). If the Component
+//! is not to be accessed through an horizontal segment, and do not cover a
+//! large span in the horizontal direction (flag \c VSmall), a local horizontal
+//! AutoSegment is added to slacken the vertical constraints.
+//!
+//! \image html doRp_Access.png "doRp_Access()"
+
+//! \function AutoContact* NetBuilder::doRp_AccessPad ( RoutingPad* rp, uint64_t flags );
+//! \param rp The Component onto which anchor the access contact.
+//! \param flags Relevant flags are:
+//! - HAccess, the terminal is to be accessed through an horizontal
+//! segment.
+//! - VSmall, force the terminal to be considered as small in the
+//! vertical direction.
+//! \return A Anabatic::AutoContactTerminal .
+//!
+//! The Component \c rp is a RoutingPad which belongs to a pad cell. This case
+//! occurs when we are routing a complete chip. This method build, from the
+//! \c rp a stack of articulated punctual segments and contacts to reach the
+//! default H/V routing layers (usually \c METAL2 & \c METAL3). This may be
+//! needed when the pad terminal is in \c METAL5, for instance.
+//!
+//! The returned AutoContactTerminal is anchored on the last punctual segment
+//! build.
+//!
+//! The GCell into which the AutoContactTerminal is created may be under the
+//! pads area. However, it will be right on the border of the GCell.
+//! The global router vertexes of GCell under the pad area are marked as
+//! blocked so will never be used for routing.
+//!
+//! \remark The segments and contacts added to ensure the layer connexity are not
+//! put into the Anabatic database. They are plain Hurricane objects, invisibles
+//! from it.
+
+//! \function void NetBuilder::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 );
+//!
+//! Build the wiring to connect to horizontal Component. Two cases:
+//! - The Component are aligneds, then only a straight wire is created.
+//! - They are \e not aligned, then a complete dogleg is created.
+//!
+//! \image html doRp_StairCaseH.png "doRp_StairCaseH()"
+
+//! \function void NetBuilder::doRp_StairCaseV ( GCell* gcell, Component* rp1, Component* rp2 );
+//!
+//! Build the wiring to connect to vertical Components. Two cases:
+//! - The Components are aligneds, then only a straight wire is created.
+//! - They are \e not aligned, then a complete dogleg is created.
+//!
+//! \image html doRp_StairCaseV.png "doRp_StairCaseV()"
+
+//! \function void NetBuilder::_do_xG_1Pad ();
+//!
+//! Construct the topology, when there is only global wires and one local
+//! terminal, but coming from a Pad. As thoses connectors will always be
+//! on one border of the GCell they can be considered as a kind of global.
+//!
+//! So this method mostly calls NetBuilder::doRp_AccessPad() to create
+//! the AutoContactTerminal, then calls NetBuilder::_do_xG(), except
+//! for straight lines which are managed directly.
+
+//! \function void NetBuilder::_do_xG ();
+//!
+//! Construct the topology, when there is only global wires (no local terminals).
+//!
+//! Some topology are not handled because they must not be managed by this
+//! function:
+//!
+//! - One global: nonsensical because there also must be a terminal.
+//!
- Two aligned globals: in that case we do a straight wire whithout
+//! any AutoContact (handled by the source/target of the wire).
+//!
+//!
+//! \image html _do_xG.png "_do_xG()"
+
+//! \function void NetBuilder::_do_1G_1M1 ();
+//!
+//! Construct a topology where there is \e one global and one RoutingPad
+//! in \c METAL1. The \c METAL1 is assumed to be vertical.
+//!
+//! \remark When accessing the RoutingPad through an horizontal global segment
+//! and the vertical extension of the segment is small, the global is
+//! still directly attached to the terminal, inducing a high constraint
+//! on it. We left to job of slackening it to the router.
+//!
+//! \image html _do_1G_1M1.png "_do_1G_1M1()"
+
+//! \function void NetBuilder::_do_1G_xM1 ();
+//!
+//! Construct a topology where there is \e one global and any number of
+//! RoutingPad in \c METAL1. The \c METAL1 is assumed to be vertical.
+//!
+//! The RoutingPads are linked together two by two. If the horizontal
+//! segments are not aligned by the router, part of the routage will be
+//! done through the RoutingPad itself. The global incoming segment will
+//! connected to the leftmost, rightmost or centermost RoutingPad according
+//! from wich side it comes from.
+//!
+//! \image html _do_1G_xM1.png "_do_1G_xM1()"
+
+//! \function void NetBuilder::_do_xG_1M1_1M2 ();
+//!
+//! Construct a topology where there is at least one global (and up to 4),
+//! one \c METAL1 RoutingPad (assumed V) and one \c METAL2 RoutingPad (assumed H).
+//!
+//! In this topology, we want to try to reuse the \c METAL2 RoutingPad as a
+//! feedtrough in the horizontal routage. Thus:
+//! - The \c METAL1 and \c METAL2 RoutingPad are connected through a separate wiring.
+//! - The south & west global wiring is attached to the leftmost contact of
+//! the \c METAL2.
+//! - The north & east global wiring is attached to the rightmost contact of
+//! the \c METAL2.
+//!
+//! South/west and north/south can be build independantly. Depending on the number
+//! of globals, they can consist of:
+//! - Nothing (no south nor west).
+//! - An AutoContact (west present).
+//! - An horizontal plus a turn (south present).
+//! - An horizontal plus a HTee (south & west present).
+//!
+//! \remark Not all configurations are represented below.
+//!
+//! \image html _do_xG_1M1_1M2.png "_do_xG_1M1_1M2()"
+
+//! \function void NetBuilder::_do_xG_xM1_xM3 ();
+//!
+//! Construct a topology where there is at least one global (and up to 4),
+//! at least one \c METAL1 RoutingPad (assumed V) and at least one \c METAL3
+//! RoutingPad (assumed V).
+//!
+//! In this topology, we want to try to reuse the \c METAL3 RoutingPad as a
+//! feedtrough in the vertical routage. Thus:
+//! - The \c METAL1 and \c METAL3 RoutingPad are connected through a separate
+//! wiring made of separate horizontals.
+//! - The south-west global wiring is attached to the leftmost RoutingPad
+//! if there isn't south or to the first \c METAL3 otherwise.
+//! - The north-east global wiring is attached to the rightmost RoutingPad
+//! if there isn't north or to the first \c METAL3 otherwise.
+//!
+//! South/west and north/south can be build independantly. Depending on the number
+//! of globals, they can consist of:
+//! - Nothing (no south nor west).
+//! - An AutoContact on the leftmost RoutingPad (west present).
+//! - An AutoContact on the first \c METAL3 (only south present).
+//! - An AutoContact plus a vertical plus a VTee (south & west present).
+//!
+//! \image html _do_xG_xM1_xM3.png "_do_xG_xM1_xM3()"
+
+//! \function void NetBuilder::_do_xG_xM2 ();
+//!
+//! Construct a topology where there is at least one global (and up to 4),
+//! and any number of \c METAL2 RoutingPads (assumeds H).
+//!
+//! In this topology, we want to try to reuse the \c METAL2 RoutingPad as a
+//! feedtrough in the horizontal routage. Thus:
+//! - The RoutingPad are connecteds trough a separate staircase (or
+//! straight wire if aligneds).
+//! - The south-west global wiring is attached to the leftmost RoutingPad
+//! if there isn't south or to the biggest horizontal RoutingPad otherwise.
+//! - The north-east global wiring is attached to the rightmost RoutingPad
+//! if there isn't south or to the biggest horizontal RoutingPad otherwise.
+//!
+//! \image html _do_xG_xM2.png "_do_xG_xM2()"
+
+//! \function void NetBuilder::_do_1G_1M3 ();
+//!
+//! Construct a topology where there is one global and one \c METAL3 RoutingPad
+//! (assumeds V).
+//!
+//! In this topology, we reuse the \c METAL3 RoutingPad as a feedtrough in the
+//! vertical routage. Thus:
+//! - If the global is either north or south, we directly connect to the
+//! north end or south end of the RoutingPad. \red{The vertical global will}
+//! \red{have no slack at all we assume that METAL3 terminals are only from}
+//! \red{blocks and are aligneds vertically.}
+//! - If the global is east or west \e and the RoutingPad is sufficiently
+//! extended in the vertical direction, we connect an horizontal in the
+//! normal way.
+//! - If the global is not sufficiently extended, we add a turn to give some
+//! slack to the global.
+//!
+//!
+//! \image html _do_1G_1M3.png "_do_1G_1M3()"
+
+//! \function void NetBuilder::_do_xG_xM3 ();
+//!
+//! Construct a topology where there at least one global and two \c METAL3 RoutingPad
+//! (assumed V).
+//!
+//! In this topology, we reuse the \c METAL3 RoutingPad as a feedtrough in the
+//! vertical routage. \red{We assume that the most likely relative position}
+//! \red{of the RoutingPads is to be aligned vertically}.
+//! Thus:
+//! - All RoutingPads are linked two by two trough vertical staircases.
+//! - The south-west global wiring is attached to the bottommost RoutingPad
+//! (without vertical slack). If a misalignment is detected, then a
+//! dogleg is added.
+//! - The north-east global wiring is attached to the topmost RoutingPad
+//! (without vertical slack).
+//!
+//! South/west and north/south can be build independantly. Depending on the number
+//! of globals, they can consist of:
+//! - Nothing (no south nor west).
+//! - An sliding AutoContact on the bottommost RoutingPad (west present).
+//! - An fixed AutoContact on the bottommost RoutingPad (only south present).
+//! - An fixed AutoContact plus a vertical plus a VTee (south & west present).
+//!
+//! \image html _do_xG_xM3.png "_do_xG_xM3()"
+
+//! \function void singleGCell ( AnabaticEngine* anbt, Net* net );
+//!
+//! All the RoutingPads of the net are concentrated under a single
+//! GCell. This function assumes that all the terminals are in
+//! \c METAL1 (vertical), and link them two by two by horizontal
+//! wires.
+
+//! \}
+
+}
diff --git a/anabatic/src/AnabaticEngine.cpp b/anabatic/src/AnabaticEngine.cpp
index b0fcfb20..d98a94e2 100644
--- a/anabatic/src/AnabaticEngine.cpp
+++ b/anabatic/src/AnabaticEngine.cpp
@@ -27,7 +27,9 @@
#include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h"
#include "crlcore/RoutingGauge.h"
+#include "crlcore/Measures.h"
#include "anabatic/GCell.h"
+#include "anabatic/NetBuilderHV.h"
#include "anabatic/AnabaticEngine.h"
@@ -50,6 +52,8 @@ namespace Anabatic {
using Hurricane::UpdateSession;
using CRL::RoutingGauge;
using CRL::RoutingLayerGauge;
+ using CRL::addMeasure;
+ using CRL::getMeasure;
// -------------------------------------------------------------------
@@ -718,6 +722,38 @@ namespace Anabatic {
}
+ void AnabaticEngine::_loadGrByNet ()
+ {
+ cmess1 << " o Building detailed routing from global." << endl;
+
+ startMeasures();
+ openSession();
+
+ for ( Net* net : getCell()->getNets() ) {
+ if (NetRoutingExtension::isAutomaticGlobalRoute(net)) {
+ DebugSession::open( net, 144, 160 );
+ AutoSegment::setAnalogMode( NetRoutingExtension::isAnalog(net) );
+ NetBuilder::load( this, net );
+ Session::revalidate();
+ DebugSession::close();
+ }
+ }
+ AutoSegment::setAnalogMode( false );
+
+#if defined(CHECK_DATABASE)
+ _check ( "after Anabatic loading" );
+#endif
+
+ Session::close();
+
+ stopMeasures();
+ printMeasures( "load" );
+
+ addMeasure( getCell(), "Globals", AutoSegment::getGlobalsCount() );
+ addMeasure( getCell(), "Edges" , AutoSegment::getAllocateds() );
+ }
+
+
void AnabaticEngine::updateNetTopology ( Net* net )
{
DebugSession::open( net, 140, 150 );
diff --git a/anabatic/src/CMakeLists.txt b/anabatic/src/CMakeLists.txt
index e59cfd29..6ff7d7b7 100644
--- a/anabatic/src/CMakeLists.txt
+++ b/anabatic/src/CMakeLists.txt
@@ -29,6 +29,8 @@ endif ( CHECK_DETERMINISM )
anabatic/AutoHorizontal.h
anabatic/AutoVertical.h
anabatic/Session.h
+ anabatic/NetBuilder.h
+ anabatic/NetBuilderHV.h
anabatic/ChipTools.h
)
set( pyIncludes )
@@ -38,9 +40,7 @@ endif ( CHECK_DETERMINISM )
Edge.cpp
Edges.cpp
GCell.cpp
- AnabaticEngine.cpp
Dijkstra.cpp
-
AutoContact.cpp
AutoContactTerminal.cpp
AutoContactTurn.cpp
@@ -52,10 +52,12 @@ endif ( CHECK_DETERMINISM )
Session.cpp
NetConstraints.cpp
NetOptimals.cpp
- LoadGlobalRouting.cpp
+ NetBuilder.cpp
+ NetBuilderHV.cpp
ChipTools.cpp
LayerAssign.cpp
PreRouteds.cpp
+ AnabaticEngine.cpp
)
set( pyCpps PyAnabatic.cpp
)
diff --git a/anabatic/src/LoadGlobalRouting.cpp b/anabatic/src/NetBuilder.cpp
similarity index 67%
rename from anabatic/src/LoadGlobalRouting.cpp
rename to anabatic/src/NetBuilder.cpp
index 05829ec5..3abccd17 100644
--- a/anabatic/src/LoadGlobalRouting.cpp
+++ b/anabatic/src/NetBuilder.cpp
@@ -10,7 +10,7 @@
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
-// | C++ Module : "./LoadGlobalRouting.cpp" |
+// | C++ Module : "./NetBuilder.cpp" |
// +-----------------------------------------------------------------+
@@ -39,12 +39,13 @@
#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/NetBuilder.h"
+#include "anabatic/NetBuilderHV.h"
#include "anabatic/AnabaticEngine.h"
@@ -52,348 +53,6 @@ namespace {
using Anabatic::AutoContactTerminal;
using Hurricane::Breakpoint;
-
-
-
-/*! \defgroup LoadGlobalRouting Global Routing Loading
- * \brief Translation rules to build detailed routing from global
- *
- * This module documents how the global routing built by \c Knik is
- * loaded into the \c Anabatic data-base. It is intented for developpers
- * only.
- */
-
-//! \addtogroup LoadGlobalRouting
-//! \{
-
-//! \enum LocalFunctionFlag
-//! A set of flags for all functions of the LoadGlobalRouting module.
-//! They can be combined to form the \e flags argument of functions.
-//! the functions will ignore flags that are not intended to them.
-//!
-//! For \c HSmall, \c VSmall & \c Punctual see checkRoutingPadSize().
-
-//! \var LocalFunctionFlag::NoFlags
-//! A simple alias over zero to explicitly tell that no flag at all is
-//! passed to the function.
-
-//! \var LocalFunctionFlag::HAccess
-//! The constructed topology will be accessed through an horizontal
-//! segment. The absence of this flag tell that the access will be done
-//! trough a vertical.
-
-//! \var LocalFunctionFlag::VSmall
-//! The RoutingPad vertically covers a very small number of access points,
-//! so it is likely overconstrained for direct horizontal connexion.
-
-//! \var LocalFunctionFlag::HSmall
-//! The RoutingPad horizontally covers a very small number of access points,
-//! so it is likely overconstrained for direct vertical connexion.
-
-//! \var LocalFunctionFlag::Punctual
-//! The RoutingPad covers only an access point in either direction.
-
-//! \var LocalFunctionFlag::DoSourceContact
-//! When creating Anabatic::AutoContactTerminal on non-punctual RoutingPad, this flag
-//! request the creation of a contact on the source point.
-
-//! \var LocalFunctionFlag::DoTargetContact
-//! When creating Anabatic::AutoContactTerminal on non-punctual RoutingPad, this flag
-//! request the creation of a contact on the target point.
-
-
-//! \function uint64_t checkRoutingPadSize ( Component* rp );
-//!
-//! Look at the geometrical size of the Component and assess if
-//! it's span is too narrow either horizontally or vertically.
-//! Return a combination of flags indicating it's state:
-//! - HSmall : less than 3 pitches in horizontal direction.
-//! - VSmall : less than 3 pitches in vertical direction.
-//! - Punctual : one pitch in either directions.
-//!
-//! The component can be a RoutingPad, a Vertical or an Horizontal.
-//!
-//! \image html checkRoutingPadSize.png "checkRoutingPadSize()"
-
-/*! \class GCellTopology
- *
- * \brief Build the wiring for a Net inside a GCell (\b internal).
- *
- * As this class is called to initially construct the Anabatic wiring,
- * it must build a \b connex wiring. That is without gaps in layer depth,
- * because the topology restauration mechanism (AutoContact::updateTopology())
- * of the AutoContact cannot work until all AutoSegments are revalidated at
- * least once. The topology restauration work by creating doglegs which in turn,
- * call the canonization, which needs all the caches to be up to date.
- */
-
-//! \function void GCellTopology::doRp_AutoContacts ( GCell* gcell, Component* rp, AutoContact*& source, AutoContact*& target, uint64_t flags );
-//! \param gcell The GCell into which create the AutoContact.
-//! \param rp The Component we want to access.
-//! \param source The AutoContact created on the \c source (\e returned).
-//! \param target The AutoContact created on the \c target (\e returned).
-//! \param flags Managed by this function:
-//! - LocalFunctionFlag::DoSourceContact
-//! - LocalFunctionFlag::DoTargetContact
-//!
-//! Create the AutoContact directly anchored on the Component (terminal).
-//! Three cases are manageds:
-//! -# Ordinary (non-punctual) \c METAL1 terminal: an AutoContactTerminal
-//! is anchored on the RoutingPad.
-//! -# Punctual \c METAL1 terminal, the access must never be blocked
-//! by other routing. To ensure it, we create a fixed AutoSegment (anchored
-//! on two AutoContactTerminal) to cover it. The \e normal AutoContactTerminal
-//! is also created.
-//! -# non \c METAL1 terminal, as for the punctual \c METAL1, a
-//! fixed protection is added over the RoutingPad. If we access
-//! horizontally a vertical RoutingPad or vertically an horizontal
-//! one, an extra AutoContactTerminal is added (to allow is displacement
-//! along the RoutingPad).
-//!
-//! To avoid creating a fixed protection over a RoutingPad multiple times,
-//! the RoutingPad and it's associated protection is stored in a static
-//! \c map : \c __routingPadAutoSegments.
-//!
-//! Conversely, because an AutoContactTerminal can only be connected to one
-//! segment, each time this function is called a new terminal will be created
-//! (or maybe two in case of non-punctual terminals). If only one AutoContact
-//! is requested, it is created centered on the RoutingPad. The initial
-//! position of AutoContact do not prevent them to move afterwards,
-//! even those created on source/target on a non-punctual RoutingPad.
-//!
-//! \remark For clarity we describe the layer management of this function in term
-//! of \c METAL, but it is the RoutingGauge depth which is actually used.
-//!
-//! \image html doRp_AutoContacts.png "doRp_AutoContacts()"
-
-//! \function AutoContact* GCellTopology::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags );
-//! \param gcell The GCell into which create the AutoContact.
-//! \param rp The Component onto which anchor the access contact.
-//! \param flags Relevant flags are:
-//! - HAccess, the terminal is to be accessed through an horizontal
-//! segment.
-//! - VSmall, force the terminal to be considered as small in the
-//! vertical direction.
-//!
-//! If \c HAccess is set, the Component is to be accessed trough an horizontal
-//! segment. If unset, the access is done vertically.
-//!
-//! Create an AutoContact to access a Component (terminal). If the Component
-//! is not to be accessed through an horizontal segment, and do not cover a
-//! large span in the horizontal direction (flag \c VSmall), a local horizontal
-//! AutoSegment is added to slacken the vertical constraints.
-//!
-//! \image html doRp_Access.png "doRp_Access()"
-
-//! \function AutoContact* GCellTopology::doRp_AccessPad ( RoutingPad* rp, uint64_t flags );
-//! \param rp The Component onto which anchor the access contact.
-//! \param flags Relevant flags are:
-//! - HAccess, the terminal is to be accessed through an horizontal
-//! segment.
-//! - VSmall, force the terminal to be considered as small in the
-//! vertical direction.
-//! \return A Anabatic::AutoContactTerminal .
-//!
-//! The Component \c rp is a RoutingPad which belongs to a pad cell. This case
-//! occurs when we are routing a complete chip. This method build, from the
-//! \c rp a stack of articulated punctual segments and contacts to reach the
-//! default H/V routing layers (usually \c METAL2 & \c METAL3). This may be
-//! needed when the pad terminal is in \c METAL5, for instance.
-//!
-//! The returned AutoContactTerminal is anchored on the last punctual segment
-//! build.
-//!
-//! The GCell into which the AutoContactTerminal is created may be under the
-//! pads area. However, it will be right on the border of the GCell.
-//! The global router vertexes of GCell under the pad area are marked as
-//! blocked so will never be used for routing.
-//!
-//! \remark The segments and contacts added to ensure the layer connexity are not
-//! put into the Anabatic database. They are plain Hurricane objects, invisibles
-//! from it.
-
-//! \function void GCellTopology::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 );
-//!
-//! Build the wiring to connect to horizontal Component. Two cases:
-//! - The Component are aligneds, then only a straight wire is created.
-//! - They are \e not aligned, then a complete dogleg is created.
-//!
-//! \image html doRp_StairCaseH.png "doRp_StairCaseH()"
-
-//! \function void GCellTopology::doRp_StairCaseV ( GCell* gcell, Component* rp1, Component* rp2 );
-//!
-//! Build the wiring to connect to vertical Components. Two cases:
-//! - The Components are aligneds, then only a straight wire is created.
-//! - They are \e not aligned, then a complete dogleg is created.
-//!
-//! \image html doRp_StairCaseV.png "doRp_StairCaseV()"
-
-//! \function void GCellTopology::_do_xG_1Pad ();
-//!
-//! Construct the topology, when there is only global wires and one local
-//! terminal, but coming from a Pad. As thoses connectors will always be
-//! on one border of the GCell they can be considered as a kind of global.
-//!
-//! So this method mostly calls GCellTopology::doRp_AccessPad() to create
-//! the AutoContactTerminal, then calls GCellTopology::_do_xG(), except
-//! for straight lines which are managed directly.
-
-//! \function void GCellTopology::_do_xG ();
-//!
-//! Construct the topology, when there is only global wires (no local terminals).
-//!
-//! Some topology are not handled because they must not be managed by this
-//! function:
-//!
-//! - One global: nonsensical because there also must be a terminal.
-//!
- Two aligned globals: in that case we do a straight wire whithout
-//! any AutoContact (handled by the source/target of the wire).
-//!
-//!
-//! \image html _do_xG.png "_do_xG()"
-
-//! \function void GCellTopology::_do_1G_1M1 ();
-//!
-//! Construct a topology where there is \e one global and one RoutingPad
-//! in \c METAL1. The \c METAL1 is assumed to be vertical.
-//!
-//! \remark When accessing the RoutingPad through an horizontal global segment
-//! and the vertical extension of the segment is small, the global is
-//! still directly attached to the terminal, inducing a high constraint
-//! on it. We left to job of slackening it to the router.
-//!
-//! \image html _do_1G_1M1.png "_do_1G_1M1()"
-
-//! \function void GCellTopology::_do_1G_xM1 ();
-//!
-//! Construct a topology where there is \e one global and any number of
-//! RoutingPad in \c METAL1. The \c METAL1 is assumed to be vertical.
-//!
-//! The RoutingPads are linked together two by two. If the horizontal
-//! segments are not aligned by the router, part of the routage will be
-//! done through the RoutingPad itself. The global incoming segment will
-//! connected to the leftmost, rightmost or centermost RoutingPad according
-//! from wich side it comes from.
-//!
-//! \image html _do_1G_xM1.png "_do_1G_xM1()"
-
-//! \function void GCellTopology::_do_xG_1M1_1M2 ();
-//!
-//! Construct a topology where there is at least one global (and up to 4),
-//! one \c METAL1 RoutingPad (assumed V) and one \c METAL2 RoutingPad (assumed H).
-//!
-//! In this topology, we want to try to reuse the \c METAL2 RoutingPad as a
-//! feedtrough in the horizontal routage. Thus:
-//! - The \c METAL1 and \c METAL2 RoutingPad are connected through a separate wiring.
-//! - The south & west global wiring is attached to the leftmost contact of
-//! the \c METAL2.
-//! - The north & east global wiring is attached to the rightmost contact of
-//! the \c METAL2.
-//!
-//! South/west and north/south can be build independantly. Depending on the number
-//! of globals, they can consist of:
-//! - Nothing (no south nor west).
-//! - An AutoContact (west present).
-//! - An horizontal plus a turn (south present).
-//! - An horizontal plus a HTee (south & west present).
-//!
-//! \remark Not all configurations are represented below.
-//!
-//! \image html _do_xG_1M1_1M2.png "_do_xG_1M1_1M2()"
-
-//! \function void GCellTopology::_do_xG_xM1_xM3 ();
-//!
-//! Construct a topology where there is at least one global (and up to 4),
-//! at least one \c METAL1 RoutingPad (assumed V) and at least one \c METAL3
-//! RoutingPad (assumed V).
-//!
-//! In this topology, we want to try to reuse the \c METAL3 RoutingPad as a
-//! feedtrough in the vertical routage. Thus:
-//! - The \c METAL1 and \c METAL3 RoutingPad are connected through a separate
-//! wiring made of separate horizontals.
-//! - The south-west global wiring is attached to the leftmost RoutingPad
-//! if there isn't south or to the first \c METAL3 otherwise.
-//! - The north-east global wiring is attached to the rightmost RoutingPad
-//! if there isn't north or to the first \c METAL3 otherwise.
-//!
-//! South/west and north/south can be build independantly. Depending on the number
-//! of globals, they can consist of:
-//! - Nothing (no south nor west).
-//! - An AutoContact on the leftmost RoutingPad (west present).
-//! - An AutoContact on the first \c METAL3 (only south present).
-//! - An AutoContact plus a vertical plus a VTee (south & west present).
-//!
-//! \image html _do_xG_xM1_xM3.png "_do_xG_xM1_xM3()"
-
-//! \function void GCellTopology::_do_xG_xM2 ();
-//!
-//! Construct a topology where there is at least one global (and up to 4),
-//! and any number of \c METAL2 RoutingPads (assumeds H).
-//!
-//! In this topology, we want to try to reuse the \c METAL2 RoutingPad as a
-//! feedtrough in the horizontal routage. Thus:
-//! - The RoutingPad are connecteds trough a separate staircase (or
-//! straight wire if aligneds).
-//! - The south-west global wiring is attached to the leftmost RoutingPad
-//! if there isn't south or to the biggest horizontal RoutingPad otherwise.
-//! - The north-east global wiring is attached to the rightmost RoutingPad
-//! if there isn't south or to the biggest horizontal RoutingPad otherwise.
-//!
-//! \image html _do_xG_xM2.png "_do_xG_xM2()"
-
-//! \function void GCellTopology::_do_1G_1M3 ();
-//!
-//! Construct a topology where there is one global and one \c METAL3 RoutingPad
-//! (assumeds V).
-//!
-//! In this topology, we reuse the \c METAL3 RoutingPad as a feedtrough in the
-//! vertical routage. Thus:
-//! - If the global is either north or south, we directly connect to the
-//! north end or south end of the RoutingPad. \red{The vertical global will}
-//! \red{have no slack at all we assume that METAL3 terminals are only from}
-//! \red{blocks and are aligneds vertically.}
-//! - If the global is east or west \e and the RoutingPad is sufficiently
-//! extended in the vertical direction, we connect an horizontal in the
-//! normal way.
-//! - If the global is not sufficiently extended, we add a turn to give some
-//! slack to the global.
-//!
-//!
-//! \image html _do_1G_1M3.png "_do_1G_1M3()"
-
-//! \function void GCellTopology::_do_xG_xM3 ();
-//!
-//! Construct a topology where there at least one global and two \c METAL3 RoutingPad
-//! (assumed V).
-//!
-//! In this topology, we reuse the \c METAL3 RoutingPad as a feedtrough in the
-//! vertical routage. \red{We assume that the most likely relative position}
-//! \red{of the RoutingPads is to be aligned vertically}.
-//! Thus:
-//! - All RoutingPads are linked two by two trough vertical staircases.
-//! - The south-west global wiring is attached to the bottommost RoutingPad
-//! (without vertical slack). If a misalignment is detected, then a
-//! dogleg is added.
-//! - The north-east global wiring is attached to the topmost RoutingPad
-//! (without vertical slack).
-//!
-//! South/west and north/south can be build independantly. Depending on the number
-//! of globals, they can consist of:
-//! - Nothing (no south nor west).
-//! - An sliding AutoContact on the bottommost RoutingPad (west present).
-//! - An fixed AutoContact on the bottommost RoutingPad (only south present).
-//! - An fixed AutoContact plus a vertical plus a VTee (south & west present).
-//!
-//! \image html _do_xG_xM3.png "_do_xG_xM3()"
-
-//! \function void singleGCell ( AnabaticEngine* anbt, Net* net );
-//!
-//! All the RoutingPads of the net are concentrated under a single
-//! GCell. This function assumes that all the terminals are in
-//! \c METAL1 (vertical), and link them two by two by horizontal
-//! wires.
-
-//! \}
using namespace std;
@@ -402,70 +61,51 @@ namespace {
using namespace Anabatic;
- // ---------------------------------------------------------------
- // Local Enum/Types.
-
- enum LocalFunctionFlag { NoFlags = (1 << 0)
- , SortDecreasing = (1 << 1)
- , HAccess = (1 << 2)
- , VSmall = (1 << 3)
- , HSmall = (1 << 4)
- , Punctual = (1 << 5)
- , HCollapse = (1 << 6)
- , VCollapse = (1 << 7)
- , Terminal = (1 << 8)
- , DoSourceContact = (1 << 9)
- , DoTargetContact = (1 << 10)
- , SouthBound = (1 << 11)
- , NorthBound = (1 << 12)
- , WestBound = (1 << 13)
- , EastBound = (1 << 14)
- , Middle = (1 << 15)
- , SouthWest = SouthBound|WestBound
- , NorthEast = NorthBound|EastBound
- };
-
-
// ---------------------------------------------------------------
// Local Variables.
const char* invalidGCell =
- "Anabatic::GCellTopology () :\n\n"
+ "Anabatic::NetBuilder () :\n\n"
" No GCell under point.\n";
const char* mismatchGCell =
- "Anabatic::GCellTopology () :\n\n"
+ "Anabatic::NetBuilder () :\n\n"
" Contacts under two different GCells.\n";
const char* missingGCell =
- "Anabatic::GCellTopology () :\n\n"
+ "Anabatic::NetBuilder () :\n\n"
" No Contact in GCell.\n";
- map __routingPadAutoSegments;
+} // Anonymous namespace.
- // ---------------------------------------------------------------
- // LoadGlobalRouting Local Classes.
+namespace Anabatic {
+
+ using Hurricane::Name;
+ using Hurricane::DebugSession;
+ using Hurricane::Error;
+ using Hurricane::Warning;
+ using Hurricane::Bug;
+
+
+// -------------------------------------------------------------------
+// Class : "NetBuilder".
+
+ map NetBuilder::_routingPadAutoSegments;
+ vector NetBuilder::_toFixSegments;
+ unsigned int NetBuilder::_degree = 0;
- struct NetCompareByName {
- inline bool operator() ( const Net* lhs, const Net* rhs ) const;
- };
+ map& NetBuilder::getRpLookup ()
+ { return _routingPadAutoSegments; }
- inline bool NetCompareByName::operator() ( const Net* lhs, const Net* rhs ) const
- { return lhs->getName() < rhs->getName(); }
+
+ void NetBuilder::clearRpLookup ()
+ { _routingPadAutoSegments.clear(); }
- // ---------------------------------------------------------------
- // LoadGlobalRouting Local Functions.
-
-
- void lookupClear ()
- { __routingPadAutoSegments.clear (); }
-
-
- void getPositions ( Component* anchor, Point& source, Point& target )
+ void NetBuilder::getPositions ( Component* anchor, Point& source, Point& target )
{
Segment* segment = dynamic_cast( anchor );
if (segment) {
@@ -486,7 +126,7 @@ namespace {
}
- uint64_t checkRoutingPadSize ( Component* anchor )
+ uint64_t NetBuilder::checkRoutingPadSize ( Component* anchor )
{
Point source;
Point target;
@@ -494,34 +134,34 @@ namespace {
size_t anchorDepth = Session::getLayerDepth( anchor->getLayer() );
if (anchorDepth == 0) ++anchorDepth;
- getPositions( anchor, source, target );
+ NetBuilder::getPositions( anchor, source, target );
DbU::Unit width = abs( target.getX() - source.getX() );
DbU::Unit height = abs( target.getY() - source.getY() );
uint64_t flags = 0;
- flags |= (width < 3*Session::getPitch(anchorDepth)) ? HSmall : 0;
- flags |= (height < 3*Session::getPitch(anchorDepth)) ? VSmall : 0;
- flags |= ((width == 0) && (height == 0)) ? Punctual : 0;
+ flags |= (width < 3*Session::getPitch(anchorDepth)) ? NetBuilder::HSmall : 0;
+ flags |= (height < 3*Session::getPitch(anchorDepth)) ? NetBuilder::VSmall : 0;
+ flags |= ((width == 0) && (height == 0)) ? NetBuilder::Punctual : 0;
cdebug_log(145,0) << "::checkRoutingPadSize(): pitch[" << anchorDepth << "]:"
<< DbU::getValueString(Session::getPitch(anchorDepth)) << " "
- << ((flags & HSmall) ? "HSmall " : " ")
- << ((flags & VSmall) ? "VSmall " : " ")
+ << ((flags & NetBuilder::HSmall) ? "HSmall " : " ")
+ << ((flags & NetBuilder::VSmall) ? "VSmall " : " ")
<< endl;
return flags;
}
- Hook* getSegmentOppositeHook ( Hook* hook )
+ Hook* NetBuilder::getSegmentOppositeHook ( Hook* hook )
{
Segment* segment = static_cast( hook->getComponent() );
return segment->getOppositeHook( hook );
}
- uint64_t getSegmentHookType ( Hook* hook )
+ uint64_t NetBuilder::getSegmentHookType ( Hook* hook )
{
Horizontal* horizontal = dynamic_cast( hook->getComponent() );
if (horizontal) {
@@ -529,8 +169,8 @@ namespace {
cerr << Warning("Bad orientation of %s",getString(horizontal).c_str()) << endl;
if (dynamic_cast(hook))
- return EastBound;
- return WestBound;
+ return NetBuilder::EastBound;
+ return NetBuilder::WestBound;
} else {
Vertical* vertical = dynamic_cast( hook->getComponent() );
if (vertical) {
@@ -538,398 +178,16 @@ namespace {
cerr << Warning("Bad orientation of %s",getString(vertical).c_str()) << endl;
if (dynamic_cast(hook))
- return NorthBound;
+ return NetBuilder::NorthBound;
} else {
cerr << Warning("Unmanaged Hook %s",getString(hook).c_str()) << endl;
}
}
- return SouthBound;
+ return NetBuilder::SouthBound;
}
-// ---------------------------------------------------------------
-// Class : "SortHookByX".
-
- class SortHookByX {
- public:
- inline SortHookByX ( uint64_t flags );
- inline bool operator() ( Hook* h1, Hook* h2 );
- protected:
- uint64_t _flags;
- };
-
-
- inline SortHookByX::SortHookByX ( uint64_t flags )
- : _flags(flags)
- { }
-
-
- inline bool SortHookByX::operator() ( Hook* h1, Hook* h2 )
- {
- DbU::Unit x1 = 0;
- DbU::Unit x2 = 0;
- Horizontal* hh1 = dynamic_cast(h1->getComponent());
- Horizontal* hh2 = dynamic_cast(h2->getComponent());
- Vertical* vv1 = dynamic_cast (h1->getComponent());
- Vertical* vv2 = dynamic_cast (h2->getComponent());
-
- if (hh1) x1 = min( hh1->getSource()->getX(), hh1->getTarget()->getX() );
- else if (vv1) x1 = vv1->getX();
- else x1 = h1->getComponent()->getCenter().getX();
-
- if (hh2) x2 = min( hh2->getSource()->getX(), hh2->getTarget()->getX() );
- else if (vv2) x2 = vv2->getX();
- else x2 = h2->getComponent()->getCenter().getX();
-
- if (x1 == x2) return false;
- return (_flags & SortDecreasing) xor (x1 < x2);
- }
-
-
-// ---------------------------------------------------------------
-// Class : "SortHookByY".
-
- class SortHookByY {
- public:
- inline SortHookByY ( uint64_t flags );
- inline bool operator() ( Hook* h1, Hook* h2 );
- protected:
- uint64_t _flags;
- };
-
-
- inline SortHookByY::SortHookByY ( uint64_t flags )
- : _flags(flags)
- { }
-
-
- inline bool SortHookByY::operator() ( Hook* h1, Hook* h2 )
- {
- DbU::Unit y1 = 0;
- DbU::Unit y2 = 0;
- Horizontal* hh1 = dynamic_cast(h1->getComponent());
- Horizontal* hh2 = dynamic_cast(h2->getComponent());
- Vertical* vv1 = dynamic_cast (h1->getComponent());
- Vertical* vv2 = dynamic_cast (h2->getComponent());
-
- if (vv1) y1 = min( vv1->getSource()->getY(), vv1->getTarget()->getY() );
- else if (hh1) y1 = hh1->getY();
- else y1 = h1->getComponent()->getCenter().getX();
-
- if (vv2) y2 = min( vv2->getSource()->getY(), vv2->getTarget()->getY() );
- else if (hh2) y2 = hh2->getY();
- else y2 = h2->getComponent()->getCenter().getY();
-
- if (y1 == y2) return false;
- return (_flags & SortDecreasing) xor (y1 < y2);
- }
-
- // ---------------------------------------------------------------
- // Class : "SortRpByX".
-
- class SortRpByX {
- public:
- inline SortRpByX ( uint64_t flags );
- inline bool operator() ( Component* rp1, Component* rp2 );
- protected:
- uint64_t _flags;
- };
-
-
- inline SortRpByX::SortRpByX ( uint64_t flags )
- : _flags(flags)
- { }
-
-
- inline bool SortRpByX::operator() ( Component* rp1, Component* rp2 )
- {
- DbU::Unit x1 = rp1->getCenter().getX();
- DbU::Unit x2 = rp2->getCenter().getX();
-
- if (x1 == x2) return false;
- return (_flags & SortDecreasing) xor (x1 < x2);
- }
-
-
- // ---------------------------------------------------------------
- // Class : "SortRpByY".
-
- class SortRpByY {
- public:
- inline SortRpByY ( uint64_t flags );
- inline bool operator() ( Component* rp1, Component* rp2 );
- protected:
- uint64_t _flags;
- };
-
-
- inline SortRpByY::SortRpByY ( uint64_t flags )
- : _flags(flags)
- { }
-
-
- inline bool SortRpByY::operator() ( Component* rp1, Component* rp2 )
- {
- DbU::Unit y1 = rp1->getCenter().getY();
- DbU::Unit y2 = rp2->getCenter().getY();
-
- if (y1 == y2) return false;
- return (_flags & SortDecreasing) xor (y1 < y2);
- }
-
-
- // ---------------------------------------------------------------
- // Class : "ForkStack".
-
- class ForkStack {
- public:
- inline void push ( Hook* from, AutoContact* contact );
- inline void pop ();
- inline Hook* getFrom () const;
- inline AutoContact* getContact () const;
- private:
- struct Element {
- Hook* _from;
- AutoContact* _contact;
- inline Element ( Hook* from, AutoContact* contact );
- };
- private:
- list _stack;
- };
-
-
- inline ForkStack::Element::Element ( Hook* from, AutoContact* contact ) : _from(from), _contact(contact) {}
- inline void ForkStack::pop () { if (not _stack.empty()) _stack.pop_back(); }
- inline Hook* ForkStack::getFrom () const { return _stack.empty() ? NULL : _stack.back()._from; }
- inline AutoContact* ForkStack::getContact () const { return _stack.empty() ? NULL : _stack.back()._contact; }
-
-
- inline void ForkStack::push ( Hook* from, AutoContact* contact )
- {
- cdebug_log(145,0) << " Stacking " << from << " + " << contact << endl;
- _stack.push_back( Element(from,contact) );
- }
-
-
- // ---------------------------------------------------------------
- // Class : "GGellTopology".
-
- class GCellTopology {
-
- public:
- static void init ( unsigned int degree );
- static void fixSegments ();
- GCellTopology ( AnabaticEngine*
- , ForkStack&
- , Hook* fromHook
- , AutoContact* sourceContact=NULL );
- void construct ();
- inline unsigned int getStateG () const;
- inline GCell* getGCell () const;
- inline Hook* north ( size_t i=0 ) const;
- inline Hook* south ( size_t i=0 ) const;
- inline Hook* east ( size_t i=0 ) const;
- inline Hook* west ( size_t i=0 ) const;
- inline bool push ( Hook* to, AutoContact* contact, uint64_t flags=NoFlags );
- static void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
- static AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
- static AutoContact* doRp_AccessPad ( RoutingPad*, uint64_t flags );
- static AutoContact* doRp_AccessAnalog ( GCell*, RoutingPad*, uint64_t flags );
- AutoContact* doRp_2m_Access ( GCell*, RoutingPad*, uint64_t flags );
- static void doRp_StairCaseH ( GCell*, Component* rp1, Component* rp2 );
- static void doRp_StairCaseV ( GCell*, Component* rp1, Component* rp2 );
- private:
- void _do_2m_1G_1M1 ();
- void _do_2m_2G_1M1 ();
- void _do_2m_xG ();
- void _do_xG ();
- void _do_2G ();
- void _do_xG_1Pad ();
- void _do_1G_1PinM2 ();
- void _do_1G_1M1 ();
- void _do_1G_xM1 ();
- void _do_xG_xM1_xM3 ();
- void _do_xG_1M1_1M2 ();
- void _do_4G_1M2 ();
- void _do_xG_xM2 ();
- void _do_1G_1M3 ();
- void _do_xG_xM3 ();
- AutoContact* _doHChannel ();
- AutoContact* _doVChannel ();
- AutoContact* _doStrut ();
- AutoContact* _doDevice ();
- AutoContact* _doHRail ();
- AutoContact* _doVRail ();
- void _doIoPad ();
-
- unsigned int getNumberGlobals ();
- unsigned int getDeviceNeighbourBound();
-
-
-
- private:
- enum ConnexityBits { GlobalBSize = 8
- , Metal1BSize = 4
- , Metal2BSize = 4
- , Metal3BSize = 4
- , PadsBSize = 4
- , PinsBSize = 4
- };
-
-#define CONNEXITY_VALUE( Gs, M1s, M2s, M3s, pads, pins ) \
- Gs + ((M1s ) << GlobalBSize) \
- + ((M2s ) << (GlobalBSize+Metal1BSize)) \
- + ((M3s ) << (GlobalBSize+Metal1BSize+Metal2BSize)) \
- + ((pads) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize)) \
- + ((pins) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize+PadsBSize))
-
- // Connexity Name | G|M1|M2|M2|Pad|Pin|
- enum ConnexityFlag { Conn_0G = CONNEXITY_VALUE( 0, 0, 0, 0, 0 , 0 )
- , Conn_2G = CONNEXITY_VALUE( 2, 0, 0, 0, 0 , 0 )
- , Conn_3G = CONNEXITY_VALUE( 3, 0, 0, 0, 0 , 0 )
- , Conn_4G = CONNEXITY_VALUE( 4, 0, 0, 0, 0 , 0 )
- , Conn_0G_2M1 = CONNEXITY_VALUE( 0, 2, 0, 0, 0 , 0 )
- , Conn_1G_1M1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 0 )
- , Conn_1G_2M1 = CONNEXITY_VALUE( 1, 2, 0, 0, 0 , 0 )
- , Conn_1G_3M1 = CONNEXITY_VALUE( 1, 3, 0, 0, 0 , 0 )
- , Conn_1G_4M1 = CONNEXITY_VALUE( 1, 4, 0, 0, 0 , 0 )
- , Conn_1G_5M1 = CONNEXITY_VALUE( 1, 5, 0, 0, 0 , 0 )
- , Conn_1G_1M2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 0 )
- , Conn_1G_2M2 = CONNEXITY_VALUE( 1, 0, 2, 0, 0 , 0 )
- , Conn_1G_3M2 = CONNEXITY_VALUE( 1, 0, 3, 0, 0 , 0 )
- , Conn_1G_4M2 = CONNEXITY_VALUE( 1, 0, 4, 0, 0 , 0 )
- , Conn_1G_1M3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 0 )
- , Conn_1G_2M3 = CONNEXITY_VALUE( 1, 0, 0, 2, 0 , 0 )
- , Conn_1G_3M3 = CONNEXITY_VALUE( 1, 0, 0, 3, 0 , 0 )
- , Conn_1G_4M3 = CONNEXITY_VALUE( 1, 0, 0, 4, 0 , 0 )
- , Conn_1G_1M1_1M2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 0 )
- , Conn_1G_1M1_1M3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 0 )
- // Connexity Name | G|M1|M2|M2|Pad|Pin|
- , Conn_2G_1M1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 0 )
- , Conn_2G_2M1 = CONNEXITY_VALUE( 2, 2, 0, 0, 0 , 0 )
- , Conn_2G_3M1 = CONNEXITY_VALUE( 2, 3, 0, 0, 0 , 0 )
- , Conn_2G_4M1 = CONNEXITY_VALUE( 2, 4, 0, 0, 0 , 0 )
- , Conn_2G_5M1 = CONNEXITY_VALUE( 2, 5, 0, 0, 0 , 0 )
- , Conn_2G_1M2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 0 )
- , Conn_2G_2M2 = CONNEXITY_VALUE( 2, 0, 2, 0, 0 , 0 )
- , Conn_2G_3M2 = CONNEXITY_VALUE( 2, 0, 3, 0, 0 , 0 )
- , Conn_2G_4M2 = CONNEXITY_VALUE( 2, 0, 4, 0, 0 , 0 )
- , Conn_2G_1M3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 0 )
- , Conn_2G_2M3 = CONNEXITY_VALUE( 2, 0, 0, 2, 0 , 0 )
- , Conn_2G_3M3 = CONNEXITY_VALUE( 2, 0, 0, 3, 0 , 0 )
- , Conn_2G_4M3 = CONNEXITY_VALUE( 2, 0, 0, 4, 0 , 0 )
- , Conn_2G_1M1_1M2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 0 )
- // Connexity Name | G|M1|M2|M2|Pad|Pin|
- , Conn_3G_1M1 = CONNEXITY_VALUE( 3, 1, 0, 0, 0 , 0 )
- , Conn_3G_2M1 = CONNEXITY_VALUE( 3, 2, 0, 0, 0 , 0 )
- , Conn_3G_3M1 = CONNEXITY_VALUE( 3, 3, 0, 0, 0 , 0 )
- , Conn_3G_4M1 = CONNEXITY_VALUE( 3, 4, 0, 0, 0 , 0 )
- , Conn_3G_1M2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 0 )
- , Conn_3G_2M2 = CONNEXITY_VALUE( 3, 0, 2, 0, 0 , 0 )
- , Conn_3G_1M3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 0 )
- , Conn_3G_2M3 = CONNEXITY_VALUE( 3, 0, 0, 2, 0 , 0 )
- , Conn_3G_3M3 = CONNEXITY_VALUE( 3, 0, 0, 3, 0 , 0 )
- , Conn_3G_4M3 = CONNEXITY_VALUE( 3, 0, 0, 4, 0 , 0 )
- // Connexity Name | G|M1|M2|M2|Pad|Pin|
- , Conn_4G_1M1 = CONNEXITY_VALUE( 4, 1, 0, 0, 0 , 0 )
- , Conn_4G_2M1 = CONNEXITY_VALUE( 4, 2, 0, 0, 0 , 0 )
- , Conn_4G_3M1 = CONNEXITY_VALUE( 4, 3, 0, 0, 0 , 0 )
- , Conn_4G_4M1 = CONNEXITY_VALUE( 4, 4, 0, 0, 0 , 0 )
- , Conn_4G_1M2 = CONNEXITY_VALUE( 4, 0, 1, 0, 0 , 0 )
- , Conn_4G_1M3 = CONNEXITY_VALUE( 4, 0, 0, 1, 0 , 0 )
- , Conn_1G_1Pad = CONNEXITY_VALUE( 1, 0, 0, 0, 1 , 0 )
- , Conn_2G_1Pad = CONNEXITY_VALUE( 2, 0, 0, 0, 1 , 0 )
- , Conn_3G_1Pad = CONNEXITY_VALUE( 3, 0, 0, 0, 1 , 0 )
- , Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 )
- , Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 )
- };
-
- // Connexity Union Type.
- union UConnexity {
- uint64_t connexity;
- struct {
- unsigned int globals : GlobalBSize;
- unsigned int M1 : Metal1BSize;
- unsigned int M2 : Metal2BSize;
- unsigned int M3 : Metal3BSize;
- unsigned int Pad : PadsBSize;
- unsigned int Pin : PinsBSize;
- } fields;
- };
-
- enum TopologyFlag { Global_Vertical_End = 0x00000001
- , Global_Horizontal_End = 0x00000002
- , Global_Horizontal = 0x00000004
- , Global_Vertical = 0x00000008
- , Global_Turn = 0x00000010
- , Global_Fork = 0x00000020
- , Global_Fixed = 0x00000040
- , Global_End = Global_Vertical_End | Global_Horizontal_End
- , Global_Split = Global_Horizontal | Global_Vertical | Global_Fork
- };
-
- // Attributes.
- private:
- static vector _toFixSegments;
- static unsigned int _degree;
- ForkStack& _forks;
- UConnexity _connexity;
- unsigned int _topology;
- Net* _net;
- GCell* _gcell;
- AutoContact* _sourceContact;
- AutoContact* _southWestContact;
- AutoContact* _northEastContact;
- Hook* _fromHook;
- vector _easts;
- vector _wests;
- vector _norths;
- vector _souths;
- vector _routingPads;
- };
-
-
- inline unsigned int GCellTopology::getStateG () const { return _connexity.fields.globals; }
- inline GCell* GCellTopology::getGCell () const { return _gcell; }
- inline Hook* GCellTopology::north ( size_t i ) const { return (i<_norths.size()) ? _norths[i] : NULL; }
- inline Hook* GCellTopology::south ( size_t i ) const { return (i<_souths.size()) ? _souths[i] : NULL; }
- inline Hook* GCellTopology::east ( size_t i ) const { return (i<_easts .size()) ? _easts [i] : NULL; }
- inline Hook* GCellTopology::west ( size_t i ) const { return (i<_wests .size()) ? _wests [i] : NULL; }
-
- inline bool GCellTopology::push ( Hook* toHook, AutoContact* contact, uint64_t flags )
- {
- cdebug_log(145,0) << "GCellTopology::push()" << endl;
- cdebug_log(145,0) << "* toHook: " << toHook << endl;
- cdebug_log(145,0) << "* _fromHook:" << _fromHook << endl;
-
- if (not toHook or (toHook == _fromHook)) {
- if (contact) {
- if ( (flags & SouthWest) and not _southWestContact ) {
- cdebug_log(145,0) << "Setting _southWestContact:" << contact << endl;
- _southWestContact = contact;
- }
- if ( (flags & NorthEast) and not _northEastContact ) {
- cdebug_log(145,0) << "Setting _northEastContact:" << contact << endl;
- _northEastContact = contact;
- }
- }
- return false;
- }
-
- Hook* toHookOpposite = getSegmentOppositeHook( toHook );
- cdebug_log(145,0) << "Pushing (to) " << getString(toHook) << endl;
- cdebug_log(145,0) << "Pushing (from) " << contact << endl;
- _forks.push( toHookOpposite, contact );
-
- return true;
- }
-
-
- vector GCellTopology::_toFixSegments;
- unsigned int GCellTopology::_degree = 0;
-
-
- void GCellTopology::fixSegments ()
+ void NetBuilder::fixSegments ()
{
for ( size_t i=0 ; i<_toFixSegments.size() ; ++i )
_toFixSegments[i]->setFlags( AutoSegment::SegFixed );
@@ -937,37 +195,60 @@ namespace {
}
- void GCellTopology::init ( unsigned int degree )
+ void NetBuilder::init ( unsigned int degree )
{
_degree = degree;
_toFixSegments.clear();
}
- GCellTopology::GCellTopology ( AnabaticEngine* anbt
- , ForkStack& forks
- , Hook* fromHook
- , AutoContact* sourceContact )
- : _forks (forks)
+ NetBuilder::NetBuilder ()
+ : _forks ()
, _connexity ()
, _topology (0)
, _gcell (NULL)
- , _sourceContact (sourceContact)
+ , _sourceContact (NULL)
, _southWestContact(NULL)
, _northEastContact(NULL)
- , _fromHook (fromHook)
+ , _fromHook (NULL)
, _easts ()
, _wests ()
, _norths ()
, _souths ()
, _routingPads ()
+ { }
+
+
+ void NetBuilder::clear ()
{
_connexity.connexity = 0;
+ _topology = 0;
+ _gcell = NULL;
+ _sourceContact = NULL;
+ _southWestContact = NULL;
+ _northEastContact = NULL;
+ _fromHook = NULL;
+ _easts .clear();
+ _wests .clear();
+ _norths .clear();
+ _souths .clear();
+ _routingPads.clear();
+ }
+
- cdebug_log(145,1) << "GCellTopology::GCellTopology()" << endl;
+ NetBuilder& NetBuilder::startFrom ( AnabaticEngine* anbt, Hook* fromHook, AutoContact* sourceContact )
+ {
+ clear();
+
+ _sourceContact = sourceContact;
+ _fromHook = fromHook;
+
+ cdebug_log(145,1) << "NetBuilder::NetBuilder()" << endl;
cdebug_log(145,0) << "* _fromHook: " << fromHook << endl;
cdebug_log(145,0) << "* _sourceContact:" << sourceContact << endl;
+ if (not _fromHook) return *this;
+
Segment* fromSegment = static_cast( _fromHook->getComponent() );
_net = fromSegment->getNet();
@@ -1072,12 +353,47 @@ namespace {
cdebug_tabw(145,-1);
if (_gcell == NULL) throw Error( missingGCell );
+
+ return *this;
}
- void GCellTopology::construct ()
+ NetBuilder::~NetBuilder ()
+ { }
+
+
+ bool NetBuilder::push ( Hook* toHook, AutoContact* contact, uint64_t flags )
{
- cdebug_log(145,1) << "GCellTopology::construct() [" << _connexity.connexity << "] in " << _gcell << endl;
+ cdebug_log(145,0) << "NetBuilder::push()" << endl;
+ cdebug_log(145,0) << "* toHook: " << toHook << endl;
+ cdebug_log(145,0) << "* _fromHook:" << _fromHook << endl;
+
+ if (not toHook or (toHook == _fromHook)) {
+ if (contact) {
+ if ( (flags & SouthWest) and not _southWestContact ) {
+ cdebug_log(145,0) << "Setting _southWestContact:" << contact << endl;
+ _southWestContact = contact;
+ }
+ if ( (flags & NorthEast) and not _northEastContact ) {
+ cdebug_log(145,0) << "Setting _northEastContact:" << contact << endl;
+ _northEastContact = contact;
+ }
+ }
+ return false;
+ }
+
+ Hook* toHookOpposite = getSegmentOppositeHook( toHook );
+ cdebug_log(145,0) << "Pushing (to) " << getString(toHook) << endl;
+ cdebug_log(145,0) << "Pushing (from) " << contact << endl;
+ _forks.push( toHookOpposite, contact );
+
+ return true;
+ }
+
+
+ void NetBuilder::construct ()
+ {
+ cdebug_log(145,1) << "NetBuilder::construct() [" << _connexity.connexity << "] in " << _gcell << endl;
_southWestContact = NULL;
_northEastContact = NULL;
@@ -1259,130 +575,7 @@ namespace {
}
- void GCellTopology::doRp_AutoContacts ( GCell* gcell
- , Component* rp
- , AutoContact*& source
- , AutoContact*& target
- , uint64_t flags
- )
- {
- cdebug_log(145,1) << "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::iterator irp = __routingPadAutoSegments.find( rp );
- if (irp == __routingPadAutoSegments.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 );
-
- __routingPadAutoSegments.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* GCellTopology::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
- {
- cdebug_log(145,1) << "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;
- }
-
-
- AutoContact* GCellTopology::doRp_AccessPad ( RoutingPad* rp, uint64_t flags )
+ AutoContact* NetBuilder::doRp_AccessPad ( RoutingPad* rp, uint64_t flags )
{
cdebug_log(145,1) << "doRp_AccessPad()" << endl;
cdebug_log(145,0) << rp << endl;
@@ -1391,7 +584,7 @@ namespace {
size_t accessDepth = (flags & HAccess) ? 1 : 2 ;
size_t padDepth = Session::getLayerDepth(rp->getLayer());
if (padDepth > Session::getAllowedDepth()) {
- cerr << Error( "GCellTopology::doRp_AccessPad(): Pad RoutingPad %s\n"
+ cerr << Error( "NetBuilder::doRp_AccessPad(): Pad RoutingPad %s\n"
" has a layer unreachable by the router (top layer is: %s)"
, getString(rp).c_str()
, getString(Session::getRoutingLayer(Session::getAllowedDepth())).c_str()
@@ -1529,7 +722,7 @@ namespace {
}
- AutoContact* GCellTopology::doRp_AccessAnalog ( GCell* gcell, RoutingPad* rp, uint64_t flags )
+ AutoContact* NetBuilder::doRp_AccessAnalog ( GCell* gcell, RoutingPad* rp, uint64_t flags )
{
cdebug_log(145,1) << "doRp_AccessAnalog()" << endl;
cdebug_log(145,0) << rp << endl;
@@ -1543,7 +736,7 @@ namespace {
AutoContact* contact = AutoContactTerminal::create( gcell, rp, rpLayer, position, viaSide, viaSide );
if (position != onGrid) {
- cerr << Bug( "GCellTopology::doRp_AccessAnalog(): RoutingPad is not under any grid point.\n"
+ cerr << Bug( "NetBuilder::doRp_AccessAnalog(): RoutingPad is not under any grid point.\n"
" %s\n"
" Using nearest grid point: %s"
, getString(rp).c_str()
@@ -1553,7 +746,7 @@ namespace {
}
if (rpDepth != 1) {
- cerr << Bug( "GCellTopology::doRp_AccessAnalog(): RoutingPad must be in METAL2 layer.\n"
+ cerr << Bug( "NetBuilder::doRp_AccessAnalog(): RoutingPad must be in METAL2 layer.\n"
" %s"
, getString(rp).c_str()
) << endl;
@@ -1565,7 +758,7 @@ namespace {
}
- AutoContact* GCellTopology::doRp_2m_Access ( GCell* gcell, RoutingPad* rp, uint64_t flags )
+ AutoContact* NetBuilder::doRp_2m_Access ( GCell* gcell, RoutingPad* rp, uint64_t flags )
{
cdebug_log(145,1) << "doRp_2m_Access()" << endl;
cdebug_log(145,0) << rp << endl;
@@ -1609,7 +802,7 @@ namespace {
}
- void GCellTopology::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 )
+ void NetBuilder::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 )
{
cdebug_log(145,0) << "doRp_StairCaseH()" << endl;
@@ -1643,7 +836,7 @@ namespace {
}
- void GCellTopology::doRp_StairCaseV ( GCell* gcell, Component* rp1, Component* rp2 )
+ void NetBuilder::doRp_StairCaseV ( GCell* gcell, Component* rp1, Component* rp2 )
{
cdebug_log(145,0) << "doRp_StairCaseV()" << endl;
@@ -1677,7 +870,7 @@ namespace {
}
- void GCellTopology::_do_2m_1G_1M1 ()
+ void NetBuilder::_do_2m_1G_1M1 ()
{
cdebug_log(145,1) << "_do_2m_1G_1M1()" << endl;
@@ -1694,7 +887,7 @@ namespace {
}
- void GCellTopology::_do_2m_2G_1M1 ()
+ void NetBuilder::_do_2m_2G_1M1 ()
{
cdebug_log(145,1) << "_do_2m_2G_1M1()" << endl;
@@ -1709,7 +902,7 @@ namespace {
}
- void GCellTopology::_do_2m_xG ()
+ void NetBuilder::_do_2m_xG ()
{
cdebug_log(145,1) << "_do_2m_xG()" << endl;
@@ -1783,7 +976,7 @@ namespace {
}
- void GCellTopology::_do_xG ()
+ void NetBuilder::_do_xG ()
{
cdebug_log(145,1) << "_do_xG()" << endl;
@@ -1816,7 +1009,7 @@ namespace {
}
- void GCellTopology::_do_2G ()
+ void NetBuilder::_do_2G ()
{
cdebug_log(145,1) << "_do_2G()" << endl;
@@ -1838,7 +1031,7 @@ namespace {
}
- void GCellTopology::_do_xG_1Pad ()
+ void NetBuilder::_do_xG_1Pad ()
{
cdebug_log(145,1) << "_do_xG_1Pad() [Managed Configuration - Optimized] " << _topology << endl;
cdebug_log(145,0) << "_connexity.globals:" << (int)_connexity.fields.globals << endl;
@@ -1942,7 +1135,7 @@ namespace {
}
- void GCellTopology::_do_1G_1PinM2 ()
+ void NetBuilder::_do_1G_1PinM2 ()
{
cdebug_log(145,1) << "_do_1G_1PinM2() [Managed Configuration - Optimized] " << _topology << endl;
@@ -1961,63 +1154,7 @@ namespace {
}
- void GCellTopology::_do_1G_1M1 ()
- {
- cdebug_log(145,1) << "_do_1G_1M1() [Managed Configuration - Optimized] " << _topology << endl;
-
- uint64_t flags = NoFlags;
- if (east() ) { flags |= HAccess; }
- else if (west() ) { flags |= HAccess; }
- else if (north()) { flags |= VSmall; }
- else if (south()) { flags |= VSmall; }
-
- _southWestContact = _northEastContact = doRp_Access( _gcell, _routingPads[0], flags );
-
- cdebug_tabw(145,-1);
- }
-
-
- void GCellTopology::_do_1G_xM1 ()
- {
- cdebug_log(145,1) << "_do_1G_" << (int)_connexity.fields.M1 << "M1() [Managed Configuration]" << endl;
-
- sort( _routingPads.begin(), _routingPads.end(), SortRpByX(NoFlags) ); // increasing X.
- for ( size_t i=1 ; i<_routingPads.size() ; ++i ) {
- AutoContact* leftContact = doRp_Access( _gcell, _routingPads[i-1], HAccess );
- AutoContact* rightContact = doRp_Access( _gcell, _routingPads[i ], HAccess );
- AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
- }
-
- Component* globalRp = NULL;
- if (east()) globalRp = _routingPads[_routingPads.size()-1];
- else if (west()) globalRp = _routingPads[0];
- else {
- globalRp = _routingPads[0];
-
- cdebug_log(145,0) << "| Initial N/S Global RP: " << globalRp << endl;
- for ( size_t i=1 ; i<_routingPads.size() ; ++i ) {
- if (_routingPads[i]->getBoundingBox().getHeight() > globalRp->getBoundingBox().getHeight()) {
- cdebug_log(145,0) << "| Better RP: " << globalRp << endl;
- globalRp = _routingPads[i];
- }
- }
- }
-
- AutoContact* globalContact = doRp_Access( _gcell, globalRp, HAccess );
-
- if (north() or south()) {
- AutoContact* turn = globalContact;
- globalContact = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) );
- AutoSegment::create( globalContact, turn, Flags::Horizontal );
- }
-
- _northEastContact = _southWestContact = globalContact;
-
- cdebug_tabw(145,-1);
- }
-
-
- void GCellTopology::_do_xG_1M1_1M2 ()
+ void NetBuilder::_do_xG_1M1_1M2 ()
{
cdebug_log(145,1) << "_do_xG_1M1_1M2() [Managed Configuration]" << endl;
@@ -2082,7 +1219,7 @@ namespace {
}
- void GCellTopology::_do_xG_xM1_xM3 ()
+ void NetBuilder::_do_xG_xM1_xM3 ()
{
cdebug_log(145,1) << "_do_xG_" << (int)_connexity.fields.M1
<< "M1_" << (int)_connexity.fields.M3
@@ -2191,7 +1328,7 @@ namespace {
}
- void GCellTopology::_do_4G_1M2 ()
+ void NetBuilder::_do_4G_1M2 ()
{
cdebug_log(145,1) << "_do_4G_1M2() [Managed Configuration]" << endl;
@@ -2215,7 +1352,7 @@ namespace {
}
- void GCellTopology::_do_xG_xM2 ()
+ void NetBuilder::_do_xG_xM2 ()
{
cdebug_log(145,1) << "_do_"
<< (int)_connexity.fields.globals << "G_"
@@ -2255,7 +1392,7 @@ namespace {
}
- void GCellTopology::_do_1G_1M3 ()
+ void NetBuilder::_do_1G_1M3 ()
{
cdebug_log(145,1) << "_do_1G_1M3() [Optimised Configuration]" << endl;
@@ -2300,7 +1437,7 @@ namespace {
}
- void GCellTopology::_do_xG_xM3 ()
+ void NetBuilder::_do_xG_xM3 ()
{
cdebug_log(145,1) << "_do_xG_" << (int)_connexity.fields.M3
<< "M3() [Managed Configuration]" << endl;
@@ -2369,9 +1506,9 @@ namespace {
}
- void singleGCell ( AnabaticEngine* anbt, Net* net )
+ void NetBuilder::singleGCell ( AnabaticEngine* anbt, Net* net )
{
- cdebug_log(145,1) << "singleGCell() " << net << endl;
+ cdebug_log(145,1) << "NetBuilder::singleGCell() " << net << endl;
vector rpM1s;
Component* rpM2 = NULL;
@@ -2397,7 +1534,7 @@ namespace {
return;
}
- sort( rpM1s.begin(), rpM1s.end(), SortRpByX(NoFlags) ); // increasing X.
+ sort( rpM1s.begin(), rpM1s.end(), SortRpByX(NetBuilder::NoFlags) ); // increasing X.
GCell* gcell1 = anbt->getGCellUnder( (*rpM1s.begin ())->getCenter() );
GCell* gcell2 = anbt->getGCellUnder( (*rpM1s.rbegin())->getCenter() );
@@ -2420,14 +1557,14 @@ namespace {
AutoContact* target = NULL;
for ( size_t irp=1 ; irpgetNet(), Session::getContactLayer(1) );
AutoSegment::create( source, turn , Flags::Horizontal );
AutoSegment::create( turn , target, Flags::Vertical );
@@ -2481,14 +1618,14 @@ namespace {
}
- AutoContact* GCellTopology::_doDevice ()
+ AutoContact* NetBuilder::_doDevice ()
{
- cdebug_log(145,1) << "void GCellTopology::_doDevice ()" << _gcell << endl;
+ cdebug_log(145,1) << "void NetBuilder::_doDevice ()" << _gcell << endl;
for ( size_t i=0; i<_routingPads.size() ; i++ ) {
if ( (_routingPads[i]->getSourcePosition().getX() == _routingPads[i]->getTargetPosition().getX())
and (_routingPads[i]->getSourcePosition().getY() == _routingPads[i]->getTargetPosition().getY()) ) {
- throw Error( "GCellTopology::_doDevice() Some RoutingPads are not set to a component.\n"
+ throw Error( "NetBuilder::_doDevice() Some RoutingPads are not set to a component.\n"
" On: %s."
, getString(_gcell).c_str() );
}
@@ -2522,7 +1659,7 @@ namespace {
cdebug_log(145,0) << "rpSW: " << rpSW << endl;
} else if (_routingPads.size() == 0) {
cdebug_log(145,0) << "Case _routingPads.size() = 0 "<< endl;
- throw Error( "GCellTopology::_doDevice() No RoutingPads found.\n"
+ throw Error( "NetBuilder::_doDevice() No RoutingPads found.\n"
" On: %s."
, getString(_gcell).c_str() );
} else {
@@ -2561,9 +1698,9 @@ namespace {
}
- AutoContact* GCellTopology::_doHChannel ()
+ AutoContact* NetBuilder::_doHChannel ()
{
- cdebug_log(145,1) << "void GCellTopology::_doHChannel() " << _gcell << endl;
+ cdebug_log(145,1) << "void NetBuilder::_doHChannel() " << _gcell << endl;
vector hooks;
Hook* firsthhook = NULL;
@@ -2581,7 +1718,7 @@ namespace {
if (h) {
if (h->getSource()->getX() <= _gcell->getXMin()) firsthhook = toHook;
else if (h->getTarget()->getX() >= _gcell->getXMax()) lasthhook = toHook;
- else cdebug_log(145,0) << "Error(AutoContact* GCellTopology::_doHChannel ( ForkStack& forks )): This case should not happen " << endl;
+ else cdebug_log(145,0) << "Error(AutoContact* NetBuilder::_doHChannel ( ForkStack& forks )): This case should not happen " << endl;
} else hooks.push_back(toHook);
}
}
@@ -2765,9 +1902,9 @@ namespace {
}
- AutoContact* GCellTopology::_doVChannel ()
+ AutoContact* NetBuilder::_doVChannel ()
{
- cdebug_log(145,1) << "void GCellTopology::_doVChannel ()" << _gcell << endl;
+ cdebug_log(145,1) << "void NetBuilder::_doVChannel ()" << _gcell << endl;
vector hooks;
@@ -2788,7 +1925,7 @@ namespace {
if (v) {
if (v->getSource()->getY() <= _gcell->getYMin()) firstvhook = toHook;
else if (v->getTarget()->getY() >= _gcell->getYMax()) lastvhook = toHook;
- else cdebug_log(145,0) << "Error(AutoContact* GCellTopology::_doVChannel()): This case should not happen " << endl;
+ else cdebug_log(145,0) << "Error(AutoContact* NetBuilder::_doVChannel()): This case should not happen " << endl;
} else hooks.push_back(toHook);
}
}
@@ -2978,9 +2115,9 @@ namespace {
}
- AutoContact* GCellTopology::_doHRail ()
+ AutoContact* NetBuilder::_doHRail ()
{
- cdebug_log(145,1) << "void GCellTopology::_doHRail ()" << _gcell << endl;
+ cdebug_log(145,1) << "void NetBuilder::_doHRail ()" << _gcell << endl;
cdebug_log(145,0) << "FromHook: " << _fromHook << endl;
cdebug_log(145,0) << "North : " << north() << endl;
cdebug_log(145,0) << "East : " << east() << endl;
@@ -2995,7 +2132,7 @@ namespace {
rpNE = rpSW = _routingPads[0];
} else {
cdebug_log(145,0) << "Case _routingPads.size() != 1 "<< endl;
- throw Error( "GCellTopology::_doHRail() Unexpected case.\n"
+ throw Error( "NetBuilder::_doHRail() Unexpected case.\n"
" On: %s."
, getString(_gcell).c_str() );
}
@@ -3025,9 +2162,9 @@ namespace {
}
- AutoContact* GCellTopology::_doVRail ()
+ AutoContact* NetBuilder::_doVRail ()
{
- cdebug_log(145,1) << "void GCellTopology::_doVRail ()" << _gcell << endl;
+ cdebug_log(145,1) << "void NetBuilder::_doVRail ()" << _gcell << endl;
cdebug_log(145,0) << "FromHook: " << _fromHook << endl;
cdebug_log(145,0) << "North : " << north() << endl;
cdebug_log(145,0) << "East : " << east() << endl;
@@ -3042,7 +2179,7 @@ namespace {
rpNE = rpSW = _routingPads[0];
} else {
cdebug_log(145,0) << "Case _routingPads.size() != 1 "<< endl;
- throw Error( "GCellTopology::_doVRail() Unexpected case.\n"
+ throw Error( "NetBuilder::_doVRail() Unexpected case.\n"
" On: %s."
, getString(_gcell).c_str() );
}
@@ -3072,7 +2209,7 @@ namespace {
}
- unsigned int GCellTopology::getNumberGlobals ()
+ unsigned int NetBuilder::getNumberGlobals ()
{
unsigned int i = 0;
if (north()) i++;
@@ -3083,7 +2220,7 @@ namespace {
}
- unsigned int GCellTopology::getDeviceNeighbourBound()
+ unsigned int NetBuilder::getDeviceNeighbourBound()
{
unsigned int bound = 0;
if (north()){
@@ -3099,9 +2236,9 @@ namespace {
}
- AutoContact* GCellTopology::_doStrut ()
+ AutoContact* NetBuilder::_doStrut ()
{
- cdebug_log(145,1) << "void GCellTopology::_doStrut ()" << _gcell << endl;
+ cdebug_log(145,1) << "void NetBuilder::_doStrut ()" << _gcell << endl;
AutoContact* targetContact = NULL; // Contact for fromHook segment
cdebug_log(145,0) << "FromHook: " << _fromHook << endl;
@@ -3501,73 +2638,23 @@ namespace {
}
- void GCellTopology::_doIoPad ()
+ void NetBuilder::_doIoPad ()
{
- throw Error( "GCellTopology::_doIoPad() Unimplemented, blame goes to J.-P. Chaput." );
+ throw Error( "NetBuilder::_doIoPad() Unimplemented, blame goes to J.-P. Chaput." );
}
-} // Anonymous namespace.
-
-
-
-
-namespace Anabatic {
-
- using Hurricane::Name;
- using Hurricane::DebugSession;
- using Hurricane::Error;
- using Hurricane::Warning;
- using Hurricane::Bug;
- using CRL::addMeasure;
- using CRL::getMeasure;
-
-
- void AnabaticEngine::_loadGrByNet ()
- {
- cmess1 << " o Building detailed routing from global." << endl;
- //cmess1 << Dots::asDouble(" - Saturation",getMeasure(getCell(),"Sat.")->getData()) << endl;
-
- startMeasures();
- openSession();
-
- for ( Net* net : getCell()->getNets() ) {
- if (NetRoutingExtension::isAutomaticGlobalRoute(net)) {
- DebugSession::open( net, 144, 160 );
- AutoSegment::setAnalogMode( NetRoutingExtension::isAnalog(net) );
- _loadNetGlobalRouting( net );
- Session::revalidate();
- DebugSession::close();
- }
- }
- AutoSegment::setAnalogMode( false );
-
-#if defined(CHECK_DATABASE)
- _check ( "after Anabatic loading" );
-#endif
-
- Session::close();
-
- stopMeasures();
- printMeasures( "load" );
-
- addMeasure( getCell(), "Globals", AutoSegment::getGlobalsCount() );
- addMeasure( getCell(), "Edges" , AutoSegment::getAllocateds() );
- }
-
-
- void AnabaticEngine::_loadNetGlobalRouting ( Net* net )
+ void NetBuilder::_load ( AnabaticEngine* anabatic, Net* net )
{
//DebugSession::open( 145, 150 );
- cdebug_log(149,0) << "Anabatic::_loadNetGlobalRouting( " << net << " )" << endl;
+ cdebug_log(149,0) << "NetBuilder::load( " << net << " )" << endl;
cdebug_tabw(145,1);
- ForkStack forks;
Hook* sourceHook = NULL;
AutoContact* sourceContact = NULL;
- lookupClear();
+ clearRpLookup();
RoutingPads routingPads = net->getRoutingPads();
size_t degree = routingPads.getSize();
@@ -3579,11 +2666,6 @@ namespace Anabatic {
return;
}
if (degree < 2) {
-#if 0
- if (not getDemoMode())
- cmess2 << Warning("Net \"%s\" have less than 2 plugs/pins (ignored)."
- ,getString(net->getName()).c_str()) << endl;
-#endif
cdebug_tabw(145,-1);
return;
}
@@ -3594,28 +2676,28 @@ namespace Anabatic {
size_t unconnecteds = 0;
size_t connecteds = 0;
- GCellTopology::init( degree );
+ init( degree );
cdebug_log(145,0) << "Start RoutingPad Ring" << endl;
- forEach ( RoutingPad*, startRp, routingPads ) {
+ for ( RoutingPad* startRp : routingPads ) {
bool segmentFound = false;
cdebug_log(145,0) << "startRp : " << startRp << endl;
cdebug_log(145,0) << "startHook: " << startHook << endl;
- forEach ( Hook*, ihook, startRp->getBodyHook()->getHooks() ) {
- cdebug_log(145,0) << "Component " << ihook->getComponent() << endl;
- Segment* segment = dynamic_cast( ihook->getComponent() );
+ for ( Hook* hook : startRp->getBodyHook()->getHooks() ) {
+ cdebug_log(145,0) << "Component " << hook->getComponent() << endl;
+ Segment* segment = dynamic_cast( hook->getComponent() );
if (segment) {
++connecteds;
segmentFound = true;
- GCellTopology gcellConf ( this, forks, *ihook, NULL );
- if (gcellConf.getStateG() == 1) {
- if ( (lowestGCell == NULL) or (*gcellConf.getGCell() < *lowestGCell) ) {
- cdebug_log(145,0) << "Potential starting GCell " << gcellConf.getGCell() << endl;
- lowestGCell = gcellConf.getGCell();
- startHook = *ihook;
+ startFrom( anabatic, hook, NULL );
+ if (getStateG() == 1) {
+ if ( (lowestGCell == NULL) or (*getGCell() < *lowestGCell) ) {
+ cdebug_log(145,0) << "Potential starting GCell " << getGCell() << endl;
+ lowestGCell = getGCell();
+ startHook = hook;
}
break;
}
@@ -3638,32 +2720,32 @@ namespace Anabatic {
}
cdebug_tabw(145,-1);
- if (startHook == NULL) { singleGCell( this, net ); cdebug_tabw(145,-1); return; }
+ if (startHook == NULL) { startFrom(anabatic,NULL,NULL).singleGCell(anabatic,net); cdebug_tabw(145,-1); return; }
- GCellTopology startGCellConf ( this, forks, startHook, NULL );
+ startFrom( anabatic, startHook, NULL );
cdebug_log(145,0) << endl;
cdebug_log(145,0) << "--------~~~~=={o}==~~~~--------" << endl;
cdebug_log(145,0) << endl;
- cdebug_log(145,0) << "Start building from:" << startGCellConf.getGCell() << endl;
- startGCellConf.construct();
+ cdebug_log(145,0) << "Start building from:" << getGCell() << endl;
+ construct();
- sourceHook = forks.getFrom ();
- sourceContact = forks.getContact();
- forks.pop();
+ sourceHook = _forks.getFrom ();
+ sourceContact = _forks.getContact();
+ _forks.pop();
while ( sourceHook ) {
- GCellTopology gcellConf ( this, forks, sourceHook, sourceContact );
- gcellConf.construct();
+ startFrom( anabatic, sourceHook, sourceContact );
+ construct();
- sourceHook = forks.getFrom();
- sourceContact = forks.getContact();
- forks.pop();
+ sourceHook = _forks.getFrom();
+ sourceContact = _forks.getContact();
+ _forks.pop();
cdebug_log(145,0) << "Popping (from) " << sourceHook << endl;
cdebug_log(145,0) << "Popping (to) " << sourceContact << endl;
}
- lookupClear();
+ clearRpLookup();
Session::revalidate();
//Breakpoint::stop( 0, "After construct" );
@@ -3675,7 +2757,7 @@ namespace Anabatic {
#endif
Session::revalidate();
- GCellTopology::fixSegments();
+ fixSegments();
cdebug_tabw(145,-1);
//DebugSession::close();
diff --git a/anabatic/src/NetBuilderHV.cpp b/anabatic/src/NetBuilderHV.cpp
new file mode 100644
index 00000000..5e76d1c9
--- /dev/null
+++ b/anabatic/src/NetBuilderHV.cpp
@@ -0,0 +1,244 @@
+// -*- 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 : "./LoadGlobalRouting.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;
+
+
+ NetBuilderHV::NetBuilderHV ()
+ : NetBuilder()
+ { }
+
+
+ NetBuilderHV::~NetBuilderHV () { }
+
+
+ void NetBuilderHV::doRp_AutoContacts ( GCell* gcell
+ , Component* rp
+ , AutoContact*& source
+ , AutoContact*& target
+ , uint64_t flags
+ )
+ {
+ cdebug_log(145,1) << "NetBuilderHV::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::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) << "NetBuilderHV::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;
+ }
+
+
+ void NetBuilderHV::_do_1G_1M1 ()
+ {
+ cdebug_log(145,1) << "NetBuilderHV::_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);
+ }
+
+
+ void NetBuilderHV::_do_1G_xM1 ()
+ {
+ cdebug_log(145,1) << "NetBuilderHV::_do_1G_" << (int)getConnexity().fields.M1 << "M1() [Managed Configuration]" << endl;
+
+ sort( getRoutingPads().begin(), getRoutingPads().end(), SortRpByX(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);
+ }
+
+
+} // Anabatic namespace.
diff --git a/anabatic/src/anabatic/AnabaticEngine.h b/anabatic/src/anabatic/AnabaticEngine.h
index 682343ab..304d8290 100644
--- a/anabatic/src/anabatic/AnabaticEngine.h
+++ b/anabatic/src/anabatic/AnabaticEngine.h
@@ -256,7 +256,6 @@ namespace Anabatic {
AutoContact* _lookup ( Contact* ) const;
AutoSegment* _lookup ( Segment* ) const;
void _loadGrByNet ();
- void _loadNetGlobalRouting ( Net* );
void _computeNetOptimals ( Net* );
void _computeNetTerminals ( Net* );
void _alignate ( Net* );
diff --git a/anabatic/src/anabatic/NetBuilder.h b/anabatic/src/anabatic/NetBuilder.h
new file mode 100644
index 00000000..b3ba3de7
--- /dev/null
+++ b/anabatic/src/anabatic/NetBuilder.h
@@ -0,0 +1,441 @@
+// -*- 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++ Header : "./anabatic/NetBuilder.h" |
+// +-----------------------------------------------------------------+
+
+#ifndef ANABATIC_NET_BUILDER_H
+#define ANABATIC_NET_BUILDER_H
+
+#include
+#include