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: +//! +//! +//! \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 + +namespace Hurricane { + class Hook; + class Net; + class RoutingPad; + class Component; +} + + +namespace Anabatic { + + using std::vector; + using std::map; + using std::endl; + using Hurricane::Hook; + using Hurricane::Net; + using Hurricane::RoutingPad; + using Hurricane::Component; + class GCell; + class AutoContact; + class AutoSegment; + class AnabaticEngine; + + +// ------------------------------------------------------------------- +// 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 : "NetBuilder". + + class NetBuilder { + public: + enum FunctionFlags { 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 + }; + + // Connexity Union Type. + enum ConnexityBits { GlobalBSize = 8 + , Metal1BSize = 4 + , Metal2BSize = 4 + , Metal3BSize = 4 + , PadsBSize = 4 + , PinsBSize = 4 + }; + 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; + }; + public: + template< typename BuilderT > + static void load ( AnabaticEngine*, Net* ); + static void init ( unsigned int degree ); + static void fixSegments (); + static void getPositions ( Component* anchor, Point& source, Point& target ); + static uint64_t checkRoutingPadSize ( Component* anchor ); + static Hook* getSegmentOppositeHook ( Hook* hook ); + static uint64_t getSegmentHookType ( Hook* hook ); + public: + NetBuilder (); + virtual ~NetBuilder (); + void clear (); + NetBuilder& startFrom ( AnabaticEngine* + , Hook* fromHook + , AutoContact* sourceContact=NULL ); + void construct (); + inline unsigned int getStateG () const; + inline UConnexity getConnexity () const; + inline Net* getNet () const; + inline GCell* getGCell () const; + inline ForkStack& getForks (); + inline vector& getRoutingPads (); + static map& getRpLookup (); + inline unsigned int getTopology () 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 void setBothCornerContacts ( AutoContact* ); + static void clearRpLookup (); + bool push ( Hook* to, AutoContact* contact, uint64_t flags=0 ); + virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags ) = 0; + virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags ) = 0; + virtual AutoContact* doRp_AccessPad ( RoutingPad*, uint64_t flags ); + virtual AutoContact* doRp_AccessAnalog ( GCell*, RoutingPad*, uint64_t flags ); + AutoContact* doRp_2m_Access ( GCell*, RoutingPad*, uint64_t flags ); + void doRp_StairCaseH ( GCell*, Component* rp1, Component* rp2 ); + void doRp_StairCaseV ( GCell*, Component* rp1, Component* rp2 ); + void singleGCell ( AnabaticEngine*, Net* ); + void _load ( AnabaticEngine*, Net* ); + private: + void _do_2m_1G_1M1 (); + void _do_2m_2G_1M1 (); + void _do_2m_xG (); + void _do_xG (); + void _do_2G (); + virtual void _do_xG_1Pad (); + virtual void _do_1G_1PinM2 (); + virtual void _do_1G_1M1 () = 0; + virtual void _do_1G_xM1 () = 0; + virtual void _do_xG_xM1_xM3 (); + virtual void _do_xG_1M1_1M2 (); + virtual void _do_4G_1M2 (); + virtual void _do_xG_xM2 (); + virtual void _do_1G_1M3 (); + virtual 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: + +#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 ) + }; + +#undef CONNEXITY_VALUE + + 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 map _routingPadAutoSegments; + 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; + + // Sort classes. + public: + class SortHookByX { + public: + inline SortHookByX ( uint64_t flags ); + inline bool operator() ( Hook* h1, Hook* h2 ); + protected: + uint64_t _flags; + }; + + class SortHookByY { + public: + inline SortHookByY ( uint64_t flags ); + inline bool operator() ( Hook* h1, Hook* h2 ); + protected: + uint64_t _flags; + }; + + class SortRpByX { + public: + inline SortRpByX ( uint64_t flags ); + inline bool operator() ( Component* rp1, Component* rp2 ); + private: + uint64_t _flags; + }; + + class SortRpByY { + public: + inline SortRpByY ( uint64_t flags ); + inline bool operator() ( Component* rp1, Component* rp2 ); + protected: + uint64_t _flags; + }; + }; + + + inline NetBuilder::UConnexity NetBuilder::getConnexity () const { return _connexity; } + inline ForkStack& NetBuilder::getForks () { return _forks; } + inline unsigned int NetBuilder::getStateG () const { return _connexity.fields.globals; } + inline GCell* NetBuilder::getGCell () const { return _gcell; } + inline Net* NetBuilder::getNet () const { return _net; } + inline unsigned int NetBuilder::getTopology () const { return _topology; } + inline vector& NetBuilder::getRoutingPads () { return _routingPads; } + inline Hook* NetBuilder::north ( size_t i ) const { return (i<_norths.size()) ? _norths[i] : NULL; } + inline Hook* NetBuilder::south ( size_t i ) const { return (i<_souths.size()) ? _souths[i] : NULL; } + inline Hook* NetBuilder::east ( size_t i ) const { return (i<_easts .size()) ? _easts [i] : NULL; } + inline Hook* NetBuilder::west ( size_t i ) const { return (i<_wests .size()) ? _wests [i] : NULL; } + inline void NetBuilder::setBothCornerContacts ( AutoContact* ac ) { _southWestContact = _northEastContact = ac; } + + template< typename BuilderT > + void NetBuilder::load ( AnabaticEngine* engine, Net* net ) { BuilderT()._load(engine,net); } + + +// ------------------------------------------------------------------- +// Class : "NetBuilder::SortRpByX". + + inline NetBuilder::SortRpByX::SortRpByX ( uint64_t flags ) + : _flags(flags) + { } + + + inline bool NetBuilder::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 & NetBuilder::SortDecreasing) xor (x1 < x2); + } + + +// ------------------------------------------------------------------- +// Class : "NetBuilder::SortRpByY". + + inline NetBuilder::SortRpByY::SortRpByY ( uint64_t flags ) + : _flags(flags) + { } + + + inline bool NetBuilder::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 & NetBuilder::SortDecreasing) xor (y1 < y2); + } + + +// ------------------------------------------------------------------- +// Class : "NetBuilder::SortHookByX". + + inline NetBuilder::SortHookByX::SortHookByX ( uint64_t flags ) + : _flags(flags) + { } + + + inline bool NetBuilder::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 = std::min( hh1->getSource()->getX(), hh1->getTarget()->getX() ); + else if (vv1) x1 = vv1->getX(); + else x1 = h1->getComponent()->getCenter().getX(); + + if (hh2) x2 = std::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 & NetBuilder::SortDecreasing) xor (x1 < x2); + } + + +// ------------------------------------------------------------------- +// Class : "NetBuilder::SortHookByY". + + inline NetBuilder::SortHookByY::SortHookByY ( uint64_t flags ) + : _flags(flags) + { } + + + inline bool NetBuilder::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 = std::min( vv1->getSource()->getY(), vv1->getTarget()->getY() ); + else if (hh1) y1 = hh1->getY(); + else y1 = h1->getComponent()->getCenter().getX(); + + if (vv2) y2 = std::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 & NetBuilder::SortDecreasing) xor (y1 < y2); + } + +} + +#endif // ANABATIC_NET_BUILDER_H diff --git a/anabatic/src/anabatic/NetBuilderHV.h b/anabatic/src/anabatic/NetBuilderHV.h new file mode 100644 index 00000000..f7c906ca --- /dev/null +++ b/anabatic/src/anabatic/NetBuilderHV.h @@ -0,0 +1,42 @@ +// -*- 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/NetBuilderHV.h" | +// +-----------------------------------------------------------------+ + +#ifndef ANABATIC_NET_BUILDER_HV_H +#define ANABATIC_NET_BUILDER_HV_H + +#include "anabatic/NetBuilder.h" + + +namespace Anabatic { + + +// ----------------------------------------------------------------- +// Class : "NetBuilderHV". + + class NetBuilderHV : public NetBuilder { + public: + NetBuilderHV (); + virtual ~NetBuilderHV (); + virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags ); + virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags ); + private: + virtual void _do_1G_1M1 (); + virtual void _do_1G_xM1 (); + }; + + +} // Anabatic namespace. + +#endif // ANABATIC_NET_BUILDER_HV_H diff --git a/hurricane/src/hurricane/hurricane/Net.h b/hurricane/src/hurricane/hurricane/Net.h index 66da21cb..b7d247cd 100644 --- a/hurricane/src/hurricane/hurricane/Net.h +++ b/hurricane/src/hurricane/hurricane/Net.h @@ -260,6 +260,10 @@ class Net : public Entity { public: void _setNextOfCellNetMap(Net* net) {_nextOfCellNetMap = net;}; + public: struct CompareByName { + inline bool operator() ( const Net* lhs, const Net* rhs ) const { return lhs->getName() < rhs->getName(); } + }; + };