2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
2012-12-03 02:28:43 -06:00
|
|
|
// Copyright (c) UPMC/LIP6 2008-2012, 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 |
|
|
|
|
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
|
|
|
// | =============================================================== |
|
|
|
|
// | 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
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Katabatic::GCell::BlockedAxis".
|
|
|
|
|
|
|
|
|
|
|
|
GCell::BlockedAxis::BlockedAxis ( GCell* gcell )
|
|
|
|
: _gcell (gcell)
|
|
|
|
, _axisSets(new set<DbU::Unit>* [_gcell->getDepth()])
|
|
|
|
{
|
|
|
|
for ( size_t i=0 ; i<_gcell->getDepth() ; ++i ) _axisSets[i] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const set<DbU::Unit>& GCell::BlockedAxis::getAxisSet ( size_t depth ) const
|
|
|
|
{
|
|
|
|
static const set<DbU::Unit> _emptySet;
|
|
|
|
|
|
|
|
if ( (depth >= _gcell->getDepth()) or (not _axisSets[depth]) )
|
|
|
|
return _emptySet;
|
|
|
|
|
|
|
|
return *(_axisSets[depth]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::BlockedAxis::addAxis ( size_t depth, DbU::Unit axis )
|
|
|
|
{
|
|
|
|
if ( depth >= _gcell->getDepth() ) return;
|
|
|
|
if ( not _axisSets[depth] ) _axisSets[depth] = new set<DbU::Unit>();
|
|
|
|
|
|
|
|
_axisSets[depth]->insert ( axis );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
float difference = roundfp ( lhs->getDensity(_depth) - rhs->getDensity(_depth) );
|
|
|
|
if ( difference != 0.0 ) return (difference > 0.0);
|
|
|
|
|
|
|
|
//int difference = floatCompare ( lhs->getDensity(_depth), rhs->getDensity(_depth) );
|
|
|
|
//if ( abs(difference) > 1000 ) return difference > 0;
|
|
|
|
|
|
|
|
if ( lhs->getIndex() < rhs->getIndex() ) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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])
|
2010-03-09 09:24:29 -06:00
|
|
|
, _saturated (false)
|
|
|
|
, _invalid (true)
|
2010-03-23 04:25:15 -05:00
|
|
|
, _key (0.0,_index)
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
_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 )
|
|
|
|
{
|
|
|
|
if ( !_topRightShrink )
|
|
|
|
_topRightShrink = 1 /*DbU::lambda(0.0)*/;
|
|
|
|
|
|
|
|
GCell* gcell = new GCell ( gcellGrid, index, box.inflate(0
|
|
|
|
,0
|
|
|
|
,-_topRightShrink
|
|
|
|
,-_topRightShrink) );
|
|
|
|
|
|
|
|
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
|
|
|
|
{
|
|
|
|
if (_invalid) const_cast<GCell*>(this)->updateDensity();
|
|
|
|
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
|
|
|
|
{
|
|
|
|
if (_invalid) const_cast<GCell*>(this)->updateDensity();
|
|
|
|
|
|
|
|
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); }
|
|
|
|
|
|
|
|
|
|
|
|
Interval GCell::getUSide ( unsigned int direction ) const
|
|
|
|
{
|
|
|
|
Interval side;
|
|
|
|
switch ( direction ) {
|
|
|
|
default:
|
|
|
|
case Constant::Horizontal: side = Interval(_box.getXMin(),_box.getXMax()); break;
|
|
|
|
case Constant::Vertical: side = Interval(_box.getYMin(),_box.getYMax()); break;
|
|
|
|
}
|
|
|
|
return side;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getHStartSegments ()
|
|
|
|
{
|
|
|
|
return new AutoSegments_AnchorOnGCell (this,true,Constant::Horizontal);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getVStartSegments ()
|
|
|
|
{
|
|
|
|
return new AutoSegments_AnchorOnGCell (this,true,Constant::Vertical);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getHStopSegments ()
|
|
|
|
{
|
|
|
|
return new AutoSegments_AnchorOnGCell (this,false,Constant::Horizontal);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getVStopSegments ()
|
|
|
|
{
|
|
|
|
return new AutoSegments_AnchorOnGCell (this,false,Constant::Vertical);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float GCell::getDensity ( bool update ) const
|
|
|
|
{
|
|
|
|
if (_invalid and update) const_cast<GCell*>(this)->updateDensity();
|
|
|
|
|
|
|
|
float density = 0.0;
|
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
if ( getGCellGrid()->getDensityMode() == GCellGrid::AverageHVDensity ) {
|
|
|
|
// 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
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
density = roundfp ( density/((float)(_depth-_pinDepth)) );
|
|
|
|
} else if ( getGCellGrid()->getDensityMode() == GCellGrid::MaxHVDensity ) {
|
|
|
|
// 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;
|
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
density = roundfp ( (hdensity > vdensity) ? hdensity : vdensity );
|
|
|
|
} else if ( getGCellGrid()->getDensityMode() == GCellGrid::AverageHDensity ) {
|
|
|
|
// 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
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
density = roundfp ( hdensity );
|
|
|
|
} else if ( getGCellGrid()->getDensityMode() == GCellGrid::AverageVDensity ) {
|
|
|
|
// 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
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
density = roundfp ( vdensity );
|
|
|
|
} 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);
|
|
|
|
} else if ( getGCellGrid()->getDensityMode() == GCellGrid::MaxHDensity ) {
|
|
|
|
// 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];
|
|
|
|
}
|
|
|
|
density = roundfp(density);
|
|
|
|
} else if ( getGCellGrid()->getDensityMode() == GCellGrid::MaxVDensity ) {
|
|
|
|
// 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];
|
|
|
|
}
|
|
|
|
density = roundfp(density);
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
#if defined(CHECK_DETERMINISM)
|
|
|
|
cerr << "Order: density " << setprecision(9) << density << endl;
|
|
|
|
#endif
|
|
|
|
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;
|
|
|
|
_invalid = true;
|
|
|
|
|
* ./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
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
// void GCell::addBlockedAxis ( unsigned int depth, DbU::Unit axis )
|
|
|
|
// {
|
|
|
|
// _invalid = true;
|
|
|
|
// _blockedAxis.addAxis ( depth, axis );
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
ltrace(200) << "remove " << (void*)ac->base() << ":" << ac
|
|
|
|
<< " from " << this << endl;
|
|
|
|
_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 ) {
|
|
|
|
cerr << Bug("%p %s do not go through %s."
|
|
|
|
,(void*)segment
|
|
|
|
,getString(segment).c_str()
|
|
|
|
,_getString().c_str()) << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( _hsegments.size() - end > 1 )
|
|
|
|
cerr << Bug("%p %s has multiple occurrences of %s."
|
|
|
|
,(void*)segment
|
|
|
|
,_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 ) {
|
|
|
|
cerr << Bug("%p %s do not go through %s."
|
|
|
|
,(void*)segment
|
|
|
|
,getString(segment).c_str()
|
|
|
|
,_getString().c_str()) << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( _vsegments.size() - end > 1 )
|
|
|
|
cerr << Bug("%p %s has multiple occurrences of %s."
|
|
|
|
,(void*)segment
|
|
|
|
,_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 ()
|
|
|
|
{
|
2011-01-09 12:08:31 -06:00
|
|
|
if ( not _invalid ) return (_saturated) ? 1 : 0;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
_saturated = false;
|
|
|
|
|
|
|
|
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() );
|
|
|
|
|
|
|
|
#if defined(CHECK_DETERMINISM)
|
|
|
|
cerr << "Order: Update density " << this << endl;
|
|
|
|
for ( size_t i=0 ; i<_hsegments.size() ; i++ ) cerr << "Order: " << _hsegments[i] << endl;
|
|
|
|
for ( size_t i=0 ; i<_vsegments.size() ; i++ ) cerr << "Order: " << _vsegments[i] << endl;
|
|
|
|
#endif
|
|
|
|
|
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 ];
|
|
|
|
//set<DbU::Unit> usedAxis [ _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;
|
|
|
|
}
|
|
|
|
|
|
|
|
//usedAxis [i] = _blockedAxis.getAxisSet ( i );
|
|
|
|
}
|
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;
|
|
|
|
//usedAxis[depth].insert ( _hsegments[i]->getAxis() );
|
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;
|
|
|
|
//usedAxis[depth].insert ( _vsegments[i]->getAxis() );
|
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()) ) {
|
|
|
|
//_feedthroughs[depth] += 1;
|
|
|
|
//usedAxis[depth].insert ( axis );
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
axis = (*isegment)->getAxis();
|
|
|
|
layer = (*isegment)->getLayer();
|
|
|
|
depth = Session::getRoutingGauge()->getLayerDepth(layer);
|
|
|
|
}
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
if ( count ) {
|
|
|
|
//_feedthroughs[depth] += 1;
|
|
|
|
//usedAxis[depth].insert ( axis );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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] = (hcapacity - _feedthroughs[i]) / (localCounts[i] + 1.0);
|
|
|
|
_fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)_box.getWidth();
|
2011-01-25 11:16:27 -06:00
|
|
|
|
|
|
|
// if ( ((float)ufragments[i].getMaxFree().getSize() + (float)uLengths2[i])
|
|
|
|
// > ( hcapacity * (float)_box.getWidth() ) ) {
|
|
|
|
// cerr << "INCOHERENCY: " << this << "\n "
|
|
|
|
// << "on d:" << i
|
|
|
|
// << " frag:" << DbU::getValueString(ufragments[i].getMaxFree().getSize())
|
|
|
|
// << " ulength2:" << DbU::getValueString(uLengths2[i])
|
|
|
|
// << " capacity:" << DbU::getValueString(hcapacity * _box.getWidth())
|
|
|
|
// << " " << getVectorString(_fragmentations,_depth) << endl;
|
|
|
|
|
|
|
|
// }
|
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] = (vcapacity - _feedthroughs[i]) / (localCounts[i] + 1.0);
|
|
|
|
_fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)_box.getHeight();
|
2011-01-25 11:16:27 -06:00
|
|
|
|
|
|
|
// if ( ((float)ufragments[i].getMaxFree().getSize() + (float)uLengths2[i])
|
|
|
|
// > ( vcapacity * (float)_box.getHeight() ) ) {
|
|
|
|
// cerr << "INCOHERENCY: " << this << "\n "
|
|
|
|
// << " on d:" << i
|
|
|
|
// << " frag:" << DbU::getValueString(ufragments[i].getMaxFree().getSize())
|
|
|
|
// << " ulength2:" << DbU::getValueString(uLengths2[i])
|
|
|
|
// << " capacity:" << DbU::getValueString(vcapacity * _box.getHeight())
|
|
|
|
// << " " << getVectorString(_fragmentations,_depth) << endl;
|
|
|
|
|
|
|
|
// }
|
2010-03-09 09:24:29 -06:00
|
|
|
break;
|
|
|
|
}
|
2011-01-09 12:08:31 -06:00
|
|
|
|
|
|
|
if ( _densities[i] >= 1.0 ) _saturated = true;
|
|
|
|
//if ( usedAxis[i].size() > _feedthroughs[i] ) _feedthroughs[i] = usedAxis[i].size();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
_cDensity = ( (float)_contacts.size() ) / ccapacity;
|
|
|
|
_invalid = false;
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) { _densities[i] = roundfp ( _densities[i] ); }
|
2010-03-09 09:24:29 -06:00
|
|
|
_cDensity = roundfp (_cDensity );
|
|
|
|
|
2011-01-25 11:16:27 -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
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
checkDensity ();
|
|
|
|
|
|
|
|
#if defined(CHECK_DETERMINISM)
|
|
|
|
float gdensity = getDensity();
|
|
|
|
cerr << "Order: [" << getIndex() << "] "
|
|
|
|
<< getVectorString(_densities,_depth)
|
|
|
|
<< " " << setprecision(9) << gdensity << endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ( _saturated ) ? 1 : 0 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t GCell::checkDensity () const
|
|
|
|
{
|
|
|
|
if ( _invalid ) const_cast<GCell*>(this)->updateDensity ();
|
|
|
|
|
* ./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
|
|
|
if ( not Session::getDemoMode() and Session::getWarnGCellOverload() ) {
|
2010-03-09 09:24:29 -06:00
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
|
|
|
if ( _densities[i] > 1.0 ) {
|
2012-12-03 02:28:43 -06:00
|
|
|
cinfo << 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
|
|
|
}
|
|
|
|
|
|
|
|
return ( _saturated ) ? 1 : 0 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-12 06:22:11 -05:00
|
|
|
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() );
|
|
|
|
}
|
|
|
|
|
2010-08-18 15:24:30 -05:00
|
|
|
if ( rpNets.size() < Session::getSaturateRp() ) return;
|
2010-04-12 06:22:11 -05:00
|
|
|
|
2012-12-03 02:28:43 -06:00
|
|
|
cinfo << Warning("%s has %zd terminals (h:%zd, v:%zd)"
|
|
|
|
,getString(this).c_str()
|
|
|
|
,rps.size()
|
|
|
|
,_hsegments.size()
|
|
|
|
,_vsegments.size()
|
|
|
|
) << endl;
|
2010-04-12 06:22:11 -05:00
|
|
|
|
|
|
|
AutoSegment* segment;
|
* ./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
|
|
|
while ( (_densities[1] > 0.5) and stepDesaturate(1,globalNets,segment,true) ) {
|
2010-04-17 05:14:22 -05:00
|
|
|
ltrace(200) << "Moved up: " << segment << endl;
|
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
|
|
|
{
|
|
|
|
if (_invalid) const_cast<GCell*>(this)->updateDensity();
|
|
|
|
|
|
|
|
#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
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-12 06:22:11 -05:00
|
|
|
bool GCell::stepDesaturate ( unsigned int depth, set<Net*>& globalNets, AutoSegment*& moved, bool force )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
|
|
|
#if defined(CHECK_DETERMINISM)
|
|
|
|
cerr << "Order: stepDesaturate [" << getIndex() << "] depth:" << depth << endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
updateDensity ();
|
2010-12-12 15:43:25 -06:00
|
|
|
//float density = getDensity();
|
|
|
|
moved = NULL;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
//float density = _densities[depth];
|
|
|
|
//float densityUp = _densities[depth+2];
|
|
|
|
|
2010-04-12 06:22:11 -05:00
|
|
|
if ( not force 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() );
|
|
|
|
#if defined(CHECK_DETERMINISM)
|
|
|
|
cerr << "Order: Move up " << (*isegment) << endl;
|
|
|
|
#endif
|
2010-12-12 15:43:25 -06:00
|
|
|
// cerr << "Move up " << (*isegment) << endl;
|
|
|
|
// if ( not (*isegment)->canMoveUp(0.5/*,AutoSegment::Propagate*/) ) {
|
|
|
|
// cinfo << Warning("Shear effect on: %s.",getString(*isegment).c_str()) << endl;
|
|
|
|
// return false;
|
|
|
|
// }
|
* ./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
|
|
|
|
* ./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 );
|
|
|
|
moved = (*isegment);
|
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
|
|
|
//(*isegment)->shearUp ( this, moved, 0.5, AutoSegment::AllowTerminal );
|
|
|
|
//updateDensity ();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2010-08-18 15:24:30 -05:00
|
|
|
//cmess2 << " - GCell [" << getIndex() << "] @" << getColumn() << "x" << getRow()
|
|
|
|
// << ":" << setprecision(4) << density
|
|
|
|
// << " [cap:" << _densities[depth]
|
|
|
|
// << " M+2: " << (_densities[depth+2] + (1.0 / capacity))
|
|
|
|
// << " displaced:" << (*isegment) << "]."
|
|
|
|
// << 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
|
|
|
if ( moved ) {
|
|
|
|
// cerr << "Desaturating: " << _densities[depth] << " > " << Session::getSaturateRatio() << " "
|
|
|
|
// << Session::getRoutingGauge()->getRoutingLayer(depth)->getName() << " "
|
|
|
|
// << this << endl;
|
|
|
|
// cerr << "Moved up: " << moved << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
bool GCell::stepNetDesaturate ( unsigned int depth, set<Net*>& globalNets, GCell::SetId& 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
|
|
|
{
|
|
|
|
#if defined(CHECK_DETERMINISM)
|
|
|
|
cerr << "Order: stepDesaturate [" << getIndex() << "] depth:" << depth << endl;
|
|
|
|
#endif
|
|
|
|
ltrace(200) << "stepNetDesaturate() - " << this << endl;
|
|
|
|
|
|
|
|
updateDensity ();
|
|
|
|
|
|
|
|
//if ( not force and not isSaturated(depth) ) return false;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
#if defined(CHECK_DETERMINISM)
|
|
|
|
cerr << "Order: Move up " << (*isegment) << endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//cerr << " Seed segment: " << *isegment << endl;
|
|
|
|
if ( getGCellGrid()->getKatabatic()->_moveUpNetTrunk(*isegment,globalNets,invalidateds) )
|
|
|
|
return true;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::desaturate ( unsigned int depth, set<Net*>& globalNets )
|
|
|
|
{
|
|
|
|
updateDensity ();
|
|
|
|
|
|
|
|
float density = _densities[depth];
|
|
|
|
float densityUp = _densities[depth+2];
|
|
|
|
|
|
|
|
if ( density < Session::getSaturateRatio() ) return;
|
|
|
|
|
|
|
|
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;
|
|
|
|
default:
|
|
|
|
case Constant::Vertical:
|
|
|
|
iend = _vsegments.end ();
|
|
|
|
isegment = _vsegments.begin ();
|
|
|
|
capacity = getHCapacity ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int overload = (unsigned int)( ( density - Session::getSaturateRatio() ) * capacity );
|
|
|
|
unsigned int displaced = 0;
|
|
|
|
|
|
|
|
for ( ; (isegment != iend) && (displaced < overload) ; isegment++ ) {
|
|
|
|
unsigned int segmentDepth = Session::getRoutingGauge()->getLayerDepth((*isegment)->getLayer());
|
|
|
|
|
|
|
|
if ( segmentDepth < depth ) continue;
|
|
|
|
if ( segmentDepth > depth ) break;
|
|
|
|
|
|
|
|
globalNets.insert ( (*isegment)->getNet() );
|
|
|
|
(*isegment)->changeDepth ( depth+2, false, false );
|
|
|
|
|
|
|
|
displaced++;
|
|
|
|
}
|
|
|
|
|
|
|
|
float desaturated = density - ((float)(displaced)) / capacity;
|
|
|
|
|
|
|
|
cmess2 << " - GCell [" << getIndex() << "] @" << getColumn() << "x" << getRow()
|
|
|
|
<< ":" << setprecision(4) << density
|
|
|
|
<< " -> " << desaturated
|
|
|
|
<< " [displaced:" << displaced
|
|
|
|
<< " cap:" << capacity
|
|
|
|
<< " M+2: " << densityUp
|
|
|
|
<< " -> " << (densityUp + ((float)(displaced)) / capacity) << "]."
|
|
|
|
<< endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::checkEdgeSaturation ( float threshold ) const
|
|
|
|
{
|
|
|
|
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++;
|
|
|
|
}
|
|
|
|
}
|
2010-08-22 07:37:48 -05:00
|
|
|
//edgeUpSaturation = (float)edgeUpUsage/((float)getVCapacity()*2.0);
|
|
|
|
edgeUpSaturation = (float)edgeUpUsage/getGCellGrid()->getVEdgeCapacity();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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++;
|
|
|
|
}
|
|
|
|
}
|
2010-08-22 07:37:48 -05:00
|
|
|
//edgeRightSaturation = (float)edgeRightUsage/((float)getHCapacity()*2.0);
|
|
|
|
edgeRightSaturation = (float)edgeRightUsage/getGCellGrid()->getHEdgeCapacity();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
bool overload = false;
|
|
|
|
if ( (edgeUpSaturation > threshold) or (edgeRightSaturation > threshold) ) {
|
|
|
|
overload = true;
|
|
|
|
|
2012-12-03 02:28:43 -06:00
|
|
|
cinfo << Warning("In %s, (over %.2f) ", _getString().c_str(), threshold);
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
ostringstream message;
|
|
|
|
message << setprecision(3);
|
|
|
|
if ( edgeUpSaturation > threshold )
|
2010-08-22 07:37:48 -05:00
|
|
|
message << "up edge: " << edgeUpUsage << "/" << getGCellGrid()->getVEdgeCapacity()
|
2010-03-09 09:24:29 -06:00
|
|
|
<< " " << edgeUpSaturation;
|
|
|
|
if ( edgeRightSaturation > threshold ) {
|
|
|
|
if ( message.str().size() ) message << " & ";
|
2010-08-22 07:37:48 -05:00
|
|
|
message << "right edge: " << edgeRightUsage << "/" << getGCellGrid()->getHEdgeCapacity()
|
2010-03-09 09:24:29 -06:00
|
|
|
<< " " << edgeRightSaturation;
|
|
|
|
}
|
|
|
|
|
2012-12-03 02:28:43 -06:00
|
|
|
cinfo << message.str() << "." << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return overload;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Box GCell::getBoundingBox () const
|
|
|
|
{
|
|
|
|
return _box;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::translate ( const DbU::Unit&, const DbU::Unit& )
|
|
|
|
{
|
2012-12-03 02:28:43 -06:00
|
|
|
cinfo << 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)
|
2010-03-09 09:24:29 -06:00
|
|
|
#if not defined(CHECK_DETERMINISM)
|
2010-12-12 15:43:25 -06:00
|
|
|
<< getDensity(false) << " "
|
2010-03-09 09:24:29 -06:00
|
|
|
#endif
|
2011-01-09 12:08:31 -06:00
|
|
|
<< "d:" << _depth << " "
|
|
|
|
<< getVectorString(_densities ,_depth) << " "
|
|
|
|
<< getVectorString(_feedthroughs,_depth)
|
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 ) );
|
|
|
|
record->add ( getSlot ( "_saturated" , _saturated ) );
|
|
|
|
record->add ( getSlot ( "_invalid" , _invalid ) );
|
|
|
|
|
* ./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
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Kite::DyKeyQueue".
|
|
|
|
|
|
|
|
|
|
|
|
DyKeyQueue::DyKeyQueue ( unsigned int depth )
|
|
|
|
: _depth (depth)
|
|
|
|
, _map ()
|
|
|
|
, _requests()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
DyKeyQueue::DyKeyQueue ( unsigned int depth, const vector<GCell*>& gcells )
|
|
|
|
: _depth (depth)
|
|
|
|
, _map ()
|
|
|
|
, _requests()
|
|
|
|
{
|
|
|
|
for ( size_t i=0 ; i<gcells.size() ; i++ )
|
|
|
|
_requests.insert ( gcells[i] );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DyKeyQueue::~DyKeyQueue ()
|
|
|
|
{
|
|
|
|
if ( not _requests.empty() ) {
|
2012-12-03 02:28:43 -06:00
|
|
|
cbug << Warning("~DyKeyQueue(): Still contains %d requests (and %d elements)."
|
2010-03-23 04:25:15 -05:00
|
|
|
,_requests.size(),_map.size()) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const std::set<GCell*,GCell::CompareByKey>& DyKeyQueue::getGCells () const
|
|
|
|
{ return _map; }
|
|
|
|
|
|
|
|
|
|
|
|
void DyKeyQueue::invalidate ( GCell* gcell )
|
|
|
|
{ push ( gcell ); }
|
|
|
|
|
|
|
|
|
|
|
|
void DyKeyQueue::push ( GCell* gcell )
|
|
|
|
{ _requests.insert ( gcell ); }
|
|
|
|
|
|
|
|
|
|
|
|
void DyKeyQueue::revalidate ()
|
|
|
|
{
|
2010-05-03 04:16:28 -05:00
|
|
|
ltrace(190) << "DyKeyQueue::revalidate()" << endl;
|
|
|
|
|
2010-03-23 04:25:15 -05:00
|
|
|
std::set<GCell*,GCell::CompareByKey>::iterator iinserted;
|
2011-01-09 12:08:31 -06:00
|
|
|
GCell::SetId::iterator igcell = _requests.begin();
|
|
|
|
|
|
|
|
// Remove invalidateds GCell from the queue.
|
2010-03-23 04:25:15 -05:00
|
|
|
for ( ; igcell != _requests.end() ; ++igcell ) {
|
|
|
|
iinserted = _map.find(*igcell);
|
|
|
|
if ( iinserted != _map.end() ) {
|
|
|
|
_map.erase ( iinserted );
|
|
|
|
}
|
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 ) {
|
2010-03-23 04:25:15 -05:00
|
|
|
(*igcell)->updateKey (_depth);
|
|
|
|
_map.insert ( *igcell );
|
|
|
|
}
|
2011-01-09 12:08:31 -06:00
|
|
|
|
2010-03-23 04:25:15 -05:00
|
|
|
_requests.clear ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* DyKeyQueue::pop ()
|
|
|
|
{
|
|
|
|
if ( _map.empty() ) return NULL;
|
|
|
|
std::set<GCell*,GCell::CompareByKey>::iterator igcell = _map.begin();
|
|
|
|
GCell* gcell = *igcell;
|
|
|
|
_map.erase ( igcell );
|
2010-03-26 13:02:37 -05:00
|
|
|
return gcell;
|
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.
|