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:
Jean-Paul Chaput 2015-08-16 23:29:28 +02:00
parent 8ead28d86c
commit ed557d9027
55 changed files with 1131 additions and 332 deletions

View File

@ -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')

View File

@ -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;
}

View File

@ -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 ();

View File

@ -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; }

View File

@ -1,15 +1,14 @@
// -*- 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" |
// +-----------------------------------------------------------------+
@ -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();

View File

@ -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:'

View File

@ -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]

View File

@ -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).

View File

@ -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.
}

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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();
Transformation transf = routingPad->getOccurrence().getPath().getTransformation();
ltrace(110) << "Anchor: " << routingPad << endl;
// Assumes there is no rotation in the Transformation.
if ( dynamic_cast<Horizontal*>(entity) ) {
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) ) {
// rpOrient is the inverse rotation.
rpOrient = (rpOrient == 1) ? 2 : 1;
} else {
rpOrient = 0;
}
switch ( rpOrient ) {
case 1:
xMin = routingPad->getSourcePosition().getX();
xMax = routingPad->getTargetPosition().getX();
yMin = yMax
= routingPad->getTargetPosition().getY();
} else if ( dynamic_cast<Vertical*>(entity) ) {
break;
case 2:
yMin = routingPad->getSourcePosition().getY();
yMax = routingPad->getTargetPosition().getY();
xMin = xMax
= routingPad->getTargetPosition().getX();
} else {
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 );
}

View File

@ -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 ) {

View File

@ -91,6 +91,10 @@ namespace Katabatic {
}
AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const
{
switch ( index ) {

View File

@ -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();

View File

@ -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;

View File

@ -256,9 +256,11 @@ namespace Katabatic {
ltrace(90) << "Saving AutoContacts/AutoSegments." << endl;
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 );

View File

@ -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,7 +1416,9 @@ namespace {
{
ltrace(99) << "_do_xG_1Pad() [Managed Configuration - Optimized] " << _topology << endl;
ltracein(99);
ltrace(99) << "_connexity.globals:" << _connexity.fields.globals << endl;
unsigned int flags = NoFlags;
bool eastPad = false;
bool westPad = false;
bool northPad = false;
@ -1245,47 +1427,57 @@ namespace {
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);

View File

@ -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);
}

View File

@ -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 ();

View File

@ -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* );

View File

@ -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 ();

View File

@ -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 ();

View File

@ -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,42 +61,43 @@ 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
, 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()); }

View File

@ -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

View File

@ -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

View File

@ -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
*

View File

@ -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() ) {

View File

@ -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;

View File

@ -514,6 +514,7 @@ namespace Kite {
_kite->setFixedPreRouted();
}
Session::revalidate();
Session::get()->isEmpty();
# if defined(CHECK_DATABASE)

View File

@ -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;

View File

@ -476,6 +476,7 @@ namespace Kite {
_axisHistory = _segment->getAxis();
_eventLevel = 0;
ltrace(500) << "Deter| addInsertEvent() @" << fsm.getCost(itrack).getTrack() << endl;
if (not _segment->isReduced())
Session::addInsertEvent( _segment, fsm.getCost(itrack).getTrack() );
fsm.setState( SegmentFsm::SelfInserted );
} else {

View File

@ -452,14 +452,14 @@ namespace Kite {
, _optimal ()
, _costs ()
, _actions ()
, _fullBlocked (true)
, _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) );
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()) );
_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++ );

View File

@ -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"
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;
}

View File

@ -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 ()
{ }

View File

@ -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; }

View File

@ -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 |
@ -121,11 +120,12 @@ namespace Kite {
_targetU = min( boundingBox.getYMax(), uside.getVMax());
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() );
if (gcell) {
while ( gcell and (gcell != end) ) {
up = gcell->getUp();
if (up == NULL) break;

View File

@ -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.

View File

@ -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 ();

View File

@ -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

View File

@ -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;

View File

@ -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 ();

View File

@ -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()

View File

@ -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 )

View File

@ -19,6 +19,7 @@ namespace Knik {
// *****
public:
typedef ExtensionGo Inherit;
enum Flags { Blocked=0x0001 };
//enum EdgeDirection { EAST=0, NORTH=1, WEST=2, SOUTH=3, UNDEFINED=4 };
// Attributes
@ -37,6 +38,7 @@ namespace Knik {
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,6 +67,8 @@ namespace Knik {
void setVTuple ( VTuple* vtuple ) { _vtuple = vtuple; };
void attachToLocalRing ( Component* component );
void sortEdges ();
void setBlocked () { _flags |= Blocked; }
void resetBlocked () { _flags &= ~Blocked; }
// Accessors
// *********
@ -107,17 +111,17 @@ namespace Knik {
// 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)); };
Box getBoundingBox () const { Box area ( getPosition() ); return area.inflate(DbU::lambda(1)); };
void invalidate ( bool propagateFlag );
// Others

View File

@ -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 :

View File

@ -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] )

View File

@ -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

View File

@ -58,7 +58,25 @@ def credits ():
def runScript ( scriptPath, editor ):
try:
script = __import__(scriptPath)
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)
@ -68,15 +86,6 @@ def runScript ( scriptPath, editor ):
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
if __name__ == '__main__':

View File

@ -64,7 +64,7 @@ namespace Utilities {
inline void Dots::_flush ( char c )
{
_ostream.put( c );
_ostream << c;
_ostream.flush();
}