From ed557d9027c31acf6ff3e7615fc1c4226aaa2811 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sun, 16 Aug 2015 23:29:28 +0200 Subject: [PATCH] Added support for "same layer" dogleg. Big fix for pad routing. * Change: In Knik, in Vertex, add a "blocked" flag to signal disabled vertexes in the grid (must not be used by the global router). Modificate the Graph::getVertex() method so that when a vertex is geometrically queried, if is a blocked one, return a non-blocked neighbor. This mechanism is introduced to, at last, prevent the global router to go *under* the pad in case of a commplete chip. * New: In Katabatic, in AutoSegment, a new state has been added: "reduced". A reduced segment is in the same layer as it's perpandiculars. To be reduced, a segments has to be connected on source & target to AutoContactTurn, both of the perpandiculars must be of the same layer (below or above) and it's length must not exceed one pitch in the perpandicular direction. To reduce an AutoSegment, call ::reduce() and to revert the state, call ::raise(). Two associated predicates are associated: ::canReduce() and ::mustRaise(). Note: No two adjacent segments can be reduced at the same time. * Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad() to connect to the pads. Create wiring, fixed and non managed by Katabatic, to connect the pad connector layer to the lowest routing layers (depth 1 & 2). The former implementation was sometimes leading to gaps (sheared contact) that *must not* occurs during the building stage. Remark: This bug did put under the light the fact that the initial wiring must be created without gaps. Gaps are closed by making doglegs on contacts. But this mechanism could only work when the database if fully initialised (the cache is up to date). Otherwise various problems arise, in the canonization process for example. * New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(), when anchored on a RoutingPad, now take account the potential rotation of the Path's transformation. Here again, for the chip's pads. * New: In Kite, support for reduced AutoSegment. TrackSegment associateds to reduced AutoSegment are *not* inserted into track to become effectively invisibles. When a segment becomes reduced, a TrackEvent is generated to remove it. Conversely when it is raised a RoutingEvent is created/rescheduled to insert it. All this is mostly managed inside the Session::revalidate() method. * New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip, mark all global routing vertexes (Knik) that are under a pad, as blockeds. * Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and Y coordinate of the chip size. Did not show until a non-square chip was routed (i.e. our MIPS R3000). * Change: In Stratus1, in st_placement.py add the ClockBuffer class for backward compatibility with the MIPS32 bench. Have to review this functionnality coming from the deprecated placeAndroute.py. In st_instance.py, no longer creates the Plug ring of a Net. In my opinion it just clutter the display until the P&R is called. Can re-enable later as an option (in Unicorn). * Change: In Unicorn, in cgt.py, more reliable way of loading then running user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py . --- crlcore/etc/common/display.conf | 16 +- crlcore/src/ccore/RoutingGauge.cpp | 13 +- crlcore/src/ccore/crlcore/RoutingGauge.h | 2 + crlcore/src/ccore/crlcore/Utilities.h | 2 + crlcore/src/ccore/toolbox/ToolBox.cpp | 27 +- cumulus/src/plugins/ChipPlugin.py | 4 +- cumulus/src/plugins/chip/PadsCorona.py | 16 +- katabatic/doc/AutoContact.dox | 11 +- katabatic/doc/AutoSegment.dox | 85 +++++- katabatic/doc/images/reduce-1.fig | 108 ++++++++ katabatic/doc/images/reduce-1.pdf | Bin 0 -> 8496 bytes katabatic/doc/images/reduce-1.png | Bin 0 -> 8696 bytes katabatic/src/AutoContact.cpp | 4 + katabatic/src/AutoContactHTee.cpp | 25 +- katabatic/src/AutoContactTerminal.cpp | 67 ++++- katabatic/src/AutoContactTurn.cpp | 8 + katabatic/src/AutoContactVTee.cpp | 4 + katabatic/src/AutoHorizontal.cpp | 3 +- katabatic/src/AutoSegment.cpp | 164 +++++++++-- katabatic/src/KatabaticEngine.cpp | 7 +- katabatic/src/LoadGrByNet.cpp | 258 ++++++++++++++++-- katabatic/src/katabatic/AutoContact.h | 19 +- katabatic/src/katabatic/AutoContactHTee.h | 1 + katabatic/src/katabatic/AutoContactTerminal.h | 1 + katabatic/src/katabatic/AutoContactTurn.h | 1 + katabatic/src/katabatic/AutoContactVTee.h | 1 + katabatic/src/katabatic/AutoSegment.h | 84 +++--- katabatic/src/katabatic/Session.h | 22 +- kite/doc/Session.dox | 10 +- kite/doc/TrackSegment.dox | 8 +- kite/doc/notes.dox | 8 + kite/src/BuildPowerRails.cpp | 4 +- kite/src/KiteEngine.cpp | 27 +- kite/src/NegociateWindow.cpp | 1 + kite/src/ProtectRoutingPads.cpp | 7 +- kite/src/RoutingEvent.cpp | 3 +- kite/src/SegmentFsm.cpp | 63 +++-- kite/src/Session.cpp | 65 +++-- kite/src/TrackCost.cpp | 29 +- kite/src/TrackElement.cpp | 2 +- kite/src/TrackFixedSegment.cpp | 14 +- kite/src/TrackSegment.cpp | 2 +- kite/src/kite/RoutingEvent.h | 8 +- kite/src/kite/Session.h | 1 + kite/src/kite/TrackCost.h | 13 +- kite/src/kite/TrackElement.h | 2 +- kite/src/kite/TrackSegment.h | 2 +- knik/src/Graph.cpp | 6 +- knik/src/MatrixVertex.cpp | 18 +- knik/src/knik/Vertex.h | 110 ++++---- stratus1/src/stratus/st_instance.py | 2 +- stratus1/src/stratus/st_placement.py | 66 ++++- stratus1/src/stratus/stratus.py | 2 +- unicorn/src/cgt.py | 35 ++- .../utilities/src/vlsisapd/utilities/Dots.h | 2 +- 55 files changed, 1131 insertions(+), 332 deletions(-) create mode 100644 katabatic/doc/images/reduce-1.fig create mode 100644 katabatic/doc/images/reduce-1.pdf create mode 100644 katabatic/doc/images/reduce-1.png diff --git a/crlcore/etc/common/display.conf b/crlcore/etc/common/display.conf index d77430a1..7d04738d 100644 --- a/crlcore/etc/common/display.conf +++ b/crlcore/etc/common/display.conf @@ -172,14 +172,14 @@ stylesTable = \ # Blockages. , (Group , 'Blockages') - , (Drawing, 'blockage1', { 'color':'Blue' , 'pattern':'light_antislash0.8', 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage2', { 'color':'Aqua' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage3', { 'color':'LightPink', 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage4', { 'color':'Green' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage5', { 'color':'Yellow' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage6', { 'color':'Violet' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage7', { 'color':'Red' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage8', { 'color':'Blue' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) + , (Drawing, 'blockage1', { 'color':'Blue' , 'pattern':'light_antislash0.8', 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage2', { 'color':'Aqua' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage3', { 'color':'LightPink', 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage4', { 'color':'Green' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage5', { 'color':'Yellow' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage6', { 'color':'Violet' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage7', { 'color':'Red' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage8', { 'color':'Blue' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) # Knick & Kite. , (Group , 'Knick & Kite') diff --git a/crlcore/src/ccore/RoutingGauge.cpp b/crlcore/src/ccore/RoutingGauge.cpp index 2fcfb504..3e503b48 100644 --- a/crlcore/src/ccore/RoutingGauge.cpp +++ b/crlcore/src/ccore/RoutingGauge.cpp @@ -1,20 +1,20 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2015, All Rights Reserved +// Copyright (c) UPMC 2008-2015, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | Alliance / Hurricane Interface | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./RoutingGauge.cpp" | // +-----------------------------------------------------------------+ -#include +#include #include #include #include "hurricane/Commons.h" @@ -49,6 +49,9 @@ namespace CRL { // Class : "RoutingGauge". + const size_t RoutingGauge::nlayerdepth = std::numeric_limits::max(); + + RoutingGauge::RoutingGauge ( const char* name ) : _name (name) , _layerGauges() @@ -150,7 +153,7 @@ namespace CRL { if ( _layerGauges[i]->getLayer()->getMask() == bottomLayer->getMask() ) return i; } - return UINT_MAX; + return nlayerdepth; } @@ -160,7 +163,7 @@ namespace CRL { if ( _layerGauges[i]->getLayer()->getMask() == layer->getMask() ) return i; } - return UINT_MAX; + return nlayerdepth; } diff --git a/crlcore/src/ccore/crlcore/RoutingGauge.h b/crlcore/src/ccore/crlcore/RoutingGauge.h index 83ff3138..8c512496 100644 --- a/crlcore/src/ccore/crlcore/RoutingGauge.h +++ b/crlcore/src/ccore/crlcore/RoutingGauge.h @@ -48,6 +48,8 @@ namespace CRL { class RoutingGauge { public: + // Constants. + static const size_t nlayerdepth; // Constructors & Destructors. static RoutingGauge* create ( const char* name ); virtual void destroy (); diff --git a/crlcore/src/ccore/crlcore/Utilities.h b/crlcore/src/ccore/crlcore/Utilities.h index 9dbaf189..1d5fe796 100644 --- a/crlcore/src/ccore/crlcore/Utilities.h +++ b/crlcore/src/ccore/crlcore/Utilities.h @@ -273,6 +273,7 @@ inline std::string tty::bgcolor ( unsigned int mask ) template inline mstream& operator<< ( T* t ); template inline mstream& operator<< ( const T& t ); template inline mstream& operator<< ( const T* t ); + inline mstream& put ( char c ); inline mstream& flush (); // Overload for manipulators. inline mstream &operator<< ( std::ostream &(*pf)(std::ostream &) ); @@ -290,6 +291,7 @@ inline std::string tty::bgcolor ( unsigned int mask ) inline unsigned int mstream::getActiveMask () { return _activeMask; } inline void mstream::setStreamMask ( unsigned int mask ) { _streamMask |= mask; } inline void mstream::unsetStreamMask( unsigned int mask ) { _streamMask &= ~mask; } + inline mstream& mstream::put ( char c ) { if (enabled()) static_cast(this)->put(c); return *this; } inline mstream& mstream::flush () { if (enabled()) static_cast(this)->flush(); return *this; } inline mstream& mstream::operator<< ( std::ostream& (*pf)(std::ostream&) ) { if (enabled()) (*pf)(*this); return *this; } diff --git a/crlcore/src/ccore/toolbox/ToolBox.cpp b/crlcore/src/ccore/toolbox/ToolBox.cpp index d3f94173..47def764 100644 --- a/crlcore/src/ccore/toolbox/ToolBox.cpp +++ b/crlcore/src/ccore/toolbox/ToolBox.cpp @@ -1,30 +1,29 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2012, All Rights Reserved +// Copyright (c) UPMC 2008-2015, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | Alliance / Hurricane Interface | // | | // | Author : The Borg Collective | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./ToolBox.cpp" | // +-----------------------------------------------------------------+ -#include "hurricane/Plug.h" -#include "hurricane/Pin.h" -#include "hurricane/Library.h" -#include "hurricane/Net.h" -#include "hurricane/Cell.h" -#include "hurricane/Instance.h" -#include "hurricane/Segment.h" -#include "hurricane/NetExternalComponents.h" -#include "hurricane/UpdateSession.h" -#include "hurricane/Warning.h" +#include "hurricane/Plug.h" +#include "hurricane/Pin.h" +#include "hurricane/Library.h" +#include "hurricane/Net.h" +#include "hurricane/Cell.h" +#include "hurricane/Instance.h" +#include "hurricane/Segment.h" +#include "hurricane/NetExternalComponents.h" +#include "hurricane/UpdateSession.h" +#include "hurricane/Warning.h" using namespace Hurricane; #include "crlcore/ToolBox.h" @@ -279,6 +278,7 @@ static void AttachPlugOrPin(Net& net) } + void createPartRing(Cell* cell, Name nom) { if (!cell) @@ -295,6 +295,7 @@ void createPartRing(Cell* cell, Name nom) UpdateSession::close(); } + void createPartRing2(Net& net) { UpdateSession::open(); diff --git a/cumulus/src/plugins/ChipPlugin.py b/cumulus/src/plugins/ChipPlugin.py index 7482547e..c61c6f16 100644 --- a/cumulus/src/plugins/ChipPlugin.py +++ b/cumulus/src/plugins/ChipPlugin.py @@ -95,8 +95,8 @@ class PlaceCore ( chip.Configuration.ChipConfWrapper ): coreAb = self.cores[0].getMasterCell().getAbutmentBox() if (not coreAb.isEmpty()): - if coreAb.getWidth () < self.coreSize.getWidth() \ - and coreAb.getHeight() < self.coreSize.getHeight(): + if coreAb.getWidth () <= self.coreSize.getWidth() \ + and coreAb.getHeight() <= self.coreSize.getHeight(): self.coreSize = coreAb else: print ErrorMessage( 1, [ 'Core %s already have an abutment box, bigger than the requested one:' diff --git a/cumulus/src/plugins/chip/PadsCorona.py b/cumulus/src/plugins/chip/PadsCorona.py index 2f61b752..b157dc96 100644 --- a/cumulus/src/plugins/chip/PadsCorona.py +++ b/cumulus/src/plugins/chip/PadsCorona.py @@ -57,10 +57,10 @@ class Side ( object ): def getAxis ( self, i ): - if self._type == chip.North: return self._corona.chipSize.getXMax() - self._corona.padHeight + self._corona._powerRails[i][2] - elif self._type == chip.South: return self._corona.chipSize.getXMin() + self._corona.padHeight - self._corona._powerRails[i][2] - elif self._type == chip.East: return self._corona.chipSize.getYMax() - self._corona.padHeight + self._corona._powerRails[i][2] - elif self._type == chip.West: return self._corona.chipSize.getYMin() + self._corona.padHeight - self._corona._powerRails[i][2] + if self._type == chip.North: return self._corona.chipSize.getYMax() - self._corona.padHeight + self._corona._powerRails[i][2] + elif self._type == chip.South: return self._corona.chipSize.getYMin() + self._corona.padHeight - self._corona._powerRails[i][2] + elif self._type == chip.East: return self._corona.chipSize.getXMax() - self._corona.padHeight + self._corona._powerRails[i][2] + elif self._type == chip.West: return self._corona.chipSize.getXMin() + self._corona.padHeight - self._corona._powerRails[i][2] else: raise ErrorMessage( 1, 'PadsCorona.Side.__init__(): Invalid value for sideType (%d)' % sideType ) return 0 @@ -224,14 +224,14 @@ class Side ( object ): def _routePads ( self ): for i in range(len(self._corona._powerRails)): if self._type == chip.South: - Horizontal.create( self._corona._corners[chip.SouthWest ][i] + Horizontal.create( self._corona._corners[chip.SouthWest][i] , self._corona._corners[chip.SouthEast][i] , self._corona._powerRails[i][1] , self.getAxis( i ) , self._corona._powerRails[i][3] ) elif self._type == chip.North: - Horizontal.create( self._corona._corners[chip.NorthWest ][i] + Horizontal.create( self._corona._corners[chip.NorthWest][i] , self._corona._corners[chip.NorthEast][i] , self._corona._powerRails[i][1] , self.getAxis( i ) @@ -239,14 +239,14 @@ class Side ( object ): ) elif self._type == chip.East: Vertical.create( self._corona._corners[chip.SouthEast][i] - , self._corona._corners[chip.NorthEast ][i] + , self._corona._corners[chip.NorthEast][i] , self._corona._powerRails[i][1] , self.getAxis( i ) , self._corona._powerRails[i][3] ) elif self._type == chip.West: Vertical.create( self._corona._corners[chip.SouthWest][i] - , self._corona._corners[chip.NorthWest ][i] + , self._corona._corners[chip.NorthWest][i] , self._corona._powerRails[i][1] , self.getAxis( i ) , self._corona._powerRails[i][3] diff --git a/katabatic/doc/AutoContact.dox b/katabatic/doc/AutoContact.dox index 142ab2af..4d4b623d 100644 --- a/katabatic/doc/AutoContact.dox +++ b/katabatic/doc/AutoContact.dox @@ -236,11 +236,16 @@ //! \function GCell* AutoContact::getGCell () const; //! \sreturn The GCell into which the AutoContact is located. - //! \function AutoSegment* AutoContact::getOpposite ( const AutoSegment* segment ) const; - //! \sreturn The AutoSegment other the same direction as \c segment, this is - //! only meaningful on AutoContactHTee or AutoContactVTee. It there is + //! \function AutoSegment* AutoContact::getOpposite ( const AutoSegment* reference ) const; + //! \sreturn The other AutoSegment the \e same direction as \c reference, this is + //! only meaningful on AutoContactHTee or AutoContactVTee. If there is //! no opposite, \c NULL is returned. + //! \function AutoSegment* AutoContact::getPerpandicular ( const AutoSegment* reference ) const; + //! \sreturn The AutoSegment in the \e perpandicular direction to \c reference, this is + //! only meaningful on AutoContacTurn. It there is no unique perpandicular, + //! \c NULL is returned. + //! \function AutoSegment* AutoContact::getSegment ( unsigned int index ) const; //! \sreturn The nth anchored AutoSegment. The index is significant: //! - \b 0 : first horizontal (\b h1). diff --git a/katabatic/doc/AutoSegment.dox b/katabatic/doc/AutoSegment.dox index 3e6daeaa..26d61c44 100644 --- a/katabatic/doc/AutoSegment.dox +++ b/katabatic/doc/AutoSegment.dox @@ -68,6 +68,9 @@ * This operation is used to slacken the constraints on a segment * or restore connexity on source/target contact after a layer * change. The new segment is always created on the source. + *
  • Reduction/Raising. When a segment is a short dogleg, + * no greater than one picth, it can use the layer of the + * perpandiculars. * * * @@ -97,6 +100,8 @@ *
  • The interval giving the complete length of the AutoSegment, * that is, with all extentions cap taken into account. * This interval is refered as the \e span. + *
  • A small counter, of the number of reduced neighbors (never + * exceed two). * * * @@ -197,6 +202,10 @@ //! \var AutoSegmentFlag::SegTargetBottom //! The target contact of this segment is connected to the bottom layer. + //! \var AutoSegmentFlag::SegIsReduced + //! This segment is the perpandicular part of a dogleg which will use the + //! same layer as the parallels. + //! \var AutoSegmentFlag::SegLayerChange //! This AutoSegment has been created to to reconnect parts of an AutoSegment //! after a layer change. @@ -273,10 +282,11 @@ //! \c source or \c target are not the one decorating the anchors, an //! exception is thrown. - //! \function AutoSegment* AutoSegment::create ( AutoContact* source, AutoContact* target, unsigned int flags ); + //! \function AutoSegment* AutoSegment::create ( AutoContact* source, AutoContact* target, unsigned int dir, size_t depth ); //! \param source The source AutoContact. //! \param target The target AutoContact. - //! \param flags Specify the constructor behavior. + //! \param dir Specify the segment direction. + //! \param depth The layer, given by it's depth in the RoutingGauge. //! \return The AutoHorizontal/AutoVertical. //! //! Factory method to create AutoHorizontal or AutoVertical. @@ -391,6 +401,22 @@ //! \sreturn \true if segment is a strap used only to connect between two different //! metal layers on the way up or down. + //! \function bool AutoSegment::isSpinTop() const; + //! \sreturn \true if segment is connected to turns and both perpandiculars segments + //! are in the \e top layer (candidate for reduction). + + //! \function bool AutoSegment::isSpinBottom() const; + //! \sreturn \true if segment is connected to turns and both perpandiculars segments + //! are in the \e bottom layer (candidate for reduction). + + //! \function bool AutoSegment::isSpinTopOrBottom() const; + //! \sreturn \true if segment is either spin top or spin bottom + //! (candidate for reduction). + + //! \function bool AutoSegment::isReduced() const; + //! \sreturn \true if segment is actually in a reduced state: it's effective layer + //! will be the one of it's perpandiculars. + //! \function bool AutoSegment::isStrap() const; //! \sreturn \true if segment has been created from a slackening operation to //! restore the slack of another segment. @@ -427,6 +453,20 @@ // \function bool AutoSegment::canDesalignate( AutoContact* contact ) const; // \sreturn \true if \c contact restrict the slack of the segment. + //! \function bool AutoSegment::canReduce() const; + //! \sreturn \true if the segment can be reduced. That is: + //! - Source & target are AutoContactTurn. + //! - It is either spin top or spin bottom, that is + //! connecting perpandiculars both in the same layer. + //! - Has a length less or equal one pitch in the perpandicular direction. + //! - Neither of the perpandicular are also reduceds. + + //! \function bool AutoSegment::mustRaise() const; + //! \sreturn \true if the segment must \e be reduced. That is: + //! - It is in reduced state... + //! - It is no longer spin top or spin bottom. + //! - It's length exceed one pitch in the perpandicular direction. + //! \function bool AutoSegment::canSlacken( unsigned int flags=0 ) const; //! \sreturn \true if the segment can be slackened. That is, source or target constraints //! are less than three pitches. @@ -806,6 +846,40 @@ //! Perform operations that must be done before the actual destructor is //! called. Merely whidrawn the AutoSegment from the lookup/Session mechanism. + //! \function bool AutoSegment::reduce (); + //! Sets the segment into reduced state. + //! + //! \sreturn \true if the operation did succeed. The layer will not be actually changed + //! until the Katabatic database is saved/destroyed. + //! + //! A segment can be reduced if: + //! - Source & target are AutoContactTurn. + //! - It is either spin top or spin bottom, that is + //! connecting perpandiculars both in the same layer. + //! - Has a length less or equal one pitch in the perpandicular direction. + //! - Neither of the perpandicular are also reduceds. + //! + //! \image html reduce-1.png "Reduce Example" + //! + //! If segment \c id:12 is reduced, it prevents \c id:10 & \c id:14 to + //! be also reduced, by increasing the \c _reduced counter. In this + //! example \c id:14 is spin top and \c id:12 is spin bottom. + //! + //! If we reduce two adjacent segments, one will go up while the other + //! will go down (they will actually exchange their layers), it will + //! thus defeat the purpose of creating a same layer dogleg. + //! Besides, the turn contact between them will be changed into a pure + //! metal one, generating a disconnexion... + //! + //! \see AutoSegment::raise() + + //! \function bool AutoSegment::raise (); + //! Get a segment out of \e reduced state. + //! + //! \sreturn \true if a state change did really take place. + //! + //! \see AutoSegment::reduce() + //! \function AutoSegment* AutoSegment::makeDogleg ( AutoContact* from ); //! \param from The AutoContact \e from which we want to make a dogleg. //! @@ -969,4 +1043,11 @@ //! //! \image html _slacken-2.png "slacken() for an Horizontal (special cases)" + //! \function bool AutoSegment::reduceDoglegLayer (); + //! + //! Perform the actual layer change on a reduced segment. This method is to + //! be called juste before destroying the Katabatic database. + //! + //! \sreturn \true if a change occurs. + } diff --git a/katabatic/doc/images/reduce-1.fig b/katabatic/doc/images/reduce-1.fig new file mode 100644 index 00000000..c378c196 --- /dev/null +++ b/katabatic/doc/images/reduce-1.fig @@ -0,0 +1,108 @@ +#FIG 3.2 Produced by xfig version 3.2.5c +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +0 32 #ffffde +6 450 900 750 2250 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1125 675 975 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1200 675 1050 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1275 675 1125 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1350 675 1200 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1425 675 1275 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1500 675 1350 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1575 675 1425 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1650 675 1500 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1725 675 1575 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1800 675 1650 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1875 675 1725 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1950 675 1800 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 2025 675 1875 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 2100 675 1950 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 2175 675 2025 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1050 600 975 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 600 2175 675 2100 +2 2 0 2 1 32 50 -1 -1 6.000 0 0 -1 0 0 5 + 525 975 675 975 675 2175 525 2175 525 975 +-6 +1 2 3 1 4 7 40 -1 -1 4.000 1 0.0000 1800 1800 375 900 1425 1800 2175 1800 +2 2 0 4 0 32 40 -1 -1 10.000 0 0 -1 0 0 5 + 525 1125 675 1125 675 1275 525 1275 525 1125 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 1050 1200 1050 900 1350 900 1350 1200 +2 1 0 2 1 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 675 1200 1800 1200 +2 1 0 4 0 32 40 -1 -1 0.000 0 0 -1 0 0 3 + 1650 1200 1800 1200 1800 1350 +2 1 0 2 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 1800 1200 1800 2400 +2 1 0 4 0 32 40 -1 -1 0.000 0 0 -1 0 0 3 + 1950 2400 1800 2400 1800 2250 +2 1 0 2 1 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 1875 2400 3000 2400 +2 1 0 4 0 32 40 -1 -1 0.000 0 0 -1 0 0 3 + 2850 2400 3000 2400 3000 2550 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 1800 1650 2100 1650 2100 1950 1800 1950 +2 1 0 2 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3000 2400 3000 3600 +2 1 0 2 1 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3000 3600 4125 3600 +2 1 0 4 0 32 40 -1 -1 0.000 0 0 -1 0 0 3 + 3150 3600 3000 3600 3000 3450 +2 1 0 4 0 32 40 -1 -1 0.000 0 0 -1 0 0 3 + 4050 3600 4200 3600 4200 3750 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 3000 2850 3300 2850 3300 3150 3000 3150 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 2250 2400 2250 2100 2550 2100 2550 2400 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 3450 3600 3450 3300 3750 3300 3750 3600 +2 1 0 1 4 7 40 -1 -1 4.000 0 0 -1 0 0 2 + 2025 1050 2400 900 +2 1 1 1 0 7 40 -1 -1 4.000 0 0 -1 0 0 2 + 1875 1200 4200 1200 +2 1 1 1 0 7 40 -1 -1 4.000 0 0 -1 0 0 2 + 3075 2400 4200 2400 +2 1 0 1 0 7 40 -1 -1 4.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 4125 1200 4125 2400 +2 2 0 0 0 32 70 -1 21 2.000 0 0 -1 0 0 5 + 0 600 5700 600 5700 5100 0 5100 0 600 +4 1 0 50 -1 14 12 0.0000 4 120 240 1950 1875 12\001 +4 1 0 50 -1 14 12 0.0000 4 120 240 2400 2325 14\001 +4 1 0 50 -1 14 12 0.0000 4 120 240 3150 3075 16\001 +4 1 0 50 -1 14 12 0.0000 4 120 240 3600 3525 18\001 +4 1 0 50 -1 14 12 0.0000 4 120 240 1200 1125 10\001 +4 1 0 50 -1 14 12 0.0000 4 120 360 1200 1425 r:1\001 +4 1 0 50 -1 14 12 1.5708 4 120 360 1725 1800 r:0\001 +4 1 0 50 -1 14 12 1.5708 4 120 360 2925 3000 r:0\001 +4 1 0 50 -1 14 12 0.0000 4 120 360 3600 3825 r:0\001 +4 1 0 50 -1 14 12 0.0000 4 120 360 2400 2625 r:1\001 +4 1 0 50 -1 14 12 0.0000 4 120 120 2250 1875 R\001 +4 0 4 40 -1 16 12 0.0000 4 195 2280 2475 900 Segment id:12 is reduced.\001 +4 0 0 40 -1 16 12 0.0000 4 195 4950 300 4500 As segment id:12 is reduced, reduced count is increased\001 +4 0 0 40 -1 16 12 0.0000 4 195 5175 300 4800 on segments id:10 and id:14 which then cannot be reduced.\001 +4 1 0 40 -1 16 12 1.5708 4 195 915 4050 1800 1 M2 pitch\001 diff --git a/katabatic/doc/images/reduce-1.pdf b/katabatic/doc/images/reduce-1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..60749cee6b38ab25c556e4bff53554b002c612eb GIT binary patch literal 8496 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 z%Ogt@05getBoundingBox (); } @@ -154,32 +163,60 @@ namespace Katabatic { RoutingPad* routingPad; if ( (horizontal = dynamic_cast(component)) ) { + ltrace(110) << "Anchor: " << horizontal << "@" << horizontal->getSourcePosition() << endl; xMin = horizontal->getSourcePosition().getX(); xMax = horizontal->getTargetPosition().getX(); yMin = yMax = horizontal->getTargetPosition().getY(); } else if ( (vertical = dynamic_cast(component)) ) { + ltrace(110) << "Anchor: " << vertical << "@" << vertical->getSourcePosition() << endl; yMin = vertical->getSourcePosition().getY(); yMax = vertical->getTargetPosition().getY(); xMin = xMax = vertical->getTargetPosition().getX(); } else if ( (routingPad = dynamic_cast(component)) ) { - Entity* entity = routingPad->getOccurrence().getEntity(); + Entity* entity = routingPad->getOccurrence().getEntity(); + Transformation transf = routingPad->getOccurrence().getPath().getTransformation(); + ltrace(110) << "Anchor: " << routingPad << endl; - // Assumes there is no rotation in the Transformation. - if ( dynamic_cast(entity) ) { - xMin = routingPad->getSourcePosition().getX(); - xMax = routingPad->getTargetPosition().getX(); - yMin = yMax - = routingPad->getTargetPosition().getY(); + int rpOrient = 1; + switch ( transf.getOrientation() ) { + case Transformation::Orientation::R1: + case Transformation::Orientation::R3: + case Transformation::Orientation::XR: + case Transformation::Orientation::YR: + rpOrient = 2; + break; + default: + break; + } + + if (dynamic_cast(entity)) { + // rpOrient *is* the rotation. } else if ( dynamic_cast(entity) ) { - yMin = routingPad->getSourcePosition().getY(); - yMax = routingPad->getTargetPosition().getY(); - xMin = xMax - = routingPad->getTargetPosition().getX(); + // rpOrient is the inverse rotation. + rpOrient = (rpOrient == 1) ? 2 : 1; } else { - xMin = xMax = routingPad->getPosition().getX(); - yMin = yMax = routingPad->getPosition().getY(); + rpOrient = 0; + } + + switch ( rpOrient ) { + case 1: + xMin = routingPad->getSourcePosition().getX(); + xMax = routingPad->getTargetPosition().getX(); + yMin = yMax + = routingPad->getTargetPosition().getY(); + break; + case 2: + yMin = routingPad->getSourcePosition().getY(); + yMax = routingPad->getTargetPosition().getY(); + xMin = xMax + = routingPad->getTargetPosition().getX(); + break; + default: + xMin = xMax = routingPad->getPosition().getX(); + yMin = yMax = routingPad->getPosition().getY(); + break; } } else { xMin = xMax = component->getPosition().getX(); @@ -189,6 +226,10 @@ namespace Katabatic { order( xMin, xMax ); order( yMin, yMax ); + ltrace(110) << "| Using (y): " << DbU::getValueString(yMin) << " " + << DbU::getValueString(yMax) << endl; + + ltraceout(110); return Box( xMin, yMin, xMax, yMax ); } diff --git a/katabatic/src/AutoContactTurn.cpp b/katabatic/src/AutoContactTurn.cpp index f38fbe5f..294a00dd 100644 --- a/katabatic/src/AutoContactTurn.cpp +++ b/katabatic/src/AutoContactTurn.cpp @@ -88,6 +88,14 @@ namespace Katabatic { { return NULL; } + AutoSegment* AutoContactTurn::getPerpandicular ( const AutoSegment* reference ) const + { + if (reference == _horizontal1) return _vertical1; + if (reference == _vertical1 ) return _horizontal1; + return NULL; + } + + AutoSegment* AutoContactTurn::getSegment ( unsigned int index ) const { switch ( index ) { diff --git a/katabatic/src/AutoContactVTee.cpp b/katabatic/src/AutoContactVTee.cpp index c355b2e5..59ae782d 100644 --- a/katabatic/src/AutoContactVTee.cpp +++ b/katabatic/src/AutoContactVTee.cpp @@ -91,6 +91,10 @@ namespace Katabatic { } + AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* ) const + { return NULL; } + + AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const { switch ( index ) { diff --git a/katabatic/src/AutoHorizontal.cpp b/katabatic/src/AutoHorizontal.cpp index 8dede65c..fc1e2e5b 100644 --- a/katabatic/src/AutoHorizontal.cpp +++ b/katabatic/src/AutoHorizontal.cpp @@ -689,9 +689,8 @@ namespace Katabatic { unsigned int AutoHorizontal::_makeDogleg ( GCell* doglegGCell, unsigned int flags ) { - ltrace(200) << "AutoHorizontal::_makeDogleg(GCell*)" << endl; - DebugSession::open( getNet(), 80 ); + ltrace(200) << "AutoHorizontal::_makeDogleg(GCell*)" << endl; ltracein(159); //Session::doglegReset(); diff --git a/katabatic/src/AutoSegment.cpp b/katabatic/src/AutoSegment.cpp index 43d03c2c..1f2b95a5 100644 --- a/katabatic/src/AutoSegment.cpp +++ b/katabatic/src/AutoSegment.cpp @@ -313,6 +313,8 @@ namespace Katabatic { , _flags (SegCreated) , _depth (Session::getLayerDepth(segment->getLayer())) , _optimalMin (0) + , _optimalMax (0) + , _reduceds (0) , _sourcePosition (0) , _targetPosition (0) , _userConstraints(false) @@ -465,25 +467,29 @@ namespace Katabatic { unsigned int oldSpinFlags = _flags & SegDepthSpin; if (_flags & (SegInvalidatedSource|SegCreated)) { - const Layer* contactLayer = getAutoSource()->getLayer(); + AutoContact* source = getAutoSource(); + const Layer* contactLayer = source->getLayer(); const Layer* segmentLayer = getLayer(); - ltrace(200) << "Changed source: " << getAutoSource() << endl; + ltrace(200) << "Changed source: " << source << endl; unsetFlags( SegSourceTop|SegSourceBottom ); - if (contactLayer != segmentLayer) { + if (contactLayer != segmentLayer) setFlags( (segmentLayer == contactLayer->getTop()) ? SegSourceBottom : SegSourceTop ); - } + if (source->isTurn() and source->getPerpandicular(this)->isReduced()) + incReduceds(); } if (_flags & (SegInvalidatedTarget|SegCreated)) { - const Layer* contactLayer = getAutoTarget()->getLayer(); + AutoContact* target = getAutoTarget(); + const Layer* contactLayer = target->getLayer(); const Layer* segmentLayer = getLayer(); - ltrace(200) << "Changed target: " << getAutoTarget() << endl; + ltrace(200) << "Changed target: " << target << endl; unsetFlags( SegTargetTop|SegTargetBottom ); - if (contactLayer != segmentLayer) { + if (contactLayer != segmentLayer) setFlags( (segmentLayer == contactLayer->getTop()) ? SegTargetBottom : SegTargetTop ); - } + if (target->isTurn() and target->getPerpandicular(this)->isReduced()) + incReduceds(); } unsigned int observerFlags = Revalidate; @@ -517,21 +523,6 @@ namespace Katabatic { } - bool AutoSegment::isSameLayerDogleg () const - { - if (not isSpinTopOrBottom()) return false; - - unsigned int perpandicularDepth = getDepth() + (isSpinTop() ? 1 : -1); - if (perpandicularDepth >= Session::getDepth()) { - cerr << this << " isSpinTop too high." << endl; - } - perpandicularDepth = Session::getDepth() - 1; - - return (getLength() > (Session::getPitch(perpandicularDepth))) - and (getLength() < (Session::getPitch(perpandicularDepth) * 3)); - } - - DbU::Unit AutoSegment::getPPitch () const { unsigned int depth = getDepth(); @@ -706,6 +697,11 @@ namespace Katabatic { { AutoContact* source = getAutoSource(); if (source) { + if (source->isTurn()) { + AutoSegment* perpandicular = source->getPerpandicular(this); + if (perpandicular and perpandicular->isReduced()) + decReduceds(); + } base()->getSourceHook()->detach(); source->cacheDetach( this ); unsetFlags( SegNotSourceAligned ); @@ -718,6 +714,11 @@ namespace Katabatic { { AutoContact* target = getAutoTarget(); if (target) { + if (target->isTurn()) { + AutoSegment* perpandicular = target->getPerpandicular(this); + if (perpandicular and perpandicular->isReduced()) + decReduceds(); + } base()->getTargetHook()->detach(); target->cacheDetach( this ); unsetFlags( SegNotTargetAligned ); @@ -1149,6 +1150,72 @@ namespace Katabatic { } + bool AutoSegment::canReduce () const + { + AutoContact* source = getAutoSource(); + AutoContact* target = getAutoTarget(); + + if (not source->isTurn() or not target->isTurn()) return false; + if (not isSpinTopOrBottom()) return false; + if (_reduceds) return false; + + unsigned int perpandicularDepth = getDepth(); + if (isSpinBottom()) --perpandicularDepth; + else if (isSpinTop()) { + ++perpandicularDepth; + if (perpandicularDepth >= Session::getDepth()) return false; + } else + return false; + + if (getLength() >= (Session::getPitch(perpandicularDepth) * 2)) return false; + + return true; + } + + + bool AutoSegment::reduce () + { + if (not canReduce()) return false; + + AutoContact* source = getAutoSource(); + AutoContact* target = getAutoTarget(); + + _flags |= SegIsReduced; + source->getPerpandicular( this )->incReduceds(); + target->getPerpandicular( this )->incReduceds(); + + return true; + } + + + bool AutoSegment::mustRaise () const + { + if (not (_flags & SegIsReduced)) return false; + + unsigned int perpandicularDepth = getDepth(); + if (isSpinBottom()) --perpandicularDepth; + else if (isSpinTop ()) ++perpandicularDepth; + else return true; + + return (getLength() >= (Session::getPitch(perpandicularDepth) * 2)); + } + + + bool AutoSegment::raise () + { + if (not (_flags & SegIsReduced)) return false; + + AutoContact* source = getAutoSource(); + AutoContact* target = getAutoTarget(); + + _flags &= ~SegIsReduced; + source->getPerpandicular( this )->decReduceds(); + target->getPerpandicular( this )->decReduceds(); + + return true; + } + + void AutoSegment::changeDepth ( unsigned int depth, unsigned int flags ) { ltrace(200) << "changeDepth() " << depth << " - " << this << endl; @@ -1481,6 +1548,32 @@ namespace Katabatic { } + bool AutoSegment::reduceDoglegLayer () + { + if (not isReduced()) return true; + + AutoContact* source = getAutoSource(); + AutoContact* target = getAutoTarget(); + + unsigned int perpandicularDepth = getDepth(); + if (isSpinBottom()) --perpandicularDepth; + if (isSpinTop ()) ++perpandicularDepth; + + if (perpandicularDepth == getDepth()) { + cerr << Bug( "AutoSegment::reduceDoglegLayer(): Reduced segment spin is neither top (TT) nor bottom (BB).\n" + " %s" + , getString(this).c_str() ) << endl; + return false; + } + + source->setLayer( Session::getRoutingLayer(perpandicularDepth) ); + target->setLayer( Session::getRoutingLayer(perpandicularDepth) ); + setLayer( Session::getRoutingLayer(perpandicularDepth) ); + + return true; + } + + #if THIS_IS_DISABLED @@ -1811,6 +1904,7 @@ namespace Katabatic { state += isWeakTerminal2 () ? "w": "-"; state += isNotAligned () ? "A": "-"; state += isSlackened () ? "S": "-"; + state += isReduced () ? "r": "-"; state += isInvalidated () ? "i": "-"; if (_flags & SegSourceTop) state += 'T'; @@ -1968,12 +2062,28 @@ namespace Katabatic { AutoSegment* AutoSegment::create ( AutoContact* source , AutoContact* target , unsigned int dir + , size_t depth ) { - static const Layer* horizontalLayer = Session::getRoutingLayer( 1 ); - static DbU::Unit horizontalWidth = Session::getWireWidth ( 1 ); - static const Layer* verticalLayer = Session::getRoutingLayer( 2 ); - static DbU::Unit verticalWidth = Session::getWireWidth ( 2 ); + // Hardcoded: make the assumption that, + // depth=0 is terminal reserved | METAL1 + // depth=1 is horizontal | METAL2 + // depth=2 is vertical | METAL3 + // Should be based on gauge informations. + static const Layer* hLayer = Session::getRoutingLayer( 1 ); + static DbU::Unit hWidth = Session::getWireWidth ( 1 ); + static const Layer* vLayer = Session::getRoutingLayer( 2 ); + static DbU::Unit vWidth = Session::getWireWidth ( 2 ); + + const Layer* horizontalLayer = hLayer; + DbU::Unit horizontalWidth = hWidth; + const Layer* verticalLayer = vLayer; + DbU::Unit verticalWidth = vWidth; + + if (depth != RoutingGauge::nlayerdepth) { + horizontalLayer = verticalLayer = Session::getRoutingLayer( depth ); + horizontalWidth = verticalWidth = Session::getWireWidth ( depth ); + } AutoSegment* segment; AutoContact* reference = source; diff --git a/katabatic/src/KatabaticEngine.cpp b/katabatic/src/KatabaticEngine.cpp index 208e5fe6..e67a3de2 100644 --- a/katabatic/src/KatabaticEngine.cpp +++ b/katabatic/src/KatabaticEngine.cpp @@ -255,10 +255,12 @@ namespace Katabatic { ltracein(90); ltrace(90) << "Saving AutoContacts/AutoSegments." << endl; - size_t fixedSegments = 0; + size_t fixedSegments = 0; + size_t sameLayerDoglegs = 0; AutoSegmentLut::const_iterator isegment = _autoSegmentLut.begin(); for ( ; isegment != _autoSegmentLut.end() ; ++isegment ) { - if ((*isegment).second->isFixed()) fixedSegments++; + if ((*isegment).second->isFixed()) ++fixedSegments; + if ((*isegment).second->reduceDoglegLayer()) ++sameLayerDoglegs; } cmess1 << " o Driving Hurricane data-base." << endl; @@ -266,6 +268,7 @@ namespace Katabatic { cmess1 << Dots::asSizet(" - Active AutoContacts",AutoContact::getAllocateds()-fixedSegments*2) << endl; cmess1 << Dots::asSizet(" - AutoSegments" ,AutoSegment::getAllocateds()) << endl; cmess1 << Dots::asSizet(" - AutoContacts" ,AutoContact::getAllocateds()) << endl; + cmess1 << Dots::asSizet(" - Same Layer doglegs" ,sameLayerDoglegs) << endl; forEach ( Net*, inet, _cell->getNets() ) _saveNet( *inet ); diff --git a/katabatic/src/LoadGrByNet.cpp b/katabatic/src/LoadGrByNet.cpp index c08f1909..b665d87a 100644 --- a/katabatic/src/LoadGrByNet.cpp +++ b/katabatic/src/LoadGrByNet.cpp @@ -21,6 +21,8 @@ #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" @@ -47,6 +49,9 @@ namespace { + using Katabatic::AutoContactTerminal; + + /*! \defgroup LoadGlobalRouting Global Routing Loading * \brief Translation rules to build detailed routing from global * @@ -111,6 +116,12 @@ namespace { * * \brief Build the wiring for a Net inside a GCell (\b internal). * + * As this class is called to initially construct the Katabatic 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, unsigned int flags ); @@ -171,6 +182,33 @@ namespace { //! //! \image html doRp_Access.png "doRp_Access()" +//! \function AutoContact* GCellTopology::doRp_AccessPad ( Component* rp, unsigned int 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 Katabatic::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 Katabatic 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: @@ -187,7 +225,17 @@ namespace { //! //! \image html doRp_StairCaseV.png "doRp_StairCaseV()" -//! \function GCellTopology::_do_xG (); +//! \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). //! @@ -594,6 +642,7 @@ namespace { inline GCell* getGCell () const; static void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, unsigned int flags ); static AutoContact* doRp_Access ( GCell*, Component*, unsigned int flags ); + static AutoContact* doRp_AccessPad ( Component*, unsigned int flags ); static void doRp_StairCaseH ( GCell*, Component* rp1, Component* rp2 ); static void doRp_StairCaseV ( GCell*, Component* rp1, Component* rp2 ); private: @@ -1132,6 +1181,135 @@ namespace { } + AutoContact* GCellTopology::doRp_AccessPad ( Component* rp, unsigned int flags ) + { + ltrace(99) << "doRp_AccessPad()" << endl; + ltracein(99); + ltrace(99) << rp << endl; + + // Hardcoded: H access is METAL2 (depth=1), V access is METAL3 (depth=2). + 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" + " has a layer unreachable by the router (top layer is: %s)" + , getString(rp).c_str() + , getString(Session::getRoutingLayer(Session::getAllowedDepth())).c_str() + ) << endl; + padDepth = Session::getAllowedDepth(); + } + + rp->getBodyHook()->detach(); + + Point position = rp->getCenter(); + GCell* gcell = Session::getKatabatic()->getGCellGrid()->getGCell(position); + Component* anchor = rp; + + if (padDepth != accessDepth) { + if (padDepth > accessDepth) { + // Go *down* from the pad's RoutingPad. + --padDepth; + + Contact* target = NULL; + Contact* source = Contact::create ( rp + , Session::getContactLayer(padDepth) + , 0 + , 0 + , Session::getViaWidth(padDepth) + , Session::getViaWidth(padDepth) + ); + + for ( size_t depth = padDepth ; depth >= accessDepth ; --depth ) { + const Layer* segmentLayer = Session::getRoutingLayer(depth); + const Layer* targetLayer = (depth == accessDepth) ? segmentLayer + : Session::getContactLayer(depth-1); + DbU::Unit targetSide = (depth == accessDepth) ? Session::getWireWidth(depth) + : Session::getViaWidth (depth-1); + + target = Contact::create( rp->getNet() + , targetLayer + , position.getX() + , position.getY() + , targetSide + , targetSide + ); + if (Session::getDirection(depth) == KbHorizontal) { + anchor = Horizontal::create( source + , target + , segmentLayer + , position.getY() + , Session::getWireWidth(depth) + ); + } else { + anchor = Vertical::create( source + , target + , segmentLayer + , position.getX() + , Session::getWireWidth(depth) + ); + } + ltrace(99) << "Pad strap: " << anchor << endl; + source = target; + } + } else { + // Go *up* from the pad's RoutingPad. + Contact* target = NULL; + Contact* source = Contact::create ( rp + , Session::getContactLayer(padDepth) + , 0 + , 0 + , Session::getViaWidth(padDepth) + , Session::getViaWidth(padDepth) + ); + + for ( size_t depth = padDepth ; depth <= accessDepth ; ++depth ) { + const Layer* segmentLayer = Session::getRoutingLayer(depth); + const Layer* targetLayer = (depth == accessDepth) ? segmentLayer + : Session::getContactLayer(depth); + DbU::Unit targetSide = (depth == accessDepth) ? Session::getWireWidth(depth) + : Session::getViaWidth (depth); + + target = Contact::create( rp->getNet() + , targetLayer + , position.getX() + , position.getY() + , targetSide + , targetSide + ); + if (Session::getDirection(depth) == KbHorizontal) { + anchor = Horizontal::create( source + , target + , segmentLayer + , position.getY() + , Session::getWireWidth(depth) + ); + } else { + anchor = Vertical::create( source + , target + , segmentLayer + , position.getX() + , Session::getWireWidth(depth) + ); + } + ltrace(99) << "Pad strap: " << anchor << endl; + source = target; + } + } + } + + AutoContact* autoSource + = AutoContactTerminal::create ( gcell + , anchor + , Session::getRoutingLayer(accessDepth) + , position + , Session::getWireWidth(accessDepth) + , Session::getWireWidth(accessDepth) + ); + ltraceout(99); + return autoSource; + } + + void GCellTopology::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 ) { ltrace(99) << "doRp_StairCaseH()" << endl; @@ -1203,6 +1381,7 @@ namespace { void GCellTopology::_do_xG () { ltrace(99) << "_do_xG()" << endl; + ltracein(99); if (_connexity.fields.globals == 2) { _southWestContact @@ -1229,6 +1408,7 @@ namespace { AutoSegment::create( _southWestContact, turn, KbHorizontal ); AutoSegment::create( turn, _northEastContact, KbVertical ); } + ltraceout(99); } @@ -1236,56 +1416,68 @@ namespace { { ltrace(99) << "_do_xG_1Pad() [Managed Configuration - Optimized] " << _topology << endl; ltracein(99); + ltrace(99) << "_connexity.globals:" << _connexity.fields.globals << endl; - bool eastPad = false; - bool westPad = false; - bool northPad = false; - bool southPad = false; - Instance* padInstance = dynamic_cast(_routingPads[0])->getOccurrence().getPath().getHeadInstance(); + unsigned int flags = NoFlags; + bool eastPad = false; + bool westPad = false; + bool northPad = false; + bool southPad = false; + Instance* padInstance = dynamic_cast(_routingPads[0])->getOccurrence().getPath().getHeadInstance(); switch ( padInstance->getTransformation().getOrientation() ) { case Transformation::Orientation::ID: northPad = true; break; - case Transformation::Orientation::YR: eastPad = true; break; - case Transformation::Orientation::R3: eastPad = true; break; case Transformation::Orientation::MY: southPad = true; break; - case Transformation::Orientation::R1: westPad = true; break; + case Transformation::Orientation::YR: + case Transformation::Orientation::R3: eastPad = true; flags |= HAccess; break; + case Transformation::Orientation::R1: westPad = true; flags |= HAccess; break; default: cerr << Warning( "Unmanaged orientation %s for pad <%s>." , getString(padInstance->getTransformation().getOrientation()).c_str() , getString(padInstance).c_str() ) << endl; break; } + ltrace(99) << "eastPad:" << eastPad << ", " + << "westPad:" << westPad << ", " + << "northPad:" << northPad << ", " + << "southPad:" << southPad + << endl; - Point position = _routingPads[0]->getCenter(); - AutoContact* source = NULL; - GCell* gcell = Session::getKatabatic()->getGCellGrid()->getGCell(position); + AutoContact* source = doRp_AccessPad( _routingPads[0], flags ); + // Point position = _routingPads[0]->getCenter(); + // AutoContact* source = NULL; + // GCell* gcell = Session::getKatabatic()->getGCellGrid()->getGCell(position); - source = AutoContactTerminal::create ( gcell - , _routingPads[0] - , Session::getContactLayer(3) - , position - , Session::getViaWidth(3), Session::getViaWidth(3) - ); - source->setFlags( CntFixed ); + // source = AutoContactTerminal::create ( gcell + // , _routingPads[0] + // , Session::getContactLayer(3) + // , position + // , Session::getViaWidth(3), Session::getViaWidth(3) + // ); + // source->setFlags( CntFixed ); - if (northPad or eastPad) { - _southWestContact = _northEastContact = source; - ltraceout(99); - return; - } + // if (northPad or eastPad) { + // _southWestContact = _northEastContact = source; + // ltraceout(99); + // return; + // } // Check for straight lines, which are not managed by _do_xG(). if (_connexity.fields.globals == 1) { - if (westPad and (_east != NULL)) { + if ( (westPad and (_east != NULL)) + or (eastPad and (_west != NULL)) ) { AutoContact* turn = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); - _northEastContact = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); + _northEastContact = _southWestContact + = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); AutoSegment::create( source, turn, KbHorizontal ); AutoSegment::create( turn, _northEastContact, KbVertical ); ltraceout(99); return; - } else if (southPad and (_north != NULL)) { + } else if ( (southPad and (_north != NULL)) + or (northPad and (_south != NULL)) ) { AutoContact* turn = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); - _northEastContact = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); + _northEastContact = _southWestContact + = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); AutoSegment::create( source, turn, KbVertical ); AutoSegment::create( turn, _northEastContact, KbHorizontal ); ltraceout(99); @@ -1297,7 +1489,9 @@ namespace { --_connexity.fields.Pad; if (westPad ) _west = source->getBodyHook(); + if (eastPad ) _east = source->getBodyHook(); if (southPad) _south = source->getBodyHook(); + if (northPad) _north = source->getBodyHook(); _do_xG(); @@ -1305,10 +1499,18 @@ namespace { AutoSegment::create( source, _southWestContact, KbHorizontal ); _west = NULL; } + if (eastPad) { + AutoSegment::create( source, _northEastContact, KbHorizontal ); + _east = NULL; + } if (southPad) { AutoSegment::create( source, _southWestContact, KbVertical ); _south = NULL; } + if (northPad) { + AutoSegment::create( source, _northEastContact, KbVertical ); + _north = NULL; + } --_connexity.fields.globals; ltraceout(99); diff --git a/katabatic/src/katabatic/AutoContact.h b/katabatic/src/katabatic/AutoContact.h index 8c482d33..52327661 100644 --- a/katabatic/src/katabatic/AutoContact.h +++ b/katabatic/src/katabatic/AutoContact.h @@ -17,13 +17,13 @@ #ifndef KATABATIC_AUTOCONTACT_H #define KATABATIC_AUTOCONTACT_H -#include -#include -#include "hurricane/Contact.h" -#include "hurricane/ExtensionGo.h" -#include "katabatic/Constants.h" -#include "katabatic/AutoSegment.h" -#include "katabatic/GCell.h" +#include +#include +#include "hurricane/Contact.h" +#include "hurricane/ExtensionGo.h" +#include "katabatic/Constants.h" +#include "katabatic/AutoSegment.h" +#include "katabatic/GCell.h" namespace Katabatic { @@ -124,6 +124,7 @@ namespace Katabatic { virtual Box getBoundingBox () const; inline GCell* getGCell () const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const = 0; + virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const = 0; virtual AutoSegment* getSegment ( unsigned int ) const = 0; unsigned int getMinDepth () const; unsigned int getMaxDepth () const; @@ -313,11 +314,11 @@ namespace Katabatic { inline void LocatorHelper::progress () { ltracein(80); - ltrace(80) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl; ++_index; + ltrace(80) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl; while ((_index < _max()) and (_contact->getSegment(_index) == NULL)) { - ltrace(80) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl; ++_index; + ltrace(80) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl; } ltraceout(80); } diff --git a/katabatic/src/katabatic/AutoContactHTee.h b/katabatic/src/katabatic/AutoContactHTee.h index c79cdbf9..8febc972 100644 --- a/katabatic/src/katabatic/AutoContactHTee.h +++ b/katabatic/src/katabatic/AutoContactHTee.h @@ -44,6 +44,7 @@ namespace Katabatic { inline AutoHorizontal* getHorizontal2 () const; inline AutoVertical* getVertical1 () const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const; + virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const; virtual AutoSegment* getSegment ( unsigned int ) const; virtual void updateGeometry (); virtual void updateTopology (); diff --git a/katabatic/src/katabatic/AutoContactTerminal.h b/katabatic/src/katabatic/AutoContactTerminal.h index 7832476e..5068e648 100644 --- a/katabatic/src/katabatic/AutoContactTerminal.h +++ b/katabatic/src/katabatic/AutoContactTerminal.h @@ -55,6 +55,7 @@ namespace Katabatic { inline AutoSegment* getSegment () const; virtual AutoSegment* getSegment ( unsigned int ) const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const; + virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const; virtual void updateGeometry (); virtual void updateTopology (); virtual void cacheDetach ( AutoSegment* ); diff --git a/katabatic/src/katabatic/AutoContactTurn.h b/katabatic/src/katabatic/AutoContactTurn.h index 52657e82..3605636a 100644 --- a/katabatic/src/katabatic/AutoContactTurn.h +++ b/katabatic/src/katabatic/AutoContactTurn.h @@ -43,6 +43,7 @@ namespace Katabatic { inline AutoHorizontal* getHorizontal1 () const; inline AutoVertical* getVertical1 () const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const; + virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const; virtual AutoSegment* getSegment ( unsigned int ) const; virtual void updateGeometry (); virtual void updateTopology (); diff --git a/katabatic/src/katabatic/AutoContactVTee.h b/katabatic/src/katabatic/AutoContactVTee.h index ba4d0f64..225daf3c 100644 --- a/katabatic/src/katabatic/AutoContactVTee.h +++ b/katabatic/src/katabatic/AutoContactVTee.h @@ -41,6 +41,7 @@ namespace Katabatic { inline AutoVertical* getVertical1 () const; inline AutoVertical* getVertical2 () const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const; + virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const; virtual AutoSegment* getSegment ( unsigned int ) const; virtual void updateGeometry (); virtual void updateTopology (); diff --git a/katabatic/src/katabatic/AutoSegment.h b/katabatic/src/katabatic/AutoSegment.h index f42668a8..f48043eb 100644 --- a/katabatic/src/katabatic/AutoSegment.h +++ b/katabatic/src/katabatic/AutoSegment.h @@ -30,7 +30,7 @@ namespace Hurricane { class Vertical; class Cell; } - +#include "crlcore/RoutingGauge.h" #include "katabatic/Constants.h" #include "katabatic/Observer.h" #include "katabatic/GCell.h" @@ -53,6 +53,7 @@ namespace Katabatic { using Hurricane::Horizontal; using Hurricane::Vertical; using Hurricane::Cell; + using CRL::RoutingGauge; class AutoHorizontal; class AutoVertical; @@ -60,43 +61,44 @@ namespace Katabatic { // ------------------------------------------------------------------- // Class : "AutoSegment". - enum AutoSegmentFlag { SegNoFlags = 0x00000000 - , SegHorizontal = 0x00000001 - , SegFixed = 0x00000002 - , SegGlobal = 0x00000004 - , SegWeakGlobal = 0x00000008 - , SegCanonical = 0x00000010 - , SegBipoint = 0x00000020 - , SegDogleg = 0x00000040 - , SegStrap = 0x00000080 - , SegSourceTop = 0x00000100 - , SegSourceBottom = 0x00000200 - , SegTargetTop = 0x00000400 - , SegTargetBottom = 0x00000800 - , SegLayerChange = 0x00001000 - , SegSourceTerminal = 0x00002000 // Replace Terminal. - , SegTargetTerminal = 0x00004000 // Replace Terminal. + enum AutoSegmentFlag { SegNoFlags = 0x0 + , SegHorizontal = (1<< 0) + , SegFixed = (1<< 1) + , SegGlobal = (1<< 2) + , SegWeakGlobal = (1<< 3) + , SegCanonical = (1<< 4) + , SegBipoint = (1<< 5) + , SegDogleg = (1<< 6) + , SegStrap = (1<< 7) + , SegSourceTop = (1<< 8) + , SegSourceBottom = (1<< 9) + , SegTargetTop = (1<<10) + , SegTargetBottom = (1<<11) + , SegIsReduced = (1<<12) + , SegLayerChange = (1<<13) + , SegSourceTerminal = (1<<14) // Replace Terminal. + , SegTargetTerminal = (1<<15) // Replace Terminal. , SegStrongTerminal = SegSourceTerminal|SegTargetTerminal - , SegWeakTerminal1 = 0x00008000 // Replace TopologicalEnd. - , SegWeakTerminal2 = 0x00010000 // Replace TopologicalEnd. - , SegNotSourceAligned = 0x00020000 - , SegNotTargetAligned = 0x00040000 - , SegUnbound = 0x00100000 - , SegHalfSlackened = 0x00200000 - , SegSlackened = 0x00400000 - , SegAxisSet = 0x00800000 - , SegInvalidated = 0x01000000 - , SegInvalidatedSource = 0x02000000 - , SegInvalidatedTarget = 0x04000000 - , SegInvalidatedLayer = 0x08000000 - , SegCreated = 0x10000000 - , SegUserDefined = 0x20000000 + , SegWeakTerminal1 = (1<<16) // Replace TopologicalEnd. + , SegWeakTerminal2 = (1<<17) // Replace TopologicalEnd. + , SegNotSourceAligned = (1<<18) + , SegNotTargetAligned = (1<<19) + , SegUnbound = (1<<20) + , SegHalfSlackened = (1<<21) + , SegSlackened = (1<<22) + , SegAxisSet = (1<<23) + , SegInvalidated = (1<<24) + , SegInvalidatedSource = (1<<25) + , SegInvalidatedTarget = (1<<26) + , SegInvalidatedLayer = (1<<27) + , SegCreated = (1<<28) + , SegUserDefined = (1<<29) // Masks. , SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2 , SegNotAligned = SegNotSourceAligned|SegNotTargetAligned - , SegSpinTop = SegSourceTop |SegTargetTop - , SegSpinBottom = SegSourceBottom|SegTargetBottom - , SegDepthSpin = SegSpinTop |SegSpinBottom + , SegSpinTop = SegSourceTop |SegTargetTop + , SegSpinBottom = SegSourceBottom |SegTargetBottom + , SegDepthSpin = SegSpinTop |SegSpinBottom }; @@ -122,6 +124,7 @@ namespace Katabatic { static AutoSegment* create ( AutoContact* source , AutoContact* target , unsigned int dir + , size_t depth=RoutingGauge::nlayerdepth ); void destroy (); // Wrapped Segment Functions. @@ -169,11 +172,11 @@ namespace Katabatic { bool isStrongTerminal ( unsigned int flags=0 ) const; inline bool isSourceTerminal () const; inline bool isTargetTerminal () const; - bool isSameLayerDogleg () const; inline bool isLayerChange () const; inline bool isSpinTop () const; inline bool isSpinBottom () const; inline bool isSpinTopOrBottom () const; + inline bool isReduced () const; inline bool isStrap () const; inline bool isDogleg () const; inline bool isUnbound () const; @@ -185,6 +188,8 @@ namespace Katabatic { inline bool isSlackened () const; inline bool isUserDefined () const; virtual bool _canSlacken () const = 0; + bool canReduce () const; + bool mustRaise () const; unsigned int canDogleg ( Interval ); virtual bool canMoveULeft ( float reserve=0.0 ) const = 0; virtual bool canMoveURight ( float reserve=0.0 ) const = 0; @@ -239,6 +244,8 @@ namespace Katabatic { inline void unsetFlags ( unsigned int ); inline void setFlags ( unsigned int ); void setFlagsOnAligneds ( unsigned int ); + inline void incReduceds (); + inline void decReduceds (); virtual void setDuSource ( DbU::Unit du ) = 0; virtual void setDuTarget ( DbU::Unit du ) = 0; void computeTerminal (); @@ -270,6 +277,9 @@ namespace Katabatic { void changeDepth ( unsigned int depth, unsigned int flags ); bool moveUp ( unsigned int flags=KbNoFlags ); bool moveDown ( unsigned int flags=KbNoFlags ); + bool reduceDoglegLayer (); + bool reduce (); + bool raise (); // Canonical Modifiers. AutoSegment* canonize ( unsigned int flags=KbNoFlags ); virtual void invalidate ( unsigned int flags=KbPropagate ); @@ -314,6 +324,7 @@ namespace Katabatic { unsigned int _depth : 8; unsigned int _optimalMin : 8; unsigned int _optimalMax : 8; + unsigned int _reduceds : 2; DbU::Unit _sourcePosition; DbU::Unit _targetPosition; Interval _userConstraints; @@ -445,6 +456,7 @@ namespace Katabatic { inline bool AutoSegment::isSpinTop () const { return ((_flags & SegSpinTop ) == SegSpinTop); } inline bool AutoSegment::isSpinBottom () const { return ((_flags & SegSpinBottom) == SegSpinBottom); } inline bool AutoSegment::isSpinTopOrBottom () const { return isSpinTop() or isSpinBottom(); } + inline bool AutoSegment::isReduced () const { return _flags & SegIsReduced; } inline bool AutoSegment::isSlackened () const { return _flags & SegSlackened; } inline bool AutoSegment::isCanonical () const { return _flags & SegCanonical; } inline bool AutoSegment::isUnsetAxis () const { return not (_flags & SegAxisSet); } @@ -457,6 +469,8 @@ namespace Katabatic { inline unsigned int AutoSegment::getFlags () const { return _flags; } inline unsigned int AutoSegment::_getFlags () const { return _flags; } + inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; } + inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; } inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); } inline void AutoSegment::setOptimalMin ( DbU::Unit min ) { _optimalMin = (unsigned int)DbU::getLambda(min-getOrigin()); } inline void AutoSegment::setOptimalMax ( DbU::Unit max ) { _optimalMax = (unsigned int)DbU::getLambda(max-getOrigin()); } diff --git a/katabatic/src/katabatic/Session.h b/katabatic/src/katabatic/Session.h index 8dab84a7..fbdbbe63 100644 --- a/katabatic/src/katabatic/Session.h +++ b/katabatic/src/katabatic/Session.h @@ -17,17 +17,17 @@ #ifndef KATABATIC_SESSION_H #define KATABATIC_SESSION_H -#include -#include -#include -#include -#include -#include "hurricane/Commons.h" -#include "hurricane/DbU.h" -#include "crlcore/CellGauge.h" -#include "crlcore/RoutingGauge.h" -#include "katabatic/Constants.h" -#include "katabatic/Configuration.h" +#include +#include +#include +#include +#include +#include "hurricane/Commons.h" +#include "hurricane/DbU.h" +#include "crlcore/CellGauge.h" +#include "crlcore/RoutingGauge.h" +#include "katabatic/Constants.h" +#include "katabatic/Configuration.h" namespace Hurricane { class Layer; diff --git a/kite/doc/Session.dox b/kite/doc/Session.dox index dc6dd463..bbbd7568 100644 --- a/kite/doc/Session.dox +++ b/kite/doc/Session.dox @@ -56,17 +56,23 @@ * - Process all insert events. This is the time TrackSegment * are moved into their new Track (physical displacement). * It is at this point that the invalidation of both AutoSegment - * and TrackSEgment is done. + * and TrackSegment is done. * - Call the Katabatic::Session::revalidate() method which * will recompute the correct contact extensions and topologies. * \e After this step the Katabatic data-base is up to date, - * but \e not the Kite one. AutoSEgment are revalidated. + * but \e not the Kite one. AutoSegment are revalidated. * - Recompute the canonical position of source and target * of all invalidateds TrackSegment (take account of * extention modifications). The set of invalidated TrackSegment * is computed from the revalidated AutoSegment, that is * AutoSegment that are canonical. * - Perform a sort() on all Track that have been modifieds. + * - Now that the size of the segments have been accurately computed, + * look for revalidateds TrackSegment that: + * -# Can be reduced, generate a track remove event. + * -# Must be raised, generate a routing event (put into the + * queue). + * - Process the additional track remove events. * * Note: We cannot use the Observer mechanism to automatically * update TrackSegment from an AutoSegment, because we must wait for all diff --git a/kite/doc/TrackSegment.dox b/kite/doc/TrackSegment.dox index eb8e54ca..b617ce4b 100644 --- a/kite/doc/TrackSegment.dox +++ b/kite/doc/TrackSegment.dox @@ -27,7 +27,7 @@ * The associated DataNegociate and RoutingEvent are \b not updated. * - The RoutingEvent will be updated when it's key is updated, * typically during a requeueing operation \b and in the - * SegmentFsm constructor. This should be optimzed in the future. + * SegmentFsm constructor. This should be optimized in the future. * - The DataNegociate is updated \e only in the SegmentFsm * constructor. This is the most costly of the two updates as * it perform a perpandicular & parallel connexity exploration. @@ -51,9 +51,9 @@ * * Figure 2 below, shows an example of dogleg creation: * - At the Katabatic level, AutoSegment \c id:12 is broken. Thus - * the creation of AutoSegments \c id:20 and \c id:21. As per - * specification, the orignal segment \c id:10 remains on the - * left side (source) of the break. + * the creation of AutoSegments \c id:20 and \c id:21. The orignal + * TrackSegment (canonical AutoSegment \c id:10) remains on the + * right side (target) of the break. * - But, because the canonical of the former aligned AutoSegment * set \c (10,11,12,13,14) was on the \e right side of the break, * the new parallel TrackSegment will be created on the \c left diff --git a/kite/doc/notes.dox b/kite/doc/notes.dox index 8664e043..ae0f16e4 100644 --- a/kite/doc/notes.dox +++ b/kite/doc/notes.dox @@ -42,6 +42,14 @@ * - Now that the Hurricane database is deterministic, the router * seems to be likewise. * + * - Reduce/raise mechanism. To manage same layer dogleg + * this mechanism has been implemented. When a candidate dogleg + * perpandicular segment length shrink below one pitch it is + * removed from any track to become invisible. + * Conversely, when a reduced segment length expand over one pitch + * generate a new RoutingEvent to insert it. All this is managed + * in the Session::revalidate() method. + * * * \section secPendingModifications Pending Modifications * diff --git a/kite/src/BuildPowerRails.cpp b/kite/src/BuildPowerRails.cpp index 6a6a377b..5cee9ac1 100644 --- a/kite/src/BuildPowerRails.cpp +++ b/kite/src/BuildPowerRails.cpp @@ -723,10 +723,10 @@ namespace { axisMin = _axis - _width/2; axisMax = _axis + _width/2; - if (coronaBb.contains(segment->getBoundingBox())) { + //if (coronaBb.contains(segment->getBoundingBox())) { axisMin -= delta; axisMax += delta; - } + //} Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior ); for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNextTrack() ) { diff --git a/kite/src/KiteEngine.cpp b/kite/src/KiteEngine.cpp index 3cd1b1a8..c885d358 100644 --- a/kite/src/KiteEngine.cpp +++ b/kite/src/KiteEngine.cpp @@ -354,6 +354,11 @@ namespace Kite { size_t coronaReserved = 4; for( Knik::Vertex* vertex : _knik->getRoutingGraph()->getVertexes() ) { + if ( chipTools.isChip() + and ( chipTools.hPadsEnclosed(Box(vertex->getPosition())) + or chipTools.vPadsEnclosed(Box(vertex->getPosition()))) ) + vertex->setBlocked(); + for ( int i=0 ; i<2 ; ++i ) { Knik::Edge* edge = NULL; @@ -661,6 +666,7 @@ namespace Kite { unsigned long long totalWireLength = 0; unsigned long long routedWireLength = 0; vector unrouteds; + vector reduceds; ostringstream result; AutoSegmentLut::const_iterator ilut = _getAutoSegmentLut().begin(); @@ -676,20 +682,16 @@ namespace Kite { } if (segment->isFixed() or segment->isBlockage()) continue; - - // if (segment->isSameLayerDogleg()) { - // cerr << " Same layer:" << segment << endl; - // cerr << " S: " << segment->base()->getAutoSource() << endl; - // cerr << " T: " << segment->base()->getAutoTarget() << endl; - // } + if (segment->isReduced()) reduceds.push_back( segment ); totalWireLength += wl; - if (segment->getTrack() != NULL) { + if ( (segment->getTrack() != NULL) or (segment->isReduced()) ) { routeds++; routedWireLength += wl; - } else { - unrouteds.push_back( segment ); + continue; } + + unrouteds.push_back( segment ); } float segmentRatio = (float)(routeds) / (float)(routeds+unrouteds.size()) * 100.0; @@ -704,6 +706,13 @@ namespace Kite { } } + // if (not reduceds.empty()) { + // cerr << " o Reduced segments:" << endl; + // for ( size_t i=0; isetFixedPreRouted(); } + Session::revalidate(); Session::get()->isEmpty(); # if defined(CHECK_DATABASE) diff --git a/kite/src/ProtectRoutingPads.cpp b/kite/src/ProtectRoutingPads.cpp index 309db737..7206a581 100644 --- a/kite/src/ProtectRoutingPads.cpp +++ b/kite/src/ProtectRoutingPads.cpp @@ -71,12 +71,17 @@ namespace { void protectRoutingPad ( RoutingPad* rp ) { + Name padNetName = "pad"; Component* usedComponent = rp->_getEntityAsComponent(); Path path = rp->getOccurrence().getPath(); Net* masterNet = usedComponent->getNet(); Transformation transformation = path.getTransformation(); - if ( CatalogExtension::isPad(masterNet->getCell()) ) return; + if ( CatalogExtension::isPad(masterNet->getCell()) ) { + if ( rp->getNet()->isPower() + or (rp->getNet()->getName() == padNetName) ) + return; + } vector segments; diff --git a/kite/src/RoutingEvent.cpp b/kite/src/RoutingEvent.cpp index 74f54c79..9cf6540d 100644 --- a/kite/src/RoutingEvent.cpp +++ b/kite/src/RoutingEvent.cpp @@ -476,7 +476,8 @@ namespace Kite { _axisHistory = _segment->getAxis(); _eventLevel = 0; ltrace(500) << "Deter| addInsertEvent() @" << fsm.getCost(itrack).getTrack() << endl; - Session::addInsertEvent( _segment, fsm.getCost(itrack).getTrack() ); + if (not _segment->isReduced()) + Session::addInsertEvent( _segment, fsm.getCost(itrack).getTrack() ); fsm.setState( SegmentFsm::SelfInserted ); } else { // Do ripup. diff --git a/kite/src/SegmentFsm.cpp b/kite/src/SegmentFsm.cpp index d8340254..54fed1ba 100644 --- a/kite/src/SegmentFsm.cpp +++ b/kite/src/SegmentFsm.cpp @@ -443,23 +443,23 @@ namespace Kite { SegmentFsm::SegmentFsm ( RoutingEvent* event, RoutingEventQueue& queue, RoutingEventHistory& history ) - : _event (event) - , _queue (queue) - , _history (history) - , _state (0) - , _data (NULL) - , _constraint () - , _optimal () - , _costs () - , _actions () - , _fullBlocked (true) + : _event (event) + , _queue (queue) + , _history (history) + , _state (0) + , _data (NULL) + , _constraint () + , _optimal () + , _costs () + , _actions () + , _fullBlocked(true) { TrackElement* segment = _event->getSegment(); unsigned int depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer()); - _event->setTracksFree ( 0 ); + _event->setTracksFree( 0 ); _data = segment->getDataNegociate(); - if ( !_data ) { + if (not _data) { _state = MissingData; return; } @@ -470,7 +470,7 @@ namespace Kite { _constraint = _event->getConstraints(); _optimal = _event->getOptimal(); - const Interval& perpandicular = _event->getPerpandicularFree (); + const Interval& perpandicular = _event->getPerpandicularFree(); ltrace(148) << "Katabatic intervals:" << endl; ltrace(148) << "* Optimal: " << _optimal << endl; @@ -478,18 +478,18 @@ namespace Kite { ltrace(148) << "* Perpandicular: " << perpandicular << endl; ltrace(148) << "* AxisHint: " << DbU::getValueString(_event->getAxisHint()) << endl; - if ( _event->getTracksNb() ) { - if ( _constraint.getIntersection(perpandicular).isEmpty() ) { + if (_event->getTracksNb()) { + if (_constraint.getIntersection(perpandicular).isEmpty()) { ltrace(200) << "Perpandicular free is too tight." << endl; _state = EmptyTrackList; } else - _constraint.intersection ( perpandicular ); + _constraint.intersection( perpandicular ); } else { ltrace(200) << "No Track in perpandicular free." << endl; _state = EmptyTrackList; } - if ( _state == EmptyTrackList ) return; + if (_state == EmptyTrackList) return; ltrace(148) << "Negociate intervals:" << endl; ltrace(148) << "* Optimal: " << _optimal << endl; @@ -504,27 +504,30 @@ namespace Kite { and (segment->base()->getAutoSource()->getGCell()->getGlobalsCount(depth) >= 9.0); RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(segment->getLayer()); - for( Track* track : Tracks_Range::get(plane,_constraint)) { + for ( Track* track : Tracks_Range::get(plane,_constraint) ) { unsigned int costflags = 0; costflags |= (segment->isLocal() and (depth >= 3)) ? TrackCost::LocalAndTopDepth : 0; - _costs.push_back ( track->getOverlapCost(segment,costflags) ); - _costs.back().setAxisWeight ( _event->getAxisWeight(track->getAxis()) ); - _costs.back().incDeltaPerpand ( _data->getWiringDelta(track->getAxis()) ); + if (not segment->isReduced()) + _costs.push_back( track->getOverlapCost(segment,costflags) ); + else + _costs.push_back( TrackCost(track,segment->getNet()) ); + _costs.back().setAxisWeight ( _event->getAxisWeight(track->getAxis()) ); + _costs.back().incDeltaPerpand( _data->getWiringDelta(track->getAxis()) ); if (segment->isGlobal()) { ltrace(500) << "Deter| setForGlobal() on " << track << endl; _costs.back().setForGlobal(); } if ( inLocalDepth and (_costs.back().getDataState() == DataNegociate::MaximumSlack) ) - _costs.back().setInfinite (); + _costs.back().setInfinite(); if ( isOneLocalTrack and _costs.back().isOverlapGlobal() and (_costs.back().getDataState() >= DataNegociate::ConflictSolveByHistory) ) - _costs.back().setInfinite (); + _costs.back().setInfinite(); - _costs.back().consolidate (); + _costs.back().consolidate(); if ( _fullBlocked and (not _costs.back().isBlockage() and not _costs.back().isFixed()) ) _fullBlocked = false; @@ -532,7 +535,7 @@ namespace Kite { } ltraceout(148); - if ( _costs.empty() ) { + if (_costs.empty()) { Track* nearest = plane->getTrackByPosition(_constraint.getCenter()); if ( (nearest->getAxis() < _constraint.getVMin()) @@ -541,9 +544,9 @@ namespace Kite { //cerr << "[UNIMPLEMENTED] " << segment << " no Track in constraint interval " // << _constraint << " " << "." << endl; } else { - cerr << Bug(" %s Track_Range() failed to find Tracks in %s (they exists)." - ,getString(segment).c_str() - ,getString(_constraint).c_str() + cerr << Bug( " %s Track_Range() failed to find Tracks in %s (they exists)." + , getString(segment).c_str() + , getString(_constraint).c_str() ) << endl; } _state = EmptyTrackList; @@ -557,11 +560,11 @@ namespace Kite { ? TrackCost::DiscardGlobals : 0; flags |= (RoutingEvent::getStage() == RoutingEvent::Repair) ? TrackCost::IgnoreSharedLength : 0; - if ( flags & TrackCost::DiscardGlobals ) { + if (flags & TrackCost::DiscardGlobals) { ltrace(200) << "TrackCost::Compare() - DiscardGlobals" << endl; } - sort ( _costs.begin(), _costs.end(), TrackCost::Compare(flags) ); + sort( _costs.begin(), _costs.end(), TrackCost::Compare(flags) ); size_t i=0; for ( ; (i<_costs.size()) and _costs[i].isFree() ; i++ ); diff --git a/kite/src/Session.cpp b/kite/src/Session.cpp index 4ed63a37..90dd21c7 100644 --- a/kite/src/Session.cpp +++ b/kite/src/Session.cpp @@ -14,14 +14,14 @@ // +-----------------------------------------------------------------+ -#include "hurricane/Bug.h" -#include "hurricane/Point.h" -#include "hurricane/Error.h" -#include "katabatic/GCellGrid.h" -#include "kite/Session.h" -#include "kite/Track.h" -#include "kite/TrackElement.h" -#include "kite/KiteEngine.h" +#include "hurricane/Bug.h" +#include "hurricane/Point.h" +#include "hurricane/Error.h" +#include "katabatic/GCellGrid.h" +#include "kite/Session.h" +#include "kite/Track.h" +#include "kite/TrackElement.h" +#include "kite/KiteEngine.h" namespace { @@ -135,11 +135,8 @@ namespace Kite { { return _getKiteEngine()->getGCellGrid()->getGCell(Point(x,y)); }; - size_t Session::_revalidate () + void Session::_doRemovalEvents () { - ltrace(90) << "Kite::Session::_revalidate()" << endl; - ltracein(90); - set packTracks; for ( size_t i=0 ; i<_removeEvents.size() ; ++i ) { @@ -152,6 +149,15 @@ namespace Kite { for ( set::iterator it=packTracks.begin() ; it != packTracks.end() ; ++it ) (*it)->doRemoval(); + } + + + size_t Session::_revalidate () + { + ltrace(150) << "Kite::Session::_revalidate()" << endl; + ltracein(150); + + _doRemovalEvents(); for ( size_t i=0 ; i<_insertEvents.size() ; ++i ) { if (_insertEvents[i]._segment) { @@ -194,10 +200,10 @@ namespace Kite { # if defined(CHECK_DATABASE) unsigned int overlaps = 0; # endif - for ( set::iterator it=_sortEvents.begin() ; it!=_sortEvents.end() ; ++it ) { - (*it)->doReorder(); + for ( Track* track : _sortEvents ) { + track->doReorder(); # if defined(CHECK_DATABASE) - (*it)->check( overlaps, "Session::_revalidate() - track sorting." ); + track->check( overlaps, "Session::_revalidate() - track sorting." ); # endif } @@ -227,7 +233,24 @@ namespace Kite { } #endif - ltraceout(90); + // Looking for reduced/raised segments. + for ( size_t i=0 ; icanReduce()) { + revalidateds[i]->reduce(); + TrackElement* trackSegment = lookup( revalidateds[i] ); + if (trackSegment->getTrack()) _addRemoveEvent( trackSegment ); + ltrace(150) << "Session: reduce:" << revalidateds[i] << endl; + } + if (revalidateds[i]->mustRaise()) { + revalidateds[i]->raise(); + lookup( revalidateds[i] )->reschedule( 0 ); + ltrace(150) << "Session: raise:" << revalidateds[i] << endl; + } + } + + _doRemovalEvents(); + + ltraceout(150); return count; } @@ -235,11 +258,17 @@ namespace Kite { bool Session::_isEmpty () const { if ( not _insertEvents.empty() or not _removeEvents.empty() or not _sortEvents.empty() ) { - cerr << Bug( " Session::checkEmpty() failed :\n" - " %u inserts, %u removes and %u sort events remains." + cerr << Bug( "Session::_isEmpty() failed :\n" + " %u inserts, %u removes and %u sort events remains." , _insertEvents.size() , _removeEvents.size() , _sortEvents .size() ) << endl; + if (not _sortEvents.empty()) { + cerr << " Remaining sort events on Tracks:" << endl; + for ( Track* track : _sortEvents ) { + cerr << " | " << track << endl; + } + } return false; } diff --git a/kite/src/TrackCost.cpp b/kite/src/TrackCost.cpp index dc78f751..5a7de899 100644 --- a/kite/src/TrackCost.cpp +++ b/kite/src/TrackCost.cpp @@ -31,6 +31,34 @@ namespace Kite { // ------------------------------------------------------------------- // Class : "TrackCost". + TrackCost::TrackCost ( Track* track, Net* net ) + : _flags (ZeroCost) + , _track (track) + , _begin (Track::npos) + , _end (Track::npos) + , _interval () + , _forGlobal (false) + , _blockage (false) + , _fixed (false) + , _infinite (false) + , _hardOverlap (false) + , _overlap (false) + , _leftOverlap (false) + , _rightOverlap (false) + , _overlapGlobal (false) + , _globalEnclosed (false) + , _terminals (0) + , _delta (0) + , _deltaShared (0) + , _deltaPerpand (0) + , _axisWeight (0) + , _distanceToFixed(2*Session::getSliceHeight()) + , _longuestOverlap(0) + , _dataState (0) + , _ripupCount (0) + { } + + TrackCost::TrackCost ( Track* track , const Interval& interval , size_t begin @@ -94,7 +122,6 @@ namespace Kite { } } - TrackCost::~TrackCost () { } diff --git a/kite/src/TrackElement.cpp b/kite/src/TrackElement.cpp index fb3cee5b..05ac0ef4 100644 --- a/kite/src/TrackElement.cpp +++ b/kite/src/TrackElement.cpp @@ -149,7 +149,7 @@ namespace Kite { bool TrackElement::isStrap () const { return false; } bool TrackElement::isSlackened () const { return false; } bool TrackElement::isDogleg () const { return false; } - bool TrackElement::isSameLayerDogleg () const { return false; } + bool TrackElement::isReduced () const { return false; } bool TrackElement::isUserDefined () const { return false; } // Predicates. bool TrackElement::canSlacken () const { return false; } diff --git a/kite/src/TrackFixedSegment.cpp b/kite/src/TrackFixedSegment.cpp index 661cfa1a..7192783b 100644 --- a/kite/src/TrackFixedSegment.cpp +++ b/kite/src/TrackFixedSegment.cpp @@ -1,8 +1,7 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC 2008-2013, All Rights Reserved +// Copyright (c) UPMC 2008-2015, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -120,12 +119,13 @@ namespace Kite { _sourceU = max( boundingBox.getYMin(), uside.getVMin()); _targetU = min( boundingBox.getYMax(), uside.getVMax()); - Katabatic::GCell* gcell = track->getKiteEngine()->getGCellGrid()->getGCell( Point(track->getAxis(),_sourceU) ); - Katabatic::GCell* end = track->getKiteEngine()->getGCellGrid()->getGCell( Point(track->getAxis(),_targetU) ); - Katabatic::GCell* up = NULL; - Interval guside = gcell->getSide( KbVertical ); - Interval segside ( boundingBox.getYMin(), boundingBox.getYMax() ); + Katabatic::GCell* gcell = track->getKiteEngine()->getGCellGrid()->getGCell( Point(track->getAxis(),_sourceU) ); if (gcell) { + Katabatic::GCell* end = track->getKiteEngine()->getGCellGrid()->getGCell( Point(track->getAxis(),_targetU) ); + Katabatic::GCell* up = NULL; + Interval guside = gcell->getSide( KbVertical ); + Interval segside ( boundingBox.getYMin(), boundingBox.getYMax() ); + while ( gcell and (gcell != end) ) { up = gcell->getUp(); if (up == NULL) break; diff --git a/kite/src/TrackSegment.cpp b/kite/src/TrackSegment.cpp index cbbcea47..41d9b451 100644 --- a/kite/src/TrackSegment.cpp +++ b/kite/src/TrackSegment.cpp @@ -141,7 +141,7 @@ namespace Kite { bool TrackSegment::isStrap () const { return _base->isStrap(); } bool TrackSegment::isSlackened () const { return _base->isSlackened(); } bool TrackSegment::isDogleg () const { return _base->isDogleg(); } - bool TrackSegment::isSameLayerDogleg () const { return _base->isSameLayerDogleg(); } + bool TrackSegment::isReduced () const { return _base->isReduced(); } bool TrackSegment::isUserDefined () const { return _base->isUserDefined(); } // Predicates. // Accessors. diff --git a/kite/src/kite/RoutingEvent.h b/kite/src/kite/RoutingEvent.h index 43ce7166..5850f048 100644 --- a/kite/src/kite/RoutingEvent.h +++ b/kite/src/kite/RoutingEvent.h @@ -17,10 +17,10 @@ #ifndef KITE_ROUTING_EVENT_H #define KITE_ROUTING_EVENT_H -#include -#include -#include -#include +#include +#include +#include +#include #include "hurricane/Interval.h" namespace Hurricane { diff --git a/kite/src/kite/Session.h b/kite/src/kite/Session.h index b2a27a16..cf0d35cf 100644 --- a/kite/src/kite/Session.h +++ b/kite/src/kite/Session.h @@ -83,6 +83,7 @@ namespace Kite { Net* _getBlockageNet (); unsigned int _getRipupCost (); Katabatic::GCell* _getGCellUnder ( DbU::Unit, DbU::Unit ); + void _doRemovalEvents (); virtual size_t _revalidate (); bool _isEmpty () const; NegociateWindow* _getNegociateWindow (); diff --git a/kite/src/kite/TrackCost.h b/kite/src/kite/TrackCost.h index d7d72cc1..e29d5e56 100644 --- a/kite/src/kite/TrackCost.h +++ b/kite/src/kite/TrackCost.h @@ -1,4 +1,3 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. @@ -40,10 +39,11 @@ namespace Kite { class TrackCost { public: - enum Flags { IgnoreAxisWeight = 0x1 - , DiscardGlobals = 0x2 - , IgnoreSharedLength = 0x4 - , LocalAndTopDepth = 0x1 + enum Flags { IgnoreAxisWeight = 0x0001 + , DiscardGlobals = 0x0002 + , IgnoreSharedLength = 0x0004 + , LocalAndTopDepth = 0x0008 + , ZeroCost = 0x0010 }; public: @@ -61,6 +61,9 @@ namespace Kite { }; public: + TrackCost ( Track* track + , Net* net + ); TrackCost ( Track* track , const Interval& interval , size_t begin diff --git a/kite/src/kite/TrackElement.h b/kite/src/kite/TrackElement.h index 863b96fa..dd7695e4 100644 --- a/kite/src/kite/TrackElement.h +++ b/kite/src/kite/TrackElement.h @@ -116,7 +116,7 @@ namespace Kite { virtual bool isStrap () const; virtual bool isSlackened () const; virtual bool isDogleg () const; - virtual bool isSameLayerDogleg () const; + virtual bool isReduced () const; virtual bool isUserDefined () const; // Predicates. inline bool isCreated () const; diff --git a/kite/src/kite/TrackSegment.h b/kite/src/kite/TrackSegment.h index 608d9fa3..a79524c7 100644 --- a/kite/src/kite/TrackSegment.h +++ b/kite/src/kite/TrackSegment.h @@ -67,7 +67,7 @@ namespace Kite { virtual bool isStrap () const; virtual bool isSlackened () const; virtual bool isDogleg () const; - virtual bool isSameLayerDogleg () const; + virtual bool isReduced () const; virtual bool isUserDefined () const; // Predicates. virtual bool canDogleg (); diff --git a/knik/src/Graph.cpp b/knik/src/Graph.cpp index 342d2461..e4453b98 100644 --- a/knik/src/Graph.cpp +++ b/knik/src/Graph.cpp @@ -369,7 +369,7 @@ Vertex* Graph::getVertex ( Point p ) { Vertex* vertex; #ifdef __USE_MATRIXVERTEX__ - vertex = _matrixVertex->getVertex(p); + vertex = _matrixVertex->getVertex(p); assert(vertex); #endif #ifdef __USE_SLICINGTREE__ @@ -1139,7 +1139,7 @@ void Graph::Dijkstra() UpdateEstimateCongestion(); //#endif - DebugSession::open( _working_net, 600 ); +//DebugSession::open( _working_net, 600 ); ltrace(600) << "Dijkstra for net: " << _working_net << endl; ltracein(600); ltrace(600) << "Stamp:" << _netStamp << endl; @@ -1304,7 +1304,7 @@ void Graph::Dijkstra() ltraceout(600); ltraceout(600); - DebugSession::close(); +//DebugSession::close(); } void Graph::Monotonic() diff --git a/knik/src/MatrixVertex.cpp b/knik/src/MatrixVertex.cpp index d61a0cd6..8adc2f0e 100644 --- a/knik/src/MatrixVertex.cpp +++ b/knik/src/MatrixVertex.cpp @@ -381,7 +381,23 @@ Vertex* MatrixVertex::getVertex ( Point point ) // ******************************************** { pair indexes = getIJ ( point ); - return getVertex ( indexes ); + Vertex* vertex = getVertex ( indexes ); + if (vertex and vertex->isBlocked()) { + Vertex* neighbor = NULL; + for ( size_t i=0; i<4 ; ++i ) { + neighbor = vertex->getFirstEdges(i)->getOpposite( vertex ); + if (neighbor and not neighbor->isBlocked()) + return neighbor; + } + } + + if (not vertex) { + cerr << Error( "MatrixVertex::getVertex(Point): On %s,\n" + " blocked and it's neighbors are also blocked (vertex unreachable)." + , getString(vertex).c_str() ) << endl; + } + + return vertex; } Vertex* MatrixVertex::getVertex ( DbU::Unit x, DbU::Unit y ) diff --git a/knik/src/knik/Vertex.h b/knik/src/knik/Vertex.h index d942c9c5..a5dc0851 100644 --- a/knik/src/knik/Vertex.h +++ b/knik/src/knik/Vertex.h @@ -19,24 +19,26 @@ namespace Knik { // ***** public: typedef ExtensionGo Inherit; + enum Flags { Blocked=0x0001 }; //enum EdgeDirection { EAST=0, NORTH=1, WEST=2, SOUTH=3, UNDEFINED=4 }; // Attributes // ********** private: - static const Name _extensionName; - Graph* _routingGraph; - Edge* _firstEdges[4]; // dans l'ordre : _hEdgeOut, _vEdgeOut, _hEdgeIn et _vEdgeIn - Edge* _predecessor; - Contact* _contact; - Point _position; - VTuple* _vtuple; - float _distance; - int _connexID; // XXX limiter le nombre de bits du connexID pour associer aux 3 booléens ? - unsigned _netStamp; - DbU::Unit _halfWidth; // this corresponds to the half width of dual bin of the vertex - DbU::Unit _halfHeight; // this corresponds to the half height of dual bin of the vertex - Box _boundingBox; + static const Name _extensionName; + Graph* _routingGraph; + Edge* _firstEdges[4]; // dans l'ordre : _hEdgeOut, _vEdgeOut, _hEdgeIn et _vEdgeIn + Edge* _predecessor; + Contact* _contact; + Point _position; + VTuple* _vtuple; + float _distance; + int _connexID; // XXX limiter le nombre de bits du connexID pour associer aux 3 booléens ? + unsigned _netStamp; + DbU::Unit _halfWidth; // this corresponds to the half width of dual bin of the vertex + DbU::Unit _halfHeight; // this corresponds to the half height of dual bin of the vertex + Box _boundingBox; + unsigned int _flags; // Constructors & Destructors // ************************** @@ -65,60 +67,62 @@ namespace Knik { void setVTuple ( VTuple* vtuple ) { _vtuple = vtuple; }; void attachToLocalRing ( Component* component ); void sortEdges (); + void setBlocked () { _flags |= Blocked; } + void resetBlocked () { _flags &= ~Blocked; } // Accessors // ********* public: - static const Name& staticGetName () { return _extensionName; }; - virtual const Name& getName () const { return _extensionName; }; - Edge* getHEdgeOut () const { return _firstEdges[0]; }; - Edge* getVEdgeOut () const { return _firstEdges[1]; }; - Edge* getHEdgeIn () const { return _firstEdges[2]; }; - Edge* getVEdgeIn () const { return _firstEdges[3]; }; - Edges getAdjacentEdges () const; - Edge* getPredecessor () const { return _predecessor; }; - Contact* getContact () const { return _contact; }; - int getConnexID () const { return _connexID; }; - float getDistance () const { return _distance; }; - unsigned getNetStamp () const { return _netStamp; }; - Point getPosition () const { return _position; }; - VTuple* getVTuple () const { return _vtuple; }; - Graph* getRoutingGraph () const { return _routingGraph; }; - DbU::Unit getX () const { return _position.getX(); }; - DbU::Unit getY () const { return _position.getY(); }; - DbU::Unit getXMin () const { return _position.getX() - _halfWidth; }; - DbU::Unit getYMin () const { return _position.getY() - _halfHeight; }; - DbU::Unit getXMax () const { return _position.getX() + _halfWidth; }; - DbU::Unit getYMax () const { return _position.getY() + _halfHeight; }; - DbU::Unit getHalfWidth () const { return _halfWidth; }; - DbU::Unit getHalfHeight () const { return _halfHeight; }; - Box getBox () const { return Box(getXMin(),getYMin(),getXMax(),getYMax()); }; - Edge* getFirstEdges ( int i ) const { return _firstEdges[i]; }; - Contact* getContact ( Edge* arrivalEdge ); - Edge* getHEdgeLeadingTo ( Vertex* to ); - Edge* getVEdgeLeadingTo ( Vertex* to ); - Edge* getHEdgeComingFrom ( Vertex* from ); - Edge* getVEdgeComingFrom ( Vertex* from ); - Edge* getBestHEdgeOut ( DbU::Unit yDest ); - Edge* getBestVEdgeOut ( DbU::Unit xDest ); - Edge* getBestHEdgeIn ( DbU::Unit yDest ); - Edge* getBestVEdgeIn ( DbU::Unit xDest ); + static const Name& staticGetName () { return _extensionName; }; + virtual const Name& getName () const { return _extensionName; }; + Edge* getHEdgeOut () const { return _firstEdges[0]; }; + Edge* getVEdgeOut () const { return _firstEdges[1]; }; + Edge* getHEdgeIn () const { return _firstEdges[2]; }; + Edge* getVEdgeIn () const { return _firstEdges[3]; }; + Edges getAdjacentEdges () const; + Edge* getPredecessor () const { return _predecessor; }; + Contact* getContact () const { return _contact; }; + int getConnexID () const { return _connexID; }; + float getDistance () const { return _distance; }; + unsigned getNetStamp () const { return _netStamp; }; + Point getPosition () const { return _position; }; + VTuple* getVTuple () const { return _vtuple; }; + Graph* getRoutingGraph () const { return _routingGraph; }; + DbU::Unit getX () const { return _position.getX(); }; + DbU::Unit getY () const { return _position.getY(); }; + DbU::Unit getXMin () const { return _position.getX() - _halfWidth; }; + DbU::Unit getYMin () const { return _position.getY() - _halfHeight; }; + DbU::Unit getXMax () const { return _position.getX() + _halfWidth; }; + DbU::Unit getYMax () const { return _position.getY() + _halfHeight; }; + DbU::Unit getHalfWidth () const { return _halfWidth; }; + DbU::Unit getHalfHeight () const { return _halfHeight; }; + Box getBox () const { return Box(getXMin(),getYMin(),getXMax(),getYMax()); }; + Edge* getFirstEdges ( int i ) const { return _firstEdges[i]; }; + Contact* getContact ( Edge* arrivalEdge ); + Edge* getHEdgeLeadingTo ( Vertex* to ); + Edge* getVEdgeLeadingTo ( Vertex* to ); + Edge* getHEdgeComingFrom ( Vertex* from ); + Edge* getVEdgeComingFrom ( Vertex* from ); + Edge* getBestHEdgeOut ( DbU::Unit yDest ); + Edge* getBestVEdgeOut ( DbU::Unit xDest ); + Edge* getBestHEdgeIn ( DbU::Unit yDest ); + Edge* getBestVEdgeIn ( DbU::Unit xDest ); // Predicates // ********** public: + bool isBlocked () const { return _flags & Blocked; }; bool isVerticallyAligned ( Vertex* vertex ) { return ( getX() == vertex->getX() ); }; bool isHorizontallyAligned ( Vertex* vertex ) { return ( getY() == vertex->getY() ); }; - bool hasInfo() const; + bool hasInfo () const; // ExtensionGo methods // ************** public: - void translate ( const DbU::Unit& dx, const DbU::Unit& dy ); - Cell* getCell () const; - Box getBoundingBox() const { Box area ( getPosition() ); return area.inflate(DbU::lambda(1)); }; - - void invalidate ( bool propagateFlag ); + void translate ( const DbU::Unit& dx, const DbU::Unit& dy ); + Cell* getCell () const; + Box getBoundingBox () const { Box area ( getPosition() ); return area.inflate(DbU::lambda(1)); }; + void invalidate ( bool propagateFlag ); // Others // ****** diff --git a/stratus1/src/stratus/st_instance.py b/stratus1/src/stratus/st_instance.py index e0dbbd8b..983f862b 100644 --- a/stratus1/src/stratus/st_instance.py +++ b/stratus1/src/stratus/st_instance.py @@ -322,7 +322,7 @@ class Inst : plug.setNet ( hurNet ) # In order to see the ring - if str ( realNet.__class__ ) not in ALIM_NET : CRL.createPartRing ( self._st_cell._hur_cell, hurNet.getName() ) + #if str ( realNet.__class__ ) not in ALIM_NET : CRL.createPartRing ( self._st_cell._hur_cell, hurNet.getName() ) ##### Loop on each pin for pin in self._map : diff --git a/stratus1/src/stratus/st_placement.py b/stratus1/src/stratus/st_placement.py index 3a861da1..09f630c7 100644 --- a/stratus1/src/stratus/st_placement.py +++ b/stratus1/src/stratus/st_placement.py @@ -49,9 +49,13 @@ from Hurricane import * - +from st_net import * from util_Place import * +global nbCkBuf +nbCkBuf = 0 + + ########### def Place ( ins, sym, ref, plac = FIXED, cell = None ) : global MYPITCH, MYSLICE @@ -535,3 +539,63 @@ def gauche ( sym ) : def droite ( sym ) : return sym == Transformation.Orientation.R2 or sym == Transformation.Orientation.MX or sym == Transformation.Orientation.R1 or sym == Transformation.Orientation.XR + + +################# +## ClockBuffer ## +################# +class ClockBuffer : + def __init__ ( self, netname ) : + global CELLS + from st_model import CELLS + global nbCkBuf + self.cell = CELLS[-1] + + self.net = self.cell._hur_cell.getNet ( netname ) + self.ck_b = Signal ( "ck_b%d"%nbCkBuf, 1 ) + + modelMasterCell = CRL.AllianceFramework.get().getCell ( "buf_x2", CRL.Catalog.State.Views ) + if not modelMasterCell : + err = "Stratus Error : ClockBuffer : Cannot find model cell : buf_x2 in database !\n" + raise Exception ( err ) + + inst = Instance.create ( self.cell._hur_cell, "ck_buffer%d"%nbCkBuf, modelMasterCell ) + nbCkBuf += 1 + + ##### Connection ##### + plugI = inst.getPlug ( modelMasterCell.getNet ( "i" ) ) + plugI.setNet ( self.net ) + + plugQ = inst.getPlug ( modelMasterCell.getNet ( "q" ) ) + plugQ.setNet ( self.ck_b._hur_net[0] ) + + plugGround = inst.getPlug ( iter(modelMasterCell.getGroundNets()).next() ) + plugGround.setNet ( iter(self.cell._hur_cell.getGroundNets()).next() ) + + plugPower = inst.getPlug ( iter(modelMasterCell.getPowerNets()).next() ) + plugPower.setNet ( iter(self.cell._hur_cell.getPowerNets()).next() ) + + def AddFF ( self, netname ) : + net = self.cell._hur_cell.getNet ( netname ) + if not net : + err = "AddFF Error net : " + netname + " not found" + raise Exception ( err ) + + instDrive = None + for plug in net.getPlugs(): + if plug.getMasterNet().getDirection() == Net.Direction.OUT : + instDrive = plug.getInstance() + break + + if instDrive == None : + err = "AddFF Error no drive instance found for net " + netname + ".\n" + raise Exception ( err ) + + masterCell = instDrive.getMasterCell() + ## ici il vaudrait mieux faire une recherche sur l'ensemble des plugs de l'instDrive et trouver celle accrochee au self.net ## + netCk = masterCell.getNet ( "ck" ) + if instDrive.getPlug ( netCk ).getNet() != self.net : + err = "Stratus Error : AddFF : driver Instance of net " + netname + " is not connected to signal " + str ( self.net.getName() ) + ".\n" + raise Exception ( err ) + + instDrive.getPlug ( netCk ).setNet ( self.ck_b._hur_net[0] ) diff --git a/stratus1/src/stratus/stratus.py b/stratus1/src/stratus/stratus.py index 1bb7316d..2f8ed701 100644 --- a/stratus1/src/stratus/stratus.py +++ b/stratus1/src/stratus/stratus.py @@ -73,7 +73,7 @@ DoStop = 0x0004 def buildModel ( name, flags ): try: - print name + #print name module = __import__( name, globals(), locals(), name ) if not module.__dict__.has_key(name): print '[ERROR] Stratus module <%s> do not contains a design of the same name.' % name diff --git a/unicorn/src/cgt.py b/unicorn/src/cgt.py index 3eff1b54..191976f0 100755 --- a/unicorn/src/cgt.py +++ b/unicorn/src/cgt.py @@ -57,25 +57,34 @@ def credits (): def runScript ( scriptPath, editor ): - try: - script = __import__(scriptPath) - except Exception, e: + try: + kw = { 'editor':editor } + sys.path.append(os.path.dirname(scriptPath)) + + module = __import__( os.path.basename(scriptPath), globals(), locals() ) + if not module.__dict__.has_key('ScriptMain'): + print '[ERROR] Script module is missing function ScriptMain().' + print ' <%s>' % scriptPath + return + if not callable( module.__dict__['ScriptMain'] ): + print '[ERROR] Script module symbol ScriptMain is not callable (not a function?).' + print ' <%s>' % scriptPath + return + + module.__dict__['ScriptMain']( **kw ) + + except ImportError, e: + module = str(e).split()[-1] + print '[ERROR] The <%s> script cannot be loaded.' % module + print ' Please check your design hierarchy.' + except Exception, e: print '[ERROR] An exception occured while loading the Stratus script module:' print ' <%s>\n' % (scriptPath) print ' You should check for simple python errors in this module.' print ' Error was:' print ' %s\n' % e print ' Trying to continue anyway...' - return - - if not hasattr(script,'ScriptMain'): - print '[ERROR] Script module is missing function ScriptMain().' - print ' <%s>' % scriptPath - return - - script.ScriptMain(editor) - - return + return if __name__ == '__main__': diff --git a/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h b/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h index 6e6884ce..a9cbf95a 100644 --- a/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h +++ b/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h @@ -64,7 +64,7 @@ namespace Utilities { inline void Dots::_flush ( char c ) { - _ostream.put( c ); + _ostream << c; _ostream.flush(); }