From 4c57b0651aa36e3ccb35d423837dd68fddb8346d Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sun, 17 Dec 2017 00:13:19 +0100 Subject: [PATCH] Modularize the global to detail routing converter. * New: In Anabatic, rename GCellTopology to NetBuilder, expose the class (no longer in a local namespace). NetBuilder become a base class performing the walkthrough the Net tree. Derived class are tasked to build routing for specific gauge. NetBuilderHV is created to manage all gauge with metal2 horizontal and metal3 vertical. In our terminolgy we consider that the first routing metal is metal2. Metal1 is used inside the standard cells. --- anabatic/doc/NetBuilder.dox | 346 +++++ anabatic/src/AnabaticEngine.cpp | 36 + anabatic/src/CMakeLists.txt | 8 +- .../{LoadGlobalRouting.cpp => NetBuilder.cpp} | 1296 +++-------------- anabatic/src/NetBuilderHV.cpp | 244 ++++ anabatic/src/anabatic/AnabaticEngine.h | 1 - anabatic/src/anabatic/NetBuilder.h | 441 ++++++ anabatic/src/anabatic/NetBuilderHV.h | 42 + hurricane/src/hurricane/hurricane/Net.h | 4 + 9 files changed, 1307 insertions(+), 1111 deletions(-) create mode 100644 anabatic/doc/NetBuilder.dox rename anabatic/src/{LoadGlobalRouting.cpp => NetBuilder.cpp} (67%) create mode 100644 anabatic/src/NetBuilderHV.cpp create mode 100644 anabatic/src/anabatic/NetBuilder.h create mode 100644 anabatic/src/anabatic/NetBuilderHV.h 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(); } + }; + };