2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
2013-12-03 18:58:58 -06:00
|
|
|
// Copyright (c) UPMC 2008-2013, All Rights Reserved
|
2010-03-09 09:24:29 -06:00
|
|
|
//
|
2012-12-03 02:28:43 -06:00
|
|
|
// +-----------------------------------------------------------------+
|
2010-03-09 09:24:29 -06:00
|
|
|
// | C O R I O L I S |
|
|
|
|
// | K a t a b a t i c - Routing Toolbox |
|
|
|
|
// | |
|
|
|
|
// | Author : Jean-Paul CHAPUT |
|
2013-12-03 18:58:58 -06:00
|
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
2010-03-09 09:24:29 -06:00
|
|
|
// | =============================================================== |
|
|
|
|
// | C++ Module : "./GCell.cpp" |
|
2012-12-03 02:28:43 -06:00
|
|
|
// +-----------------------------------------------------------------+
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <iomanip>
|
|
|
|
#include <sstream>
|
|
|
|
#include <functional>
|
|
|
|
|
|
|
|
#include "hurricane/Bug.h"
|
|
|
|
#include "hurricane/Warning.h"
|
|
|
|
#include "hurricane/Layer.h"
|
|
|
|
#include "hurricane/Horizontal.h"
|
|
|
|
#include "hurricane/Vertical.h"
|
2010-04-12 06:22:11 -05:00
|
|
|
#include "hurricane/RoutingPad.h"
|
2010-03-09 09:24:29 -06:00
|
|
|
#include "crlcore/RoutingGauge.h"
|
|
|
|
#include "katabatic/AutoContact.h"
|
|
|
|
#include "katabatic/AutoSegment.h"
|
|
|
|
#include "katabatic/GCell.h"
|
|
|
|
#include "katabatic/GCellGrid.h"
|
|
|
|
#include "katabatic/Session.h"
|
* ./katabatic:
- New: ChipTools, regroup all datas and utilities to manage a full-chip
design.
- Change: In LoadGrByNet/GCellConfiguration::_GCell_xG_1Pad(), uses straight
perpandicular wires on top & right pads. The GCells under those connectors
are fully saturated, wires must go out as straight as possible.
- Change: In AutoHorizontal/AutoVertical, update the "terminal" flag after
slackening. This is to avoid global that are no longer connected to
terminals behave as such.
- Change: In AutoSegment::canMoveUp() & canPivotUp(), prevent all local segments
to go up. This is to avoid cluttering upper levels with small segments.
- Change: In GCellConfiguration, for xG_xL3, detect straight vertical topologies
and for them to be fixed (new flag FIXED_GLOBAL set by the topological
builder instead of the constructor). This prevent the router to do
stupid things...
To sets the "Fixed" flag *after* the axis of global segments have been
positionned correctly adds a "_toFixGlobals" static table lookup.
- Change: In GCell::stepDesaturate(), if less than one free track remains in
the upper layer, do not move up the segment. This allows from a minimum
free room for expansion.
- Change: In GCell::_getString(), display indexes and layer names in various
saturation tables.
- Change: In AutoSegment, allow move up of local Segment. ::moveUp() and
::canMoveUp() arguments go from booleans to flags, which are more
explicits.
2010-12-04 09:25:18 -06:00
|
|
|
#include "katabatic/KatabaticEngine.h"
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace Hurricane;
|
|
|
|
using namespace Katabatic;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "::UsedFragments".
|
|
|
|
|
|
|
|
|
|
|
|
class UsedFragments {
|
|
|
|
private:
|
|
|
|
class Axiss;
|
|
|
|
|
|
|
|
class Axis {
|
|
|
|
public:
|
|
|
|
Axis ( UsedFragments*, DbU::Unit axis );
|
|
|
|
inline DbU::Unit getAxis () const;
|
|
|
|
inline UsedFragments* getUsedFragments () const;
|
|
|
|
void merge ( const Interval& mergeChunk );
|
|
|
|
Interval getMaxFree () const;
|
|
|
|
private:
|
|
|
|
UsedFragments* _ufragments;
|
|
|
|
DbU::Unit _axis;
|
|
|
|
list<Interval> _chunks;
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
class AxisCompare {
|
|
|
|
public:
|
|
|
|
bool operator() ( const Axis* lhs, const Axis* rhs );
|
|
|
|
};
|
|
|
|
|
|
|
|
class AxisMatch : public unary_function<Axis*,bool> {
|
|
|
|
public:
|
|
|
|
inline AxisMatch ( DbU::Unit axis );
|
|
|
|
inline bool operator() ( const Axis* );
|
|
|
|
private:
|
|
|
|
DbU::Unit _axis;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
UsedFragments ();
|
|
|
|
~UsedFragments ();
|
|
|
|
inline DbU::Unit getMin () const;
|
|
|
|
inline DbU::Unit getMax () const;
|
|
|
|
Interval getMaxFree () const;
|
|
|
|
inline void setSpan ( DbU::Unit min, DbU::Unit max );
|
|
|
|
inline void setCapacity ( size_t );
|
|
|
|
inline void incGlobals ( size_t count=1 );
|
|
|
|
void merge ( DbU::Unit axis, const Interval& );
|
|
|
|
private:
|
|
|
|
vector<Axis*> _axiss;
|
2011-01-25 11:16:27 -06:00
|
|
|
Interval _span;
|
2011-01-09 12:08:31 -06:00
|
|
|
size_t _capacity;
|
|
|
|
size_t _globals;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
UsedFragments::Axis::Axis ( UsedFragments* ufragments, DbU::Unit axis )
|
|
|
|
: _ufragments(ufragments)
|
|
|
|
, _axis (axis)
|
|
|
|
, _chunks ()
|
|
|
|
{
|
|
|
|
merge ( Interval ( ufragments->getMin()-DbU::lambda(5.0), ufragments->getMin() ) );
|
|
|
|
merge ( Interval ( ufragments->getMax(), ufragments->getMax()+DbU::lambda(5.0) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
inline DbU::Unit UsedFragments::Axis::getAxis () const { return _axis; }
|
|
|
|
inline UsedFragments* UsedFragments::Axis::getUsedFragments () const { return _ufragments; }
|
|
|
|
|
|
|
|
|
|
|
|
void UsedFragments::Axis::merge ( const Interval& chunkMerge )
|
|
|
|
{
|
2011-01-25 11:16:27 -06:00
|
|
|
// cerr << " Merge @" << DbU::getValueString(_axis)
|
|
|
|
// << " " << chunkMerge << endl;
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
list<Interval>::iterator imerge = _chunks.end();
|
|
|
|
list<Interval>::iterator ichunk = _chunks.begin();
|
|
|
|
|
|
|
|
while ( ichunk != _chunks.end() ) {
|
|
|
|
if ( chunkMerge.getVMax() < (*ichunk).getVMin() ) break;
|
|
|
|
|
|
|
|
if ( chunkMerge.intersect(*ichunk) ) {
|
|
|
|
if ( imerge == _chunks.end() ) {
|
|
|
|
imerge = ichunk;
|
|
|
|
(*imerge).merge ( chunkMerge );
|
|
|
|
} else {
|
|
|
|
(*imerge).merge ( *ichunk );
|
|
|
|
ichunk = _chunks.erase ( ichunk );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ichunk++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( imerge == _chunks.end() ) {
|
|
|
|
_chunks.insert ( ichunk, chunkMerge );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Interval UsedFragments::Axis::getMaxFree () const
|
|
|
|
{
|
|
|
|
list<Interval>::const_iterator ichunk = _chunks.begin();
|
|
|
|
list<Interval>::const_iterator iend = --_chunks.end();
|
|
|
|
|
|
|
|
Interval maxFree;
|
|
|
|
for ( ; ichunk != iend ; ++ichunk ) {
|
|
|
|
list<Interval>::const_iterator inext = ichunk;
|
|
|
|
++inext;
|
|
|
|
|
2011-01-25 11:16:27 -06:00
|
|
|
if ( inext == iend ) break;
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
Interval currentFree ( (*ichunk).getVMax(), (*inext).getVMin() );
|
|
|
|
if ( currentFree.getSize() > maxFree.getSize() )
|
|
|
|
maxFree = currentFree;
|
2011-01-25 11:16:27 -06:00
|
|
|
|
|
|
|
// cerr << " @" << DbU::getValueString(_axis)
|
|
|
|
// << " before:" << *ichunk << " after:" << *inext
|
|
|
|
// << " size:" << DbU::getValueString(currentFree.getSize()) << endl;
|
2011-01-09 12:08:31 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return maxFree;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline bool UsedFragments::AxisCompare::operator() ( const Axis* lhs, const Axis* rhs )
|
|
|
|
{
|
|
|
|
if ( lhs->getAxis () < rhs->getAxis () ) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline UsedFragments::AxisMatch::AxisMatch ( DbU::Unit axis )
|
|
|
|
: _axis(axis)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
inline bool UsedFragments::AxisMatch::operator() ( const Axis* axis )
|
|
|
|
{ return (axis->getAxis() == _axis); }
|
|
|
|
|
|
|
|
|
|
|
|
UsedFragments::UsedFragments ()
|
|
|
|
: _axiss ()
|
2011-01-25 11:16:27 -06:00
|
|
|
, _span (false)
|
2011-01-09 12:08:31 -06:00
|
|
|
, _capacity(0)
|
|
|
|
, _globals (0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
UsedFragments::~UsedFragments ()
|
|
|
|
{
|
|
|
|
while ( not _axiss.empty() ) {
|
|
|
|
delete (*_axiss.begin());
|
|
|
|
_axiss.erase ( _axiss.begin() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-25 11:16:27 -06:00
|
|
|
inline DbU::Unit UsedFragments::getMin () const { return _span.getVMin(); }
|
|
|
|
inline DbU::Unit UsedFragments::getMax () const { return _span.getVMax(); }
|
|
|
|
inline void UsedFragments::setSpan ( DbU::Unit min, DbU::Unit max ) { _span=Interval(min,max); }
|
2011-01-09 12:08:31 -06:00
|
|
|
inline void UsedFragments::setCapacity ( size_t capacity ) { _capacity=capacity; }
|
|
|
|
inline void UsedFragments::incGlobals ( size_t count ) { _globals+=count; }
|
|
|
|
|
|
|
|
|
|
|
|
void UsedFragments::merge ( DbU::Unit axis, const Interval& chunkMerge )
|
|
|
|
{
|
2011-01-25 11:16:27 -06:00
|
|
|
Interval restrict = chunkMerge.getIntersection(_span);
|
|
|
|
if ( restrict.isEmpty() ) return;
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
vector<Axis*>::iterator iaxis = find_if ( _axiss.begin(), _axiss.end(), AxisMatch(axis) );
|
|
|
|
|
|
|
|
Axis* paxis = NULL;
|
|
|
|
if ( iaxis == _axiss.end() ) {
|
|
|
|
paxis = new Axis(this,axis);
|
|
|
|
_axiss.push_back ( paxis );
|
|
|
|
stable_sort ( _axiss.begin(), _axiss.end(), AxisCompare() );
|
|
|
|
} else {
|
|
|
|
paxis = *iaxis;
|
|
|
|
}
|
|
|
|
|
2011-01-25 11:16:27 -06:00
|
|
|
paxis->merge ( restrict );
|
2011-01-09 12:08:31 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Interval UsedFragments::getMaxFree () const
|
|
|
|
{
|
2011-01-25 11:16:27 -06:00
|
|
|
//cerr << "capacity:" << _capacity << " _globals:" << _globals << " _axiss:" << _axiss.size() << endl;
|
|
|
|
if ( _capacity > _globals + _axiss.size() + 1 )
|
|
|
|
return _span;
|
2011-01-09 12:08:31 -06:00
|
|
|
|
|
|
|
Interval maxFree;
|
|
|
|
vector<Axis*>::const_iterator iaxis = _axiss.begin();
|
|
|
|
for ( ; iaxis != _axiss.end() ; ++iaxis ) {
|
|
|
|
Interval axisMaxFree = (*iaxis)->getMaxFree();
|
|
|
|
if ( axisMaxFree.getSize() > maxFree.getSize() )
|
|
|
|
maxFree = axisMaxFree;
|
|
|
|
}
|
|
|
|
|
|
|
|
return maxFree;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // End of anonymous namespace.
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
namespace Katabatic {
|
|
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using Hurricane::roundfp;
|
|
|
|
using Hurricane::tab;
|
|
|
|
using Hurricane::ltracein;
|
|
|
|
using Hurricane::ltraceout;
|
|
|
|
using Hurricane::inltrace;
|
|
|
|
using Hurricane::ForEachIterator;
|
|
|
|
using Hurricane::Warning;
|
|
|
|
using Hurricane::Bug;
|
|
|
|
using Hurricane::Horizontal;
|
|
|
|
using Hurricane::Vertical;
|
2011-01-09 12:08:31 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Katabatic::GCell::CompareByDensity".
|
|
|
|
|
|
|
|
|
2010-12-12 16:35:40 -06:00
|
|
|
GCell::CompareByDensity::CompareByDensity ( unsigned int depth )
|
2010-03-09 09:24:29 -06:00
|
|
|
: _depth(depth)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::CompareByDensity::operator() ( GCell* lhs, GCell* rhs )
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
//float difference = roundfp ( lhs->getDensity(_depth) - rhs->getDensity(_depth) );
|
|
|
|
float difference = lhs->getDensity(_depth) - rhs->getDensity(_depth);
|
|
|
|
if (difference != 0.0) return (difference > 0.0);
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
//int difference = floatCompare ( lhs->getDensity(_depth), rhs->getDensity(_depth) );
|
|
|
|
//if ( abs(difference) > 1000 ) return difference > 0;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
return lhs->getIndex() < rhs->getIndex();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-23 04:25:15 -05:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Kite::GCell::CompareByKey".
|
|
|
|
//
|
|
|
|
// lhs < rhs --> true
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::CompareByKey::operator() ( const GCell* lhs, const GCell* rhs )
|
|
|
|
{
|
|
|
|
return lhs->getKey() < rhs->getKey();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Katabatic::GCell".
|
|
|
|
|
|
|
|
|
|
|
|
const Name GCell::_goName = "Katabatic::GCell";
|
|
|
|
DbU::Unit GCell::_topRightShrink = 0;
|
|
|
|
size_t GCell::_allocateds = 0;
|
|
|
|
|
|
|
|
|
|
|
|
GCell::GCell ( GCellGrid* gcellGrid, unsigned int index, const Box& box )
|
|
|
|
: ExtensionGo (gcellGrid->getCell())
|
|
|
|
, _gcellGrid (gcellGrid)
|
|
|
|
, _index (index)
|
|
|
|
, _vsegments ()
|
|
|
|
, _hsegments ()
|
|
|
|
, _contacts ()
|
|
|
|
, _box (box)
|
|
|
|
, _depth (Session::getRoutingGauge()->getDepth())
|
|
|
|
, _pinDepth (0)
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
, _blockages (new DbU::Unit [_depth])
|
2010-03-09 09:24:29 -06:00
|
|
|
, _cDensity (0.0)
|
|
|
|
, _densities (new float [_depth])
|
2011-01-09 12:08:31 -06:00
|
|
|
, _feedthroughs (new float [_depth])
|
|
|
|
, _fragmentations (new float [_depth])
|
|
|
|
, _globalsCount (new float [_depth])
|
|
|
|
//, _blockedAxis (this)
|
|
|
|
//, _saturateDensities (new float [_depth])
|
2013-12-03 18:58:58 -06:00
|
|
|
, _flags (GCellInvalidated)
|
|
|
|
, _key (this,1)
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
_blockages [i] = 0;
|
2010-03-09 09:24:29 -06:00
|
|
|
_densities [i] = 0.0;
|
2011-01-09 12:08:31 -06:00
|
|
|
_feedthroughs [i] = 0.0;
|
|
|
|
_fragmentations [i] = 0.0;
|
|
|
|
_globalsCount [i] = 0.0;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
//_saturateDensities[i] = 0.0;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
if ( Session::getRoutingGauge()->getLayerGauge(i)->getType() == Constant::PinOnly )
|
|
|
|
++_pinDepth;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
updateKey(1);
|
2010-03-09 09:24:29 -06:00
|
|
|
_allocateds++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_postCreate ()
|
|
|
|
{
|
|
|
|
ltrace(90) << "GCell::_postCreate() - " << (void*)this << " " << this << endl;
|
|
|
|
ltracein(90);
|
|
|
|
|
|
|
|
ExtensionGo::_postCreate ();
|
|
|
|
|
|
|
|
ltraceout(90);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::create ( GCellGrid* gcellGrid, unsigned int index, Box box )
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (_topRightShrink == 0)
|
2010-03-09 09:24:29 -06:00
|
|
|
_topRightShrink = 1 /*DbU::lambda(0.0)*/;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
DbU::Unit trShrink = ( gcellGrid->isOnTopBorder (index)
|
|
|
|
or gcellGrid->isOnRightBorder(index)) ? 0 : _topRightShrink;
|
|
|
|
|
|
|
|
ltrace(90) << "Gcell::create()" << endl;
|
|
|
|
GCell* gcell = new GCell ( gcellGrid, index, box.inflate( 0 ,0 ,-trShrink ,-trShrink ) );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
gcell->_postCreate ();
|
|
|
|
|
|
|
|
return gcell;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell::~GCell ()
|
|
|
|
{
|
|
|
|
ltrace(90) << "GCell::~GCell()" << endl;
|
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
delete [] _blockages;
|
2010-03-09 09:24:29 -06:00
|
|
|
delete [] _densities;
|
2011-01-09 12:08:31 -06:00
|
|
|
delete [] _feedthroughs;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
//delete [] _saturateDensities;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
_allocateds--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_preDestroy ()
|
|
|
|
{
|
|
|
|
ltrace(90) << "GCell::_preDestroy() - " << (void*)this << " " << this << endl;
|
|
|
|
ExtensionGo::_preDestroy ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-12 16:35:40 -06:00
|
|
|
bool GCell::isSaturated ( unsigned int depth ) const
|
2010-03-09 09:24:29 -06:00
|
|
|
{ return getDensity(depth) > Session::getSaturateRatio(); }
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::isAboveDensity ( float threshold ) const
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isValid()) const_cast<GCell*>(this)->updateDensity();
|
2010-03-09 09:24:29 -06:00
|
|
|
float difference = roundfp ( getDensity() - threshold );
|
|
|
|
|
|
|
|
//int difference = floatDifference(getDensity(),threshold,10000);
|
|
|
|
ltrace(190) << "GCell:isAboveDensity() " << threshold << " diff:" << difference << endl;
|
* ./katabatic:
- Change: In loadGlobalRouting(), more exlicit message as to why a net is
filtered out the routing set (POWER, GROUND, CLOCK or BLOCKAGE).
- New: ChipTool, module with utilities specific to chip routing. Containing
a function to pre-break wires around a block.
- New: In loadGlobalRouting/GCellConfiguration, adds supports for RoutingPad
connected on chip's pad.
- New: In GCellGrid/GCell, can compute the density in three modes: average,
max of H/V and max of layer. Currently implemented in getMaxHVDensity(),
should be unificated with getDensity(). Used for display purposes.
- Bug: In AutoContact, when splitting a contact, add a specific check for
"one layer span".
- Bug: In AutoSegment::canMoveUp(), do not move up fixed segments.
2010-11-16 07:59:38 -06:00
|
|
|
return (difference >= 0.0);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::areDensityConnex ( GCell* a, GCell* b )
|
|
|
|
{
|
|
|
|
ltrace(190) << "GCell:areDensityConnex()" << endl;
|
|
|
|
|
|
|
|
for ( unsigned int i=1 ; i<a->getDepth() ; i++ ) { // Ugly: hard-coded skip METAL1.
|
|
|
|
//int highDiffa = floatDifference(a->_densities[i],0.6,10000);
|
|
|
|
//int highDiffb = floatDifference(b->_densities[i],0.6,10000);
|
|
|
|
|
|
|
|
float highDiffa = roundfp ( a->_densities[i] - 0.6 );
|
|
|
|
float highDiffb = roundfp ( b->_densities[i] - 0.6 );
|
|
|
|
ltrace(190) << "Compare depth " << i
|
|
|
|
<< " " << a->_densities[i] << "," << highDiffa
|
|
|
|
<< " & " << b->_densities[i] << "," << highDiffb << endl;
|
|
|
|
|
|
|
|
if ( (highDiffa > 0) and (highDiffb > 0) ) {
|
|
|
|
ltrace(190) << "GCell::areDensityConnex() Neighboring high saturated GCell (depth:" << i
|
|
|
|
<< " " << a->_densities[i] << " & " << b->_densities[i] << ")" << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::getDensities ( float* densities ) const
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isValid()) const_cast<GCell*>(this)->updateDensity();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
for ( unsigned int i=0 ; i<_depth ; i++ ) {
|
|
|
|
densities[i] = _densities[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const Name& GCell::getStaticName ()
|
|
|
|
{ return _goName; }
|
|
|
|
|
|
|
|
|
|
|
|
size_t GCell::getAllocateds ()
|
|
|
|
{ return _allocateds; }
|
|
|
|
|
|
|
|
|
|
|
|
DbU::Unit GCell::getTopRightShrink ()
|
|
|
|
{ return _topRightShrink; }
|
|
|
|
|
|
|
|
|
|
|
|
const Name& GCell::getName () const
|
|
|
|
{ return _goName; }
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int GCell::getRow () const
|
|
|
|
{ return _gcellGrid->getRow ( _index ); }
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int GCell::getColumn () const
|
|
|
|
{ return _gcellGrid->getColumn ( _index ); }
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getLeft () const
|
|
|
|
{ return getGCellGrid()->getGCellLeft(this); }
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getRight () const
|
|
|
|
{ return getGCellGrid()->getGCellRight(this); }
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getUp () const
|
|
|
|
{ return getGCellGrid()->getGCellUp(this); }
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getDown () const
|
|
|
|
{ return getGCellGrid()->getGCellDown(this); }
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
Interval GCell::getSide ( unsigned int direction ) const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
|
|
|
Interval side;
|
|
|
|
switch ( direction ) {
|
|
|
|
default:
|
2013-12-03 18:58:58 -06:00
|
|
|
case KbHorizontal: side = Interval(_box.getXMin(),_box.getXMax()); break;
|
|
|
|
case KbVertical: side = Interval(_box.getYMin(),_box.getYMax()); break;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
return side;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getHStartSegments ()
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
return new AutoSegments_AnchorOnGCell (this,KbHorizontal|KbBySource);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getVStartSegments ()
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
return new AutoSegments_AnchorOnGCell (this,KbVertical|KbBySource);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getHStopSegments ()
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
return new AutoSegments_AnchorOnGCell (this,KbHorizontal|KbByTarget);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getVStopSegments ()
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
return new AutoSegments_AnchorOnGCell (this,KbVertical|KbByTarget);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-12 06:22:11 -05:00
|
|
|
size_t GCell::getRoutingPads ( set<RoutingPad*>& rps )
|
|
|
|
{
|
|
|
|
for ( size_t i=0 ; i<_contacts.size() ; ++i ) {
|
|
|
|
RoutingPad* rp = dynamic_cast<RoutingPad*>(_contacts[i]->getAnchor());
|
|
|
|
if ( rp ) {
|
|
|
|
rps.insert ( rp );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rps.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
float GCell::getHCapacity () const
|
|
|
|
{
|
|
|
|
return (float)( _box.getHeight() / DbU::lambda(5.0) + 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float GCell::getVCapacity () const
|
|
|
|
{
|
|
|
|
return (float)( _box.getWidth () / DbU::lambda(5.0) + 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
float GCell::getDensity ( unsigned int flags ) const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isValid() and not(flags & NoUpdate)) const_cast<GCell*>(this)->updateDensity();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
float density = 0.0;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (getGCellGrid()->getDensityMode() == GCellGrid::AverageHVDensity) {
|
2010-12-12 15:43:25 -06:00
|
|
|
// Average density of all layers mixeds together.
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ )
|
|
|
|
density += _densities[i];
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
//density = roundfp ( density/((float)(_depth-_pinDepth)) );
|
|
|
|
density = density/((float)(_depth-_pinDepth));
|
|
|
|
} else if (getGCellGrid()->getDensityMode() == GCellGrid::MaxHVDensity) {
|
2010-12-12 15:43:25 -06:00
|
|
|
// Maximum density between all horizontal vs. all vertical layers.
|
* ./katabatic:
- Change: In loadGlobalRouting(), more exlicit message as to why a net is
filtered out the routing set (POWER, GROUND, CLOCK or BLOCKAGE).
- New: ChipTool, module with utilities specific to chip routing. Containing
a function to pre-break wires around a block.
- New: In loadGlobalRouting/GCellConfiguration, adds supports for RoutingPad
connected on chip's pad.
- New: In GCellGrid/GCell, can compute the density in three modes: average,
max of H/V and max of layer. Currently implemented in getMaxHVDensity(),
should be unificated with getDensity(). Used for display purposes.
- Bug: In AutoContact, when splitting a contact, add a specific check for
"one layer span".
- Bug: In AutoSegment::canMoveUp(), do not move up fixed segments.
2010-11-16 07:59:38 -06:00
|
|
|
size_t hplanes = 0;
|
|
|
|
size_t vplanes = 0;
|
|
|
|
float hdensity = 0.0;
|
|
|
|
float vdensity = 0.0;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- Change: In loadGlobalRouting(), more exlicit message as to why a net is
filtered out the routing set (POWER, GROUND, CLOCK or BLOCKAGE).
- New: ChipTool, module with utilities specific to chip routing. Containing
a function to pre-break wires around a block.
- New: In loadGlobalRouting/GCellConfiguration, adds supports for RoutingPad
connected on chip's pad.
- New: In GCellGrid/GCell, can compute the density in three modes: average,
max of H/V and max of layer. Currently implemented in getMaxHVDensity(),
should be unificated with getDensity(). Used for display purposes.
- Bug: In AutoContact, when splitting a contact, add a specific check for
"one layer span".
- Bug: In AutoSegment::canMoveUp(), do not move up fixed segments.
2010-11-16 07:59:38 -06:00
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
|
|
|
if ( i%2 ) { hdensity += _densities[i]; ++hplanes; }
|
|
|
|
else { vdensity += _densities[i]; ++vplanes; }
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hplanes) hdensity /= hplanes;
|
|
|
|
if (vplanes) vdensity /= vplanes;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
//density = roundfp ( (hdensity > vdensity) ? hdensity : vdensity );
|
|
|
|
density = (hdensity > vdensity) ? hdensity : vdensity;
|
|
|
|
} else if (getGCellGrid()->getDensityMode() == GCellGrid::AverageHDensity) {
|
2010-12-12 15:43:25 -06:00
|
|
|
// Average density between all horizontal layers.
|
|
|
|
size_t hplanes = 0;
|
|
|
|
float hdensity = 0.0;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- Change: In loadGlobalRouting(), more exlicit message as to why a net is
filtered out the routing set (POWER, GROUND, CLOCK or BLOCKAGE).
- New: ChipTool, module with utilities specific to chip routing. Containing
a function to pre-break wires around a block.
- New: In loadGlobalRouting/GCellConfiguration, adds supports for RoutingPad
connected on chip's pad.
- New: In GCellGrid/GCell, can compute the density in three modes: average,
max of H/V and max of layer. Currently implemented in getMaxHVDensity(),
should be unificated with getDensity(). Used for display purposes.
- Bug: In AutoContact, when splitting a contact, add a specific check for
"one layer span".
- Bug: In AutoSegment::canMoveUp(), do not move up fixed segments.
2010-11-16 07:59:38 -06:00
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
2010-12-12 15:43:25 -06:00
|
|
|
if ( i%2 ) { hdensity += _densities[i]; ++hplanes; }
|
* ./katabatic:
- Change: In loadGlobalRouting(), more exlicit message as to why a net is
filtered out the routing set (POWER, GROUND, CLOCK or BLOCKAGE).
- New: ChipTool, module with utilities specific to chip routing. Containing
a function to pre-break wires around a block.
- New: In loadGlobalRouting/GCellConfiguration, adds supports for RoutingPad
connected on chip's pad.
- New: In GCellGrid/GCell, can compute the density in three modes: average,
max of H/V and max of layer. Currently implemented in getMaxHVDensity(),
should be unificated with getDensity(). Used for display purposes.
- Bug: In AutoContact, when splitting a contact, add a specific check for
"one layer span".
- Bug: In AutoSegment::canMoveUp(), do not move up fixed segments.
2010-11-16 07:59:38 -06:00
|
|
|
}
|
2010-12-12 15:43:25 -06:00
|
|
|
if (hplanes) hdensity /= hplanes;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
//density = roundfp ( hdensity );
|
|
|
|
density = hdensity;
|
|
|
|
} else if (getGCellGrid()->getDensityMode() == GCellGrid::AverageVDensity) {
|
2010-12-12 15:43:25 -06:00
|
|
|
// Average density between all vertical layers.
|
|
|
|
size_t vplanes = 0;
|
|
|
|
float vdensity = 0.0;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
|
|
|
if ( i%2 == 0 ) { vdensity += _densities[i]; ++vplanes; }
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
if (vplanes) vdensity /= vplanes;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
//density = roundfp ( vdensity );
|
|
|
|
density = vdensity;
|
2010-12-12 15:43:25 -06:00
|
|
|
} else if ( getGCellGrid()->getDensityMode() == GCellGrid::MaxDensity ) {
|
|
|
|
// Density of the most saturated layer.
|
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
|
|
|
if ( _densities[i] > density ) density = _densities[i];
|
|
|
|
}
|
|
|
|
density = roundfp(density);
|
2013-12-03 18:58:58 -06:00
|
|
|
} else if (getGCellGrid()->getDensityMode() == GCellGrid::MaxHDensity) {
|
2010-12-12 15:43:25 -06:00
|
|
|
// Density of the most saturated horizontal layer.
|
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
|
|
|
if ( (i%2) and (_densities[i] > density) ) density = _densities[i];
|
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
//density = roundfp(density);
|
|
|
|
density = density;
|
|
|
|
} else if (getGCellGrid()->getDensityMode() == GCellGrid::MaxVDensity) {
|
2010-12-12 15:43:25 -06:00
|
|
|
// Density of the most saturated vertical layer.
|
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
|
|
|
if ( (i%2 == 0) and (_densities[i] > density) ) density = _densities[i];
|
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
//density = roundfp(density);
|
|
|
|
density = density;
|
2010-12-12 15:43:25 -06:00
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
return density;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
void GCell::addBlockage ( unsigned int depth, DbU::Unit length )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
|
|
|
if ( depth >= _depth ) return;
|
|
|
|
|
|
|
|
_blockages[depth] += length;
|
2013-12-03 18:58:58 -06:00
|
|
|
_flags |= GCellInvalidated;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- Change: In loadGlobalRouting(), more exlicit message as to why a net is
filtered out the routing set (POWER, GROUND, CLOCK or BLOCKAGE).
- New: ChipTool, module with utilities specific to chip routing. Containing
a function to pre-break wires around a block.
- New: In loadGlobalRouting/GCellConfiguration, adds supports for RoutingPad
connected on chip's pad.
- New: In GCellGrid/GCell, can compute the density in three modes: average,
max of H/V and max of layer. Currently implemented in getMaxHVDensity(),
should be unificated with getDensity(). Used for display purposes.
- Bug: In AutoContact, when splitting a contact, add a specific check for
"one layer span".
- Bug: In AutoSegment::canMoveUp(), do not move up fixed segments.
2010-11-16 07:59:38 -06:00
|
|
|
// if ( _blockages[depth] >= 8.0 ) {
|
|
|
|
// cinfo << Warning("%s is under power ring.",getString(this).c_str()) << endl;
|
|
|
|
|
|
|
|
// unsigned int modulo = depth % 2;
|
|
|
|
|
|
|
|
// for ( unsigned int parallel=0 ; parallel < _depth ; ++parallel ) {
|
|
|
|
// if ( parallel%2 == modulo ) {
|
|
|
|
// _blockages[parallel] = 10.0;
|
|
|
|
// cinfo << " Blocking [" << parallel << "]:"
|
|
|
|
// << Session::getRoutingLayer(parallel)->getName() << endl;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
ltrace(300) << "GCell:addBlockage() " << this << " "
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
<< depth << ":" << DbU::getValueString(_blockages[depth]) << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::removeContact ( AutoContact* ac )
|
|
|
|
{
|
|
|
|
size_t begin = 0;
|
|
|
|
size_t end = _contacts.size();
|
|
|
|
bool found = false;
|
|
|
|
|
|
|
|
for ( ; not found and (begin < end) ; begin++ ) {
|
|
|
|
if ( _contacts[begin] == ac ) {
|
|
|
|
_contacts[begin] = _contacts[end-1];
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found) {
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(200) << "remove " << ac << " from " << this << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
_contacts.pop_back();
|
|
|
|
} else {
|
|
|
|
cerr << Bug("%p:%s do not belong to %s."
|
|
|
|
,ac->base(),getString(ac).c_str(),_getString().c_str()) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
vector<AutoContact*>::iterator it = _contacts.begin ();
|
|
|
|
vector<AutoContact*>::iterator end = _contacts.end ();
|
|
|
|
for ( ; it != end ; it++ )
|
|
|
|
if ( *it == ac ) *it = *(--end);
|
|
|
|
_contacts.pop_back ();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::removeHSegment ( AutoSegment* segment )
|
|
|
|
{
|
|
|
|
size_t end = _hsegments.size();
|
|
|
|
size_t begin = 0;
|
|
|
|
|
|
|
|
for ( ; begin < end ; begin++ ) {
|
|
|
|
if ( _hsegments[begin] == segment ) {
|
|
|
|
swap ( _hsegments[begin], _hsegments[--end] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( _hsegments.size() == end ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
cerr << Bug("%s do not go through %s."
|
2010-03-09 09:24:29 -06:00
|
|
|
,getString(segment).c_str()
|
|
|
|
,_getString().c_str()) << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( _hsegments.size() - end > 1 )
|
2013-12-03 18:58:58 -06:00
|
|
|
cerr << Bug("%s has multiple occurrences of %s."
|
2010-03-09 09:24:29 -06:00
|
|
|
,_getString().c_str()
|
|
|
|
,getString(segment).c_str()) << endl;
|
|
|
|
|
|
|
|
_hsegments.erase ( _hsegments.begin() + end, _hsegments.end() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::removeVSegment ( AutoSegment* segment )
|
|
|
|
{
|
|
|
|
size_t end = _vsegments.size();
|
|
|
|
size_t begin = 0;
|
|
|
|
|
|
|
|
for ( ; begin < end ; begin++ ) {
|
|
|
|
if ( _vsegments[begin] == segment ) {
|
|
|
|
swap ( _vsegments[begin], _vsegments[--end] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( _vsegments.size() == end ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
cerr << Bug("%s do not go through %s."
|
2010-03-09 09:24:29 -06:00
|
|
|
,getString(segment).c_str()
|
|
|
|
,_getString().c_str()) << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( _vsegments.size() - end > 1 )
|
2013-12-03 18:58:58 -06:00
|
|
|
cerr << Bug("%s has multiple occurrences of %s."
|
2010-03-09 09:24:29 -06:00
|
|
|
,_getString().c_str()
|
|
|
|
,getString(segment).c_str()) << endl;
|
|
|
|
|
|
|
|
_vsegments.erase ( _vsegments.begin() + end, _vsegments.end() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::updateContacts ()
|
|
|
|
{
|
|
|
|
vector<AutoContact*>::iterator it = _contacts.begin ();
|
|
|
|
vector<AutoContact*>::iterator end = _contacts.end ();
|
|
|
|
for ( ; it != end ; it++ ) (*it)->updateGeometry ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t GCell::updateDensity ()
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (isValid()) return (isSaturated()) ? 1 : 0;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
_flags &= ~GCellSaturated;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
for ( size_t i=0 ; i<_vsegments.size() ; i++ ) {
|
|
|
|
if ( _vsegments[i] == NULL )
|
|
|
|
cerr << "NULL Autosegment at index " << i << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
sort ( _hsegments.begin(), _hsegments.end(), AutoSegment::CompareByDepthLength() );
|
|
|
|
sort ( _vsegments.begin(), _vsegments.end(), AutoSegment::CompareByDepthLength() );
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
float hcapacity = getHCapacity ();
|
|
|
|
float vcapacity = getVCapacity ();
|
|
|
|
float ccapacity = hcapacity * vcapacity * 4;
|
|
|
|
DbU::Unit hpenalty = 0 /*_box.getWidth () / 3*/;
|
|
|
|
DbU::Unit vpenalty = 0 /*_box.getHeight() / 3*/;
|
|
|
|
DbU::Unit uLengths1 [ _depth ];
|
|
|
|
DbU::Unit uLengths2 [ _depth ];
|
|
|
|
float localCounts [ _depth ];
|
|
|
|
UsedFragments ufragments [ _depth ];
|
|
|
|
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
|
|
|
_feedthroughs[i] = 0.0;
|
|
|
|
uLengths2 [i] = 0;
|
|
|
|
localCounts [i] = 0.0;
|
|
|
|
_globalsCount[i] = 0.0;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
switch ( Session::getRoutingGauge()->getLayerDirection(i) ) {
|
|
|
|
case Constant::Horizontal:
|
|
|
|
ufragments[i].setSpan ( _box.getXMin(), _box.getXMax() );
|
|
|
|
ufragments[i].setCapacity ( (size_t)hcapacity );
|
|
|
|
break;
|
|
|
|
case Constant::Vertical:
|
|
|
|
ufragments[i].setSpan ( _box.getYMin(), _box.getYMax() );
|
|
|
|
ufragments[i].setCapacity ( (size_t)vcapacity );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
// Compute wirelength associated to contacts (in DbU::Unit converted to float).
|
2011-01-09 12:08:31 -06:00
|
|
|
AutoSegment::DepthLengthSet processeds;
|
2010-03-09 09:24:29 -06:00
|
|
|
vector<AutoContact*>::iterator it = _contacts.begin();
|
|
|
|
vector<AutoContact*>::iterator end = _contacts.end ();
|
|
|
|
for ( ; it != end ; it++ ) {
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) uLengths1[i] = 0;
|
|
|
|
(*it)->getLengths ( uLengths1, processeds );
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
|
|
|
switch ( Session::getRoutingGauge()->getLayerDirection(i) ) {
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
case Constant::Horizontal: uLengths2[i] += uLengths1[i]+hpenalty; break;
|
|
|
|
case Constant::Vertical: uLengths2[i] += uLengths1[i]+vpenalty; break;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the "pass through" horizontal segments.
|
|
|
|
if ( _hsegments.size() ) {
|
|
|
|
const Layer* layer = _hsegments[0]->getLayer();
|
|
|
|
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
|
|
|
|
size_t count = 0;
|
|
|
|
for ( size_t i=0 ; i<_hsegments.size() ; i++ ) {
|
2011-01-09 12:08:31 -06:00
|
|
|
_globalsCount[depth] += 1.0;
|
|
|
|
ufragments [depth].incGlobals();
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
if ( layer != _hsegments[i]->getLayer() ) {
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
uLengths2[depth] += count * _box.getWidth();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
count = 0;
|
|
|
|
layer = _hsegments[i]->getLayer();
|
|
|
|
depth = Session::getRoutingGauge()->getLayerDepth(layer);
|
|
|
|
}
|
|
|
|
count++;
|
2011-01-09 12:08:31 -06:00
|
|
|
_feedthroughs[depth] += 1.0;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
if ( count ) {
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
uLengths2[depth] += count * _box.getWidth();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the "pass through" vertical segments.
|
|
|
|
if ( _vsegments.size() ) {
|
|
|
|
const Layer* layer = _vsegments[0]->getLayer();
|
|
|
|
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
|
|
|
|
size_t count = 0;
|
|
|
|
for ( size_t i=0 ; i<_vsegments.size() ; i++ ) {
|
2011-01-09 12:08:31 -06:00
|
|
|
_globalsCount[depth] += 1.0;
|
|
|
|
ufragments [depth].incGlobals();
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
if ( layer != _vsegments[i]->getLayer() ) {
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
uLengths2[depth] += count * _box.getHeight();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
count = 0;
|
|
|
|
layer = _vsegments[i]->getLayer();
|
|
|
|
depth = Session::getRoutingGauge()->getLayerDepth(layer);
|
|
|
|
}
|
|
|
|
count++;
|
2011-01-09 12:08:31 -06:00
|
|
|
_feedthroughs[depth] += 1.0;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
if ( count ) {
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
uLengths2[depth] += count * _box.getHeight();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the blockages.
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
uLengths2[i] += _blockages[i];
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
// Compute the number of non pass-through tracks.
|
|
|
|
if ( processeds.size() ) {
|
|
|
|
AutoSegment::DepthLengthSet::iterator isegment = processeds.begin();
|
|
|
|
const Layer* layer = (*isegment)->getLayer();
|
|
|
|
DbU::Unit axis = (*isegment)->getAxis();
|
|
|
|
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
|
|
|
|
size_t count = 0;
|
|
|
|
for ( ; isegment != processeds.end(); ++isegment ) {
|
|
|
|
_feedthroughs[depth] += ((*isegment)->isGlobal()) ? 0.50 : 0.33;
|
|
|
|
localCounts [depth] += 1.0;
|
|
|
|
if ( (*isegment)->isGlobal() ) _globalsCount[depth] += 1.0;
|
|
|
|
|
2011-01-25 11:16:27 -06:00
|
|
|
ufragments[depth].merge ( (*isegment)->getAxis(), (*isegment)->getSpanU() );
|
2011-01-09 12:08:31 -06:00
|
|
|
if ( (axis != (*isegment)->getAxis()) or (layer != (*isegment)->getLayer()) ) {
|
|
|
|
count = 0;
|
|
|
|
axis = (*isegment)->getAxis();
|
|
|
|
layer = (*isegment)->getLayer();
|
|
|
|
depth = Session::getRoutingGauge()->getLayerDepth(layer);
|
|
|
|
}
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
// Normalize: 0 < d < 1.0 (divide by H/V capacity).
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
|
|
|
switch ( Session::getRoutingGauge()->getLayerDirection(i) ) {
|
|
|
|
case Constant::Horizontal:
|
2011-01-09 12:08:31 -06:00
|
|
|
_densities [i] = ((float)uLengths2[i]) / ( hcapacity * (float)_box.getWidth() );
|
|
|
|
_feedthroughs [i] += (float)(_blockages[i] / _box.getWidth());
|
|
|
|
_fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)_box.getWidth();
|
2010-03-09 09:24:29 -06:00
|
|
|
break;
|
|
|
|
case Constant::Vertical:
|
2011-01-09 12:08:31 -06:00
|
|
|
_densities [i] = ((float)uLengths2[i]) / ( vcapacity * (float)_box.getHeight() );
|
|
|
|
_feedthroughs [i] += (float)(_blockages[i] / _box.getHeight());
|
|
|
|
_fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)_box.getHeight();
|
2010-03-09 09:24:29 -06:00
|
|
|
break;
|
|
|
|
}
|
2011-01-09 12:08:31 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (_densities[i] >= 1.0)
|
|
|
|
_flags |= GCellSaturated;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
_cDensity = ( (float)_contacts.size() ) / ccapacity;
|
|
|
|
_flags &= ~GCellInvalidated;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
//for ( size_t i=0 ; i<_depth ; i++ ) { _densities[i] = roundfp ( _densities[i] ); }
|
|
|
|
//_cDensity = roundfp (_cDensity );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
//ltrace(190) << "updateDensity: " << this << endl;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
checkDensity();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
return isSaturated() ? 1 : 0 ;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t GCell::checkDensity () const
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isValid()) const_cast<GCell*>(this)->updateDensity ();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( not Session::isInDemoMode() and Session::doWarnGCellOverload() ) {
|
2010-03-09 09:24:29 -06:00
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
|
|
|
if ( _densities[i] > 1.0 ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
cparanoid << Warning( "%s @%dx%d overloaded in %s (M2:%.2f M3:%.2f M4:%.2f M5:%.2f)"
|
|
|
|
, _getString().c_str()
|
|
|
|
, getColumn()
|
|
|
|
, getRow()
|
|
|
|
, getString(Session::getRoutingGauge()->getRoutingLayer(i)->getName()).c_str()
|
|
|
|
, _densities[1] // M2
|
|
|
|
, _densities[2] // M3
|
|
|
|
//, _blockages[2] // M4
|
|
|
|
, _densities[3] // M5
|
|
|
|
, _densities[4] // M6
|
|
|
|
)
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
<< endl;
|
|
|
|
}
|
|
|
|
}
|
2011-01-25 11:16:27 -06:00
|
|
|
// for ( size_t i=3 ; i<_depth ; i+=2 ) {
|
|
|
|
// if ( (_densities[i] < 0.5) and (_densities[i-2] < 0.5) ) continue;
|
|
|
|
|
|
|
|
// float balance = _densities[i] / (_densities[i-2]+0.001 );
|
|
|
|
// if ( (balance > 3) or (balance < .33) ) {
|
|
|
|
// cerr << Warning("%s @%dx%d unbalanced in %s (M2:%.2f M3:%.2f M4:%.2f M5:%.2f)"
|
|
|
|
// ,_getString().c_str()
|
|
|
|
// ,getColumn()
|
|
|
|
// ,getRow()
|
|
|
|
// ,getString(Session::getRoutingGauge()->getRoutingLayer(i)->getName()).c_str()
|
|
|
|
// ,_densities[1] // M2
|
|
|
|
// ,_densities[2] // M3
|
|
|
|
// //,_blockages[2] // M4
|
|
|
|
// ,_densities[3] // M5
|
|
|
|
// ,_densities[4] // M6
|
|
|
|
// )
|
|
|
|
// << endl;
|
|
|
|
// }
|
|
|
|
// }
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
return isSaturated() ? 1 : 0 ;
|
2010-04-12 06:22:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-23 08:13:54 -05:00
|
|
|
bool GCell::hasFreeTrack ( size_t depth, float reserve ) const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isValid()) const_cast<GCell*>(this)->updateDensity();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
#if DEPRECATED
|
|
|
|
float capacity;
|
|
|
|
vector<AutoSegment*>::const_iterator isegment;
|
|
|
|
vector<AutoSegment*>::const_iterator iend;
|
|
|
|
|
|
|
|
switch ( Session::getRoutingGauge()->getLayerDirection(depth) ) {
|
|
|
|
case Constant::Horizontal:
|
|
|
|
iend = _hsegments.end ();
|
|
|
|
isegment = _hsegments.begin ();
|
|
|
|
capacity = getHCapacity ();
|
|
|
|
break;
|
|
|
|
case Constant::Vertical:
|
|
|
|
iend = _vsegments.end ();
|
|
|
|
isegment = _vsegments.begin ();
|
|
|
|
capacity = getVCapacity ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t count = 0;
|
|
|
|
for ( ; (isegment != iend) ; isegment++ ) {
|
|
|
|
unsigned int segmentDepth = Session::getRoutingGauge()->getLayerDepth((*isegment)->getLayer());
|
|
|
|
if ( segmentDepth < depth ) continue;
|
|
|
|
if ( segmentDepth > depth ) break;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (capacity - 1.0) >= (float)count;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
float capacity = 0.0;
|
|
|
|
switch ( Session::getRoutingGauge()->getLayerDirection(depth) ) {
|
|
|
|
case Constant::Horizontal: capacity = getHCapacity(); break;
|
|
|
|
case Constant::Vertical: capacity = getVCapacity(); break;
|
|
|
|
}
|
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
ltrace(200) << " | hasFreeTrack [" << getIndex() << "] depth:" << depth << " "
|
2010-03-09 09:24:29 -06:00
|
|
|
<< Session::getRoutingGauge()->getRoutingLayer(depth)->getName()
|
2011-01-09 12:08:31 -06:00
|
|
|
//<< " " << (_densities[depth]*capacity) << " vs. " << capacity
|
|
|
|
<< " " << _feedthroughs[depth] << " vs. " << capacity
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
<< " " << this << endl;
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
//return (_densities[depth]*capacity + 1.0 + reserve <= capacity);
|
|
|
|
return (_feedthroughs[depth] + 0.99 + reserve <= capacity);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool GCell::checkEdgeSaturation ( float threshold ) const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
unsigned int edgeUpUsage = 0;
|
|
|
|
unsigned int edgeRightUsage = 0;
|
|
|
|
float edgeUpSaturation = 0.0;
|
|
|
|
float edgeRightSaturation = 0.0;
|
|
|
|
|
|
|
|
if ( getUp() ) {
|
|
|
|
// Up Edge Density.
|
|
|
|
edgeUpUsage = _vsegments.size();
|
|
|
|
for ( size_t icontact=0 ; icontact < _contacts.size() ; icontact++ ) {
|
|
|
|
forEach ( Hook*, ihook, _contacts[icontact]->getBodyHook()->getSlaveHooks() ) {
|
|
|
|
if ( dynamic_cast<Segment::SourceHook*>(*ihook) == NULL ) continue;
|
|
|
|
|
|
|
|
Segment* segment = dynamic_cast<Vertical*>((*ihook)->getComponent());
|
|
|
|
if ( not segment ) continue;
|
|
|
|
|
|
|
|
AutoSegment* autoSegment = Session::lookup ( segment );
|
|
|
|
if ( not autoSegment or autoSegment->isLocal() ) continue;
|
|
|
|
|
|
|
|
edgeUpUsage++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
edgeUpSaturation = (float)edgeUpUsage/getGCellGrid()->getVEdgeCapacity();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( getRight() ) {
|
|
|
|
// Right Edge Density.
|
|
|
|
edgeRightUsage = _vsegments.size();
|
|
|
|
for ( size_t icontact=0 ; icontact < _contacts.size() ; icontact++ ) {
|
|
|
|
forEach ( Hook*, ihook, _contacts[icontact]->getBodyHook()->getSlaveHooks() ) {
|
|
|
|
if ( dynamic_cast<Segment::SourceHook*>(*ihook) == NULL ) continue;
|
|
|
|
|
|
|
|
Segment* segment = dynamic_cast<Horizontal*>((*ihook)->getComponent());
|
|
|
|
if ( not segment ) continue;
|
|
|
|
|
|
|
|
AutoSegment* autoSegment = Session::lookup ( segment );
|
|
|
|
if ( not autoSegment or autoSegment->isLocal() ) continue;
|
|
|
|
|
|
|
|
edgeRightUsage++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
edgeRightSaturation = (float)edgeRightUsage/getGCellGrid()->getHEdgeCapacity();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool overload = false;
|
|
|
|
if ( (edgeUpSaturation > threshold) or (edgeRightSaturation > threshold) ) {
|
|
|
|
overload = true;
|
|
|
|
|
|
|
|
cparanoid << Warning("In %s, (over %.2f) ", _getString().c_str(), threshold);
|
|
|
|
|
|
|
|
ostringstream message;
|
|
|
|
message << setprecision(3);
|
|
|
|
if ( edgeUpSaturation > threshold )
|
|
|
|
message << "up edge: " << edgeUpUsage << "/" << getGCellGrid()->getVEdgeCapacity()
|
|
|
|
<< " " << edgeUpSaturation;
|
|
|
|
if ( edgeRightSaturation > threshold ) {
|
|
|
|
if ( message.str().size() ) message << " & ";
|
|
|
|
message << "right edge: " << edgeRightUsage << "/" << getGCellGrid()->getHEdgeCapacity()
|
|
|
|
<< " " << edgeRightSaturation;
|
|
|
|
}
|
|
|
|
|
|
|
|
cparanoid << message.str() << "." << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return overload;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::rpDesaturate ( set<Net*>& globalNets )
|
|
|
|
{
|
|
|
|
set<RoutingPad*> rps;
|
|
|
|
getRoutingPads ( rps );
|
|
|
|
|
|
|
|
set<Net*> rpNets;
|
|
|
|
set<RoutingPad*>::iterator irp = rps.begin();
|
|
|
|
for ( ; irp != rps.end() ; ++irp ) {
|
|
|
|
if ( (*irp)->getLayer() != Session::getRoutingLayer(0) ) continue;
|
|
|
|
rpNets.insert ( (*irp)->getNet() );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( rpNets.size() < Session::getSaturateRp() ) return;
|
|
|
|
|
|
|
|
cerr << Warning("%s has %zd terminals (h:%zd, v:%zd)"
|
|
|
|
,getString(this).c_str()
|
|
|
|
,rps.size()
|
|
|
|
,_hsegments.size()
|
|
|
|
,_vsegments.size()
|
|
|
|
) << endl;
|
|
|
|
|
|
|
|
AutoSegment* segment;
|
|
|
|
while ( (_densities[1] > 0.5) and stepDesaturate(1,globalNets,segment,KbForceMove) ) {
|
|
|
|
ltrace(200) << "Moved up: " << segment << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::stepDesaturate ( unsigned int depth
|
|
|
|
, set<Net*>& globalNets
|
|
|
|
, AutoSegment*& moved
|
|
|
|
, unsigned int flags
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ltrace(500) << "Deter| GCell::stepDesaturate() [" << getIndex() << "] depth:" << depth << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
updateDensity ();
|
2010-12-12 15:43:25 -06:00
|
|
|
moved = NULL;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( not (flags & KbForceMove) and not isSaturated(depth) ) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
float capacity;
|
|
|
|
vector<AutoSegment*>::iterator isegment;
|
|
|
|
vector<AutoSegment*>::iterator iend;
|
|
|
|
|
|
|
|
switch ( Session::getRoutingGauge()->getLayerDirection(depth) ) {
|
|
|
|
case Constant::Horizontal:
|
|
|
|
iend = _hsegments.end ();
|
|
|
|
isegment = _hsegments.begin ();
|
|
|
|
capacity = getHCapacity ();
|
|
|
|
break;
|
|
|
|
case Constant::Vertical:
|
|
|
|
iend = _vsegments.end ();
|
|
|
|
isegment = _vsegments.begin ();
|
|
|
|
capacity = getVCapacity ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( ; (isegment != iend) ; isegment++ ) {
|
|
|
|
unsigned int segmentDepth = Session::getRoutingGauge()->getLayerDepth((*isegment)->getLayer());
|
|
|
|
|
|
|
|
if ( segmentDepth < depth ) continue;
|
|
|
|
if ( segmentDepth > depth ) break;
|
|
|
|
|
|
|
|
globalNets.insert ( (*isegment)->getNet() );
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(500) << "Deter| Move up " << (*isegment) << endl;
|
* ./katabatic:
- New: ChipTools, regroup all datas and utilities to manage a full-chip
design.
- Change: In LoadGrByNet/GCellConfiguration::_GCell_xG_1Pad(), uses straight
perpandicular wires on top & right pads. The GCells under those connectors
are fully saturated, wires must go out as straight as possible.
- Change: In AutoHorizontal/AutoVertical, update the "terminal" flag after
slackening. This is to avoid global that are no longer connected to
terminals behave as such.
- Change: In AutoSegment::canMoveUp() & canPivotUp(), prevent all local segments
to go up. This is to avoid cluttering upper levels with small segments.
- Change: In GCellConfiguration, for xG_xL3, detect straight vertical topologies
and for them to be fixed (new flag FIXED_GLOBAL set by the topological
builder instead of the constructor). This prevent the router to do
stupid things...
To sets the "Fixed" flag *after* the axis of global segments have been
positionned correctly adds a "_toFixGlobals" static table lookup.
- Change: In GCell::stepDesaturate(), if less than one free track remains in
the upper layer, do not move up the segment. This allows from a minimum
free room for expansion.
- Change: In GCell::_getString(), display indexes and layer names in various
saturation tables.
- Change: In AutoSegment, allow move up of local Segment. ::moveUp() and
::canMoveUp() arguments go from booleans to flags, which are more
explicits.
2010-12-04 09:25:18 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
#if THIS_IS_DISABLED
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
(*isegment)->changeDepth ( depth+2, false, false );
|
2013-12-03 18:58:58 -06:00
|
|
|
#endif
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
moved = (*isegment);
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (moved) return true;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool GCell::stepBalance ( unsigned int depth, GCell::SetIndex& invalidateds )
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(200) << "stepBalance() - " << this << endl;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
|
|
|
|
updateDensity ();
|
|
|
|
|
|
|
|
float capacity;
|
|
|
|
vector<AutoSegment*>::iterator isegment;
|
|
|
|
vector<AutoSegment*>::iterator iend;
|
2013-12-03 18:58:58 -06:00
|
|
|
set<Net*> globalNets;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
|
|
|
|
switch ( Session::getRoutingGauge()->getLayerDirection(depth) ) {
|
|
|
|
case Constant::Horizontal:
|
|
|
|
iend = _hsegments.end ();
|
|
|
|
isegment = _hsegments.begin ();
|
|
|
|
capacity = getHCapacity ();
|
|
|
|
break;
|
|
|
|
case Constant::Vertical:
|
|
|
|
iend = _vsegments.end ();
|
|
|
|
isegment = _vsegments.begin ();
|
|
|
|
capacity = getVCapacity ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( ; (isegment != iend) ; isegment++ ) {
|
|
|
|
unsigned int segmentDepth = Session::getRoutingGauge()->getLayerDepth((*isegment)->getLayer());
|
|
|
|
|
|
|
|
if ( segmentDepth < depth ) continue;
|
|
|
|
if ( segmentDepth > depth ) break;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
// Hard-coded: reserve 3 tracks (1/20 * 3).
|
|
|
|
if ((*isegment)->canMoveULeft(0.05)) {
|
|
|
|
getGCellGrid()->getKatabatic()->moveULeft(*isegment,globalNets,invalidateds);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ((*isegment)->canMoveURight(0.05)) {
|
|
|
|
getGCellGrid()->getKatabatic()->moveURight(*isegment,globalNets,invalidateds);
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
return true;
|
2013-12-03 18:58:58 -06:00
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool GCell::stepNetDesaturate ( unsigned int depth, set<Net*>& globalNets, GCell::SetIndex& invalidateds )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(500) << "Deter| GCell::stepNetDesaturate() depth:" << depth << endl;
|
|
|
|
ltrace(500) << "Deter| " << this << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
updateDensity ();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
float capacity;
|
|
|
|
vector<AutoSegment*>::iterator isegment;
|
|
|
|
vector<AutoSegment*>::iterator iend;
|
|
|
|
|
|
|
|
switch ( Session::getRoutingGauge()->getLayerDirection(depth) ) {
|
|
|
|
case Constant::Horizontal:
|
|
|
|
iend = _hsegments.end ();
|
|
|
|
isegment = _hsegments.begin ();
|
|
|
|
capacity = getHCapacity ();
|
|
|
|
break;
|
|
|
|
case Constant::Vertical:
|
|
|
|
iend = _vsegments.end ();
|
|
|
|
isegment = _vsegments.begin ();
|
2013-12-03 18:58:58 -06:00
|
|
|
capacity = getVCapacity ();
|
2010-03-09 09:24:29 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
for ( ; (isegment != iend) ; isegment++ ) {
|
2010-03-09 09:24:29 -06:00
|
|
|
unsigned int segmentDepth = Session::getRoutingGauge()->getLayerDepth((*isegment)->getLayer());
|
|
|
|
|
|
|
|
if ( segmentDepth < depth ) continue;
|
|
|
|
if ( segmentDepth > depth ) break;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(500) << "Deter| Move up " << (*isegment) << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( getGCellGrid()->getKatabatic()->moveUpNetTrunk(*isegment,globalNets,invalidateds) )
|
|
|
|
return true;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Box GCell::getBoundingBox () const
|
|
|
|
{
|
|
|
|
return _box;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::translate ( const DbU::Unit&, const DbU::Unit& )
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
cerr << Warning("Calling GCell::translate() on %s is likely a bug."
|
|
|
|
,_getString().c_str()) << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string GCell::_getString () const
|
|
|
|
{
|
|
|
|
Box box = getBoundingBox ();
|
|
|
|
|
|
|
|
ostringstream s;
|
|
|
|
s << "<" << _getTypeName() << " [" << _index << "] "
|
|
|
|
<< DbU::getValueString(box.getXMin()) << ":" << DbU::getValueString(box.getYMin()) << " "
|
|
|
|
<< DbU::getValueString(box.getXMax()) << ":" << DbU::getValueString(box.getYMax()) << " "
|
2010-12-12 15:43:25 -06:00
|
|
|
<< setprecision(3)
|
2013-12-03 18:58:58 -06:00
|
|
|
<< getDensity(NoUpdate) << " "
|
2011-01-09 12:08:31 -06:00
|
|
|
<< "d:" << _depth << " "
|
|
|
|
<< getVectorString(_densities ,_depth) << " "
|
|
|
|
<< getVectorString(_feedthroughs,_depth)
|
2013-12-03 18:58:58 -06:00
|
|
|
<< " "
|
|
|
|
<< (isValid () ? "-" : "i")
|
|
|
|
<< (isSaturated () ? "s" : "-")
|
|
|
|
<< (isUnderIoPad() ? "P" : "-")
|
2010-03-09 09:24:29 -06:00
|
|
|
<< ">";
|
|
|
|
|
|
|
|
return s.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Record* GCell::_getRecord () const
|
|
|
|
{
|
|
|
|
Record* record = new Record ( _getString() );
|
|
|
|
record->add ( getSlot ( "_gcellGrid" , _gcellGrid ) );
|
|
|
|
record->add ( getSlot ( "_index" , &_index ) );
|
|
|
|
record->add ( getSlot ( "_vsegments" , &_vsegments ) );
|
|
|
|
record->add ( getSlot ( "_hsegments" , &_hsegments ) );
|
|
|
|
record->add ( getSlot ( "_contacts" , &_contacts ) );
|
|
|
|
record->add ( getSlot ( "_box" , &_box ) );
|
|
|
|
record->add ( getSlot ( "_depth" , &_depth ) );
|
2013-12-03 18:58:58 -06:00
|
|
|
record->add ( getSlot ( "_flags" , &_flags ) );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- New: ChipTools, regroup all datas and utilities to manage a full-chip
design.
- Change: In LoadGrByNet/GCellConfiguration::_GCell_xG_1Pad(), uses straight
perpandicular wires on top & right pads. The GCells under those connectors
are fully saturated, wires must go out as straight as possible.
- Change: In AutoHorizontal/AutoVertical, update the "terminal" flag after
slackening. This is to avoid global that are no longer connected to
terminals behave as such.
- Change: In AutoSegment::canMoveUp() & canPivotUp(), prevent all local segments
to go up. This is to avoid cluttering upper levels with small segments.
- Change: In GCellConfiguration, for xG_xL3, detect straight vertical topologies
and for them to be fixed (new flag FIXED_GLOBAL set by the topological
builder instead of the constructor). This prevent the router to do
stupid things...
To sets the "Fixed" flag *after* the axis of global segments have been
positionned correctly adds a "_toFixGlobals" static table lookup.
- Change: In GCell::stepDesaturate(), if less than one free track remains in
the upper layer, do not move up the segment. This allows from a minimum
free room for expansion.
- Change: In GCell::_getString(), display indexes and layer names in various
saturation tables.
- Change: In AutoSegment, allow move up of local Segment. ::moveUp() and
::canMoveUp() arguments go from booleans to flags, which are more
explicits.
2010-12-04 09:25:18 -06:00
|
|
|
RoutingGauge* rg = getGCellGrid()->getKatabatic()->getRoutingGauge();
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
for ( size_t depth=0 ; depth<_depth ; ++depth ) {
|
* ./katabatic:
- New: ChipTools, regroup all datas and utilities to manage a full-chip
design.
- Change: In LoadGrByNet/GCellConfiguration::_GCell_xG_1Pad(), uses straight
perpandicular wires on top & right pads. The GCells under those connectors
are fully saturated, wires must go out as straight as possible.
- Change: In AutoHorizontal/AutoVertical, update the "terminal" flag after
slackening. This is to avoid global that are no longer connected to
terminals behave as such.
- Change: In AutoSegment::canMoveUp() & canPivotUp(), prevent all local segments
to go up. This is to avoid cluttering upper levels with small segments.
- Change: In GCellConfiguration, for xG_xL3, detect straight vertical topologies
and for them to be fixed (new flag FIXED_GLOBAL set by the topological
builder instead of the constructor). This prevent the router to do
stupid things...
To sets the "Fixed" flag *after* the axis of global segments have been
positionned correctly adds a "_toFixGlobals" static table lookup.
- Change: In GCell::stepDesaturate(), if less than one free track remains in
the upper layer, do not move up the segment. This allows from a minimum
free room for expansion.
- Change: In GCell::_getString(), display indexes and layer names in various
saturation tables.
- Change: In AutoSegment, allow move up of local Segment. ::moveUp() and
::canMoveUp() arguments go from booleans to flags, which are more
explicits.
2010-12-04 09:25:18 -06:00
|
|
|
ostringstream s;
|
|
|
|
const Layer* layer = rg->getRoutingLayer(depth)->getBlockageLayer();
|
|
|
|
s << "_blockages[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
|
|
|
|
record->add ( getSlot ( s.str(), &_blockages[depth] ) );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
for ( size_t depth=0 ; depth<_depth ; ++depth ) {
|
* ./katabatic:
- New: ChipTools, regroup all datas and utilities to manage a full-chip
design.
- Change: In LoadGrByNet/GCellConfiguration::_GCell_xG_1Pad(), uses straight
perpandicular wires on top & right pads. The GCells under those connectors
are fully saturated, wires must go out as straight as possible.
- Change: In AutoHorizontal/AutoVertical, update the "terminal" flag after
slackening. This is to avoid global that are no longer connected to
terminals behave as such.
- Change: In AutoSegment::canMoveUp() & canPivotUp(), prevent all local segments
to go up. This is to avoid cluttering upper levels with small segments.
- Change: In GCellConfiguration, for xG_xL3, detect straight vertical topologies
and for them to be fixed (new flag FIXED_GLOBAL set by the topological
builder instead of the constructor). This prevent the router to do
stupid things...
To sets the "Fixed" flag *after* the axis of global segments have been
positionned correctly adds a "_toFixGlobals" static table lookup.
- Change: In GCell::stepDesaturate(), if less than one free track remains in
the upper layer, do not move up the segment. This allows from a minimum
free room for expansion.
- Change: In GCell::_getString(), display indexes and layer names in various
saturation tables.
- Change: In AutoSegment, allow move up of local Segment. ::moveUp() and
::canMoveUp() arguments go from booleans to flags, which are more
explicits.
2010-12-04 09:25:18 -06:00
|
|
|
ostringstream s;
|
|
|
|
const Layer* layer = rg->getRoutingLayer(depth);
|
|
|
|
s << "_densities[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
|
|
|
|
record->add ( getSlot ( s.str(), &_densities[depth] ) );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
// for ( size_t depth=0 ; depth<_depth ; ++depth ) {
|
|
|
|
// ostringstream s;
|
|
|
|
// const Layer* layer = rg->getRoutingLayer(depth);
|
|
|
|
// s << "_saturateDensities[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
|
|
|
|
// record->add ( getSlot ( s.str(), &_saturateDensities[depth] ) );
|
|
|
|
// }
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
return record;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_xmlWrite ( ostream& o ) const
|
|
|
|
{
|
|
|
|
char line[1024];
|
|
|
|
|
|
|
|
snprintf ( line, 1024
|
|
|
|
, "<GCell index=\"%04i %04i\" corner=\"%06.1f %06.1f\" density=\"%3.2f,%3.2f\">"
|
|
|
|
, getColumn()
|
|
|
|
, getRow()
|
|
|
|
, DbU::getLambda(getX())
|
|
|
|
, DbU::getLambda(getY())
|
|
|
|
, getDensity()
|
|
|
|
, _cDensity
|
|
|
|
);
|
|
|
|
|
|
|
|
o << line;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-23 04:25:15 -05:00
|
|
|
// -------------------------------------------------------------------
|
2013-12-03 18:58:58 -06:00
|
|
|
// Class : "Kite::GCellDensitySet".
|
2010-03-23 04:25:15 -05:00
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
GCellDensitySet::GCellDensitySet ( unsigned int depth )
|
2010-03-23 04:25:15 -05:00
|
|
|
: _depth (depth)
|
2013-12-03 18:58:58 -06:00
|
|
|
, _set ()
|
2010-03-23 04:25:15 -05:00
|
|
|
, _requests()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
GCellDensitySet::GCellDensitySet ( unsigned int depth, const std::vector<GCell*>& gcells )
|
2010-03-23 04:25:15 -05:00
|
|
|
: _depth (depth)
|
2013-12-03 18:58:58 -06:00
|
|
|
, _set ()
|
2010-03-23 04:25:15 -05:00
|
|
|
, _requests()
|
|
|
|
{
|
|
|
|
for ( size_t i=0 ; i<gcells.size() ; i++ )
|
2013-12-03 18:58:58 -06:00
|
|
|
_requests.insert( gcells[i] );
|
|
|
|
requeue();
|
2010-03-23 04:25:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
GCellDensitySet::~GCellDensitySet ()
|
2010-03-23 04:25:15 -05:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not _requests.empty()) {
|
|
|
|
cerr << Warning("~GCellDensitySet(): Still contains %d requests (and %d elements)."
|
|
|
|
,_requests.size(),_set.size()) << endl;
|
2010-03-23 04:25:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void GCellDensitySet::requeue ()
|
2010-03-23 04:25:15 -05:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(190) << "GCellDensitySet::requeue()" << endl;
|
2010-05-03 04:16:28 -05:00
|
|
|
|
2010-03-23 04:25:15 -05:00
|
|
|
std::set<GCell*,GCell::CompareByKey>::iterator iinserted;
|
2013-12-03 18:58:58 -06:00
|
|
|
GCell::SetIndex::iterator igcell = _requests.begin();
|
2011-01-09 12:08:31 -06:00
|
|
|
|
|
|
|
// Remove invalidateds GCell from the queue.
|
2010-03-23 04:25:15 -05:00
|
|
|
for ( ; igcell != _requests.end() ; ++igcell ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
iinserted = _set.find(*igcell);
|
|
|
|
if (iinserted != _set.end()) {
|
|
|
|
_set.erase( iinserted );
|
2010-03-23 04:25:15 -05:00
|
|
|
}
|
2011-01-09 12:08:31 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Re-insert invalidateds GCell in the queue *after* updating the key.
|
|
|
|
for ( igcell = _requests.begin() ; igcell != _requests.end() ; ++igcell ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
(*igcell)->updateKey( _depth );
|
|
|
|
_set.insert( *igcell );
|
2010-03-23 04:25:15 -05:00
|
|
|
}
|
2011-01-09 12:08:31 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
_requests.clear();
|
2010-03-23 04:25:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Utilities.
|
|
|
|
|
|
|
|
|
|
|
|
string getVectorString ( float* v, size_t size )
|
|
|
|
{
|
|
|
|
ostringstream s;
|
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
s << setprecision(3);
|
2010-03-09 09:24:29 -06:00
|
|
|
for ( size_t i=0 ; i<size ; i++ ) {
|
|
|
|
if ( !i ) s << "[";
|
|
|
|
else s << " ";
|
|
|
|
s << v[i];
|
|
|
|
}
|
|
|
|
s << "]";
|
|
|
|
|
|
|
|
return s.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // End of Katabatic namespace.
|