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 00000000..60749cee Binary files /dev/null and b/katabatic/doc/images/reduce-1.pdf differ diff --git a/katabatic/doc/images/reduce-1.png b/katabatic/doc/images/reduce-1.png new file mode 100644 index 00000000..6b5f757e Binary files /dev/null and b/katabatic/doc/images/reduce-1.png differ diff --git a/katabatic/src/AutoContact.cpp b/katabatic/src/AutoContact.cpp index fd8cf99e..665d5adc 100644 --- a/katabatic/src/AutoContact.cpp +++ b/katabatic/src/AutoContact.cpp @@ -180,6 +180,10 @@ namespace Katabatic { { return new AutoSegments_CachedOnContact(this); } + AutoSegment* AutoContact::getPerpandicular ( const AutoSegment* ) const + { return NULL; } + + unsigned int AutoContact::getMinDepth () const { size_t minDepth = (size_t)-1; diff --git a/katabatic/src/AutoContactHTee.cpp b/katabatic/src/AutoContactHTee.cpp index a10959a7..27625c37 100644 --- a/katabatic/src/AutoContactHTee.cpp +++ b/katabatic/src/AutoContactHTee.cpp @@ -91,6 +91,10 @@ namespace Katabatic { } + AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* ) const + { return NULL; } + + AutoSegment* AutoContactHTee::getSegment ( unsigned int index ) const { AutoSegment* segment = NULL; @@ -122,12 +126,25 @@ namespace Katabatic { void AutoContactHTee::cacheDetach ( AutoSegment* segment ) { - ltrace(110) << _getTypeName() << "::_cacheDetach() " << this << endl; + ltrace(110) << _getTypeName() << "::cacheDetach() " << this << endl; + ltrace(110) << "| h1:" << _horizontal1 << endl; + ltrace(110) << "| h2:" << _horizontal2 << endl; + ltrace(110) << "| v1:" << _vertical1 << endl; if (segment == _horizontal1) _horizontal1 = NULL; else if (segment == _horizontal2) _horizontal2 = NULL; else if (segment == _vertical1) _vertical1 = NULL; - else return; + else { + if (_horizontal1 or _horizontal2 or _vertical1) + cerr << Bug( "%s::cacheDetach() On %s,\n" + " Cannot detach %s\n" + " because it *not* attached to this contact." + , _getTypeName().c_str() + , getString(this).c_str() + , getString(segment).c_str() + ) << endl; + return; + } setFlags( CntInvalidatedCache ); } @@ -165,6 +182,10 @@ namespace Katabatic { if (_horizontal1 and _horizontal2 and _vertical1) unsetFlags( CntInvalidatedCache ); + ltrace(110) << "| h1:" << _horizontal1 << endl; + ltrace(110) << "| h2:" << _horizontal2 << endl; + ltrace(110) << "| v1:" << _vertical1 << endl; + ltraceout(110); } diff --git a/katabatic/src/AutoContactTerminal.cpp b/katabatic/src/AutoContactTerminal.cpp index c693fa88..c76b4668 100644 --- a/katabatic/src/AutoContactTerminal.cpp +++ b/katabatic/src/AutoContactTerminal.cpp @@ -44,6 +44,7 @@ namespace Katabatic { using Hurricane::Bug; using Hurricane::Error; using Hurricane::DebugSession; + using Hurricane::Transformation; using Hurricane::Entity; using Hurricane::ltracein; using Hurricane::ltraceout; @@ -125,6 +126,10 @@ namespace Katabatic { { return NULL; } + AutoSegment* AutoContactTerminal::getPerpandicular ( const AutoSegment* ) const + { return NULL; } + + AutoSegment* AutoContactTerminal::getSegment ( unsigned int index ) const { if (_segment) { @@ -139,9 +144,13 @@ namespace Katabatic { Box AutoContactTerminal::getNativeConstraintBox () const { + ltrace(110) << "AutoContactTerminal::getNativeConstraintBox()" << endl; + ltracein(110); + Component* component = getAnchor(); if (component == NULL) { cerr << Error( "%s is not anchored.", getString(this).c_str() ) << endl; + ltraceout(110); return _gcell->getBoundingBox (); } @@ -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(); }