Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled vertexes in the grid (must not be used by the global router). Modificate the Graph::getVertex() method so that when a vertex is geometrically queried, if is a blocked one, return a non-blocked neighbor. This mechanism is introduced to, at last, prevent the global router to go *under* the pad in case of a commplete chip. * New: In Katabatic, in AutoSegment, a new state has been added: "reduced". A reduced segment is in the same layer as it's perpandiculars. To be reduced, a segments has to be connected on source & target to AutoContactTurn, both of the perpandiculars must be of the same layer (below or above) and it's length must not exceed one pitch in the perpandicular direction. To reduce an AutoSegment, call ::reduce() and to revert the state, call ::raise(). Two associated predicates are associated: ::canReduce() and ::mustRaise(). Note: No two adjacent segments can be reduced at the same time. * Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad() to connect to the pads. Create wiring, fixed and non managed by Katabatic, to connect the pad connector layer to the lowest routing layers (depth 1 & 2). The former implementation was sometimes leading to gaps (sheared contact) that *must not* occurs during the building stage. Remark: This bug did put under the light the fact that the initial wiring must be created without gaps. Gaps are closed by making doglegs on contacts. But this mechanism could only work when the database if fully initialised (the cache is up to date). Otherwise various problems arise, in the canonization process for example. * New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(), when anchored on a RoutingPad, now take account the potential rotation of the Path's transformation. Here again, for the chip's pads. * New: In Kite, support for reduced AutoSegment. TrackSegment associateds to reduced AutoSegment are *not* inserted into track to become effectively invisibles. When a segment becomes reduced, a TrackEvent is generated to remove it. Conversely when it is raised a RoutingEvent is created/rescheduled to insert it. All this is mostly managed inside the Session::revalidate() method. * New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip, mark all global routing vertexes (Knik) that are under a pad, as blockeds. * Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and Y coordinate of the chip size. Did not show until a non-square chip was routed (i.e. our MIPS R3000). * Change: In Stratus1, in st_placement.py add the ClockBuffer class for backward compatibility with the MIPS32 bench. Have to review this functionnality coming from the deprecated placeAndroute.py. In st_instance.py, no longer creates the Plug ring of a Net. In my opinion it just clutter the display until the P&R is called. Can re-enable later as an option (in Unicorn). * Change: In Unicorn, in cgt.py, more reliable way of loading then running user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
This commit is contained in:
parent
8ead28d86c
commit
ed557d9027
|
@ -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')
|
||||
|
|
|
@ -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 <climits>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include "hurricane/Commons.h"
|
||||
|
@ -49,6 +49,9 @@ namespace CRL {
|
|||
// Class : "RoutingGauge".
|
||||
|
||||
|
||||
const size_t RoutingGauge::nlayerdepth = std::numeric_limits<size_t>::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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -273,6 +273,7 @@ inline std::string tty::bgcolor ( unsigned int mask )
|
|||
template<typename T> inline mstream& operator<< ( T* t );
|
||||
template<typename T> inline mstream& operator<< ( const T& t );
|
||||
template<typename T> 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<std::ostream*>(this)->put(c); return *this; }
|
||||
inline mstream& mstream::flush () { if (enabled()) static_cast<std::ostream*>(this)->flush(); return *this; }
|
||||
inline mstream& mstream::operator<< ( std::ostream& (*pf)(std::ostream&) ) { if (enabled()) (*pf)(*this); return *this; }
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:'
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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.
|
||||
* <li><b>Reduction/Raising.</b> When a segment is a short dogleg,
|
||||
* no greater than one picth, it can use the layer of the
|
||||
* perpandiculars.
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
|
@ -97,6 +100,8 @@
|
|||
* <li>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.
|
||||
* <li>A small counter, of the number of reduced neighbors (never
|
||||
* exceed two).
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
|
@ -197,6 +202,10 @@
|
|||
//! \var AutoSegmentFlag::SegTargetBottom
|
||||
//! The target contact of this segment is connected to the <em>bottom</em> layer.
|
||||
|
||||
//! \var AutoSegmentFlag::SegIsReduced
|
||||
//! This segment is the perpandicular part of a dogleg which will use the
|
||||
//! <em>same</em> 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 <em>spin top</em> or <em>spin bottom</em>
|
||||
//! (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 <em>spin top</em> or <em>spin bottom</em>, 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 <em>spin top</em> or <em>spin bottom</em>.
|
||||
//! - 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 <em>spin top</em> or <em>spin bottom</em>, 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 <em>spin top</em> and \c id:12 is <em>spin bottom</em>.
|
||||
//!
|
||||
//! 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 <em>same layer</em> 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.
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Horizontal*>(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<Vertical*>(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<RoutingPad*>(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<Horizontal*>(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<Horizontal*>(entity)) {
|
||||
// rpOrient *is* the rotation.
|
||||
} else if ( dynamic_cast<Vertical*>(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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -91,6 +91,10 @@ namespace Katabatic {
|
|||
}
|
||||
|
||||
|
||||
AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* ) const
|
||||
{ return NULL; }
|
||||
|
||||
|
||||
AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const
|
||||
{
|
||||
switch ( index ) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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<RoutingPad*>(_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<RoutingPad*>(_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);
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
#ifndef KATABATIC_AUTOCONTACT_H
|
||||
#define KATABATIC_AUTOCONTACT_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "hurricane/Contact.h"
|
||||
#include "hurricane/ExtensionGo.h"
|
||||
#include "katabatic/Constants.h"
|
||||
#include "katabatic/AutoSegment.h"
|
||||
#include "katabatic/GCell.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#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);
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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* );
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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()); }
|
||||
|
|
|
@ -17,17 +17,17 @@
|
|||
#ifndef KATABATIC_SESSION_H
|
||||
#define KATABATIC_SESSION_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <boost/function.hpp>
|
||||
#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 <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <boost/function.hpp>
|
||||
#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;
|
||||
|
|
|
@ -56,17 +56,23 @@
|
|||
* - Process all insert events. <b>This is the time TrackSegment
|
||||
* are moved into their new Track (physical displacement)</b>.
|
||||
* 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.
|
||||
*
|
||||
* <b>Note:</b> We cannot use the Observer mechanism to automatically
|
||||
* update TrackSegment from an AutoSegment, because we must wait for all
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,6 +42,14 @@
|
|||
* - Now that the Hurricane database is deterministic, the router
|
||||
* seems to be likewise.
|
||||
*
|
||||
* - <b>Reduce/raise mechanism</b>. To manage <em>same layer</em> 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 <em>invisible</em>.
|
||||
* 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
|
||||
*
|
||||
|
|
|
@ -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() ) {
|
||||
|
|
|
@ -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<TrackElement*> unrouteds;
|
||||
vector<TrackElement*> 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; i<reduceds.size() ; ++i ) {
|
||||
// cerr << " " << dec << setw(4) << (i+1) << "| " << reduceds[i] << endl;
|
||||
// }
|
||||
// }
|
||||
|
||||
result << setprecision(4) << segmentRatio
|
||||
<< "% [" << routeds << "+" << unrouteds.size() << "]";
|
||||
cmess1 << Dots::asString( " - Track Segment Completion Ratio", result.str() ) << endl;
|
||||
|
|
|
@ -514,6 +514,7 @@ namespace Kite {
|
|||
_kite->setFixedPreRouted();
|
||||
}
|
||||
|
||||
Session::revalidate();
|
||||
Session::get()->isEmpty();
|
||||
|
||||
# if defined(CHECK_DATABASE)
|
||||
|
|
|
@ -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<Segment*> segments;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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++ );
|
||||
|
|
|
@ -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<Track*> packTracks;
|
||||
|
||||
for ( size_t i=0 ; i<_removeEvents.size() ; ++i ) {
|
||||
|
@ -152,6 +149,15 @@ namespace Kite {
|
|||
|
||||
for ( set<Track*>::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<Track*>::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 ; i<revalidateds.size() ; ++i ) {
|
||||
if (revalidateds[i]->canReduce()) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ()
|
||||
{ }
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
#ifndef KITE_ROUTING_EVENT_H
|
||||
#define KITE_ROUTING_EVENT_H
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
|
||||
#include "hurricane/Interval.h"
|
||||
namespace Hurricane {
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -381,7 +381,23 @@ Vertex* MatrixVertex::getVertex ( Point point )
|
|||
// ********************************************
|
||||
{
|
||||
pair<unsigned int,unsigned int> 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 )
|
||||
|
|
|
@ -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
|
||||
// ******
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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] )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__':
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace Utilities {
|
|||
|
||||
inline void Dots::_flush ( char c )
|
||||
{
|
||||
_ostream.put( c );
|
||||
_ostream << c;
|
||||
_ostream.flush();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue