2016-05-23 09:15:25 -05:00
|
|
|
// -*- mode: C++; explicit-buffer-name: "GCell.cpp<anabatic>" -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
|
|
|
// Copyright (c) UPMC 2016-2016, All Rights Reserved
|
|
|
|
//
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
// | C O R I O L I S |
|
|
|
|
// | A n a b a t i c - Global Routing Toolbox |
|
|
|
|
// | |
|
|
|
|
// | Author : Jean-Paul CHAPUT |
|
|
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
|
|
|
// | =============================================================== |
|
|
|
|
// | C++ Module : "./GCell.cpp" |
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
2016-07-18 07:48:37 -05:00
|
|
|
#include "hurricane/Bug.h"
|
|
|
|
#include "hurricane/Warning.h"
|
2016-09-10 11:49:48 -05:00
|
|
|
#include "hurricane/Breakpoint.h"
|
2016-05-30 04:30:29 -05:00
|
|
|
#include "hurricane/Contact.h"
|
2016-07-18 07:48:37 -05:00
|
|
|
#include "hurricane/RoutingPad.h"
|
2016-05-30 11:52:38 -05:00
|
|
|
#include "hurricane/UpdateSession.h"
|
2016-05-23 09:15:25 -05:00
|
|
|
#include "anabatic/GCell.h"
|
|
|
|
#include "anabatic/AnabaticEngine.h"
|
|
|
|
|
|
|
|
|
2016-07-18 07:48:37 -05:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace Hurricane;
|
|
|
|
using namespace Anabatic;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// 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 getPitch () const;
|
|
|
|
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 );
|
|
|
|
inline void setPitch ( DbU::Unit );
|
|
|
|
void merge ( DbU::Unit axis, const Interval& );
|
|
|
|
private:
|
|
|
|
DbU::Unit _pitch;
|
|
|
|
vector<Axis*> _axiss;
|
|
|
|
Interval _span;
|
|
|
|
size_t _capacity;
|
|
|
|
size_t _globals;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
UsedFragments::Axis::Axis ( UsedFragments* ufragments, DbU::Unit axis )
|
|
|
|
: _ufragments(ufragments)
|
|
|
|
, _axis (axis)
|
|
|
|
, _chunks ()
|
|
|
|
{
|
|
|
|
merge( Interval( ufragments->getMin()-ufragments->getPitch(), ufragments->getMin() ) );
|
|
|
|
merge( Interval( ufragments->getMax(), ufragments->getMax()+ufragments->getPitch() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
inline DbU::Unit UsedFragments::Axis::getAxis () const { return _axis; }
|
|
|
|
inline UsedFragments* UsedFragments::Axis::getUsedFragments () const { return _ufragments; }
|
|
|
|
|
|
|
|
|
|
|
|
void UsedFragments::Axis::merge ( const Interval& chunkMerge )
|
|
|
|
{
|
|
|
|
// cerr << " Merge @" << DbU::getValueString(_axis)
|
|
|
|
// << " " << chunkMerge << endl;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (inext == iend) break;
|
|
|
|
|
|
|
|
Interval currentFree ( (*ichunk).getVMax(), (*inext).getVMin() );
|
|
|
|
if (currentFree.getSize() > maxFree.getSize())
|
|
|
|
maxFree = currentFree;
|
|
|
|
|
|
|
|
// cerr << " @" << DbU::getValueString(_axis)
|
|
|
|
// << " before:" << *ichunk << " after:" << *inext
|
|
|
|
// << " size:" << DbU::getValueString(currentFree.getSize()) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 ()
|
|
|
|
: _pitch (0)
|
|
|
|
, _axiss ()
|
|
|
|
, _span (false)
|
|
|
|
, _capacity(0)
|
|
|
|
, _globals (0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
UsedFragments::~UsedFragments ()
|
|
|
|
{
|
|
|
|
while ( not _axiss.empty() ) {
|
|
|
|
delete (*_axiss.begin());
|
|
|
|
_axiss.erase( _axiss.begin() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline DbU::Unit UsedFragments::getPitch () const { return _pitch; }
|
|
|
|
inline DbU::Unit UsedFragments::getMin () const { return _span.getVMin(); }
|
|
|
|
inline DbU::Unit UsedFragments::getMax () const { return _span.getVMax(); }
|
|
|
|
inline void UsedFragments::setPitch ( DbU::Unit pitch ) { _pitch=pitch; }
|
|
|
|
inline void UsedFragments::setSpan ( DbU::Unit min, DbU::Unit max ) { _span=Interval(min,max); }
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
Interval restrict = chunkMerge.getIntersection(_span);
|
|
|
|
if (restrict.isEmpty()) return;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
paxis->merge( restrict );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Interval UsedFragments::getMaxFree () const
|
|
|
|
{
|
|
|
|
//cerr << "capacity:" << _capacity << " _globals:" << _globals << " _axiss:" << _axiss.size() << endl;
|
|
|
|
if (_capacity > _globals + _axiss.size() + 1) return _span;
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
namespace Anabatic {
|
|
|
|
|
|
|
|
using std::cerr;
|
|
|
|
using std::endl;
|
2016-07-18 07:48:37 -05:00
|
|
|
using Hurricane::Bug;
|
2016-05-23 09:15:25 -05:00
|
|
|
using Hurricane::Error;
|
2016-07-18 07:48:37 -05:00
|
|
|
using Hurricane::Warning;
|
2016-05-30 11:52:38 -05:00
|
|
|
using Hurricane::UpdateSession;
|
2016-07-18 07:48:37 -05:00
|
|
|
using Hurricane::Horizontal;
|
|
|
|
using Hurricane::Vertical;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Katabatic::GCell::CompareByDensity".
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
|
2016-07-18 07:48:37 -05:00
|
|
|
GCell::CompareByDensity::CompareByDensity ( size_t depth )
|
|
|
|
: _depth(depth)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::CompareByDensity::operator() ( GCell* lhs, GCell* rhs )
|
|
|
|
{
|
|
|
|
float difference = lhs->getDensity(_depth) - rhs->getDensity(_depth);
|
|
|
|
if (difference != 0.0) return (difference > 0.0);
|
|
|
|
|
|
|
|
return lhs->getId() < rhs->getId();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Anabatic::GCell".
|
|
|
|
|
2016-09-10 11:49:48 -05:00
|
|
|
Name GCell::_extensionName = "Anabatic::GCell";
|
|
|
|
unsigned int GCell::_displayMode = GCell::Boundary;
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int GCell::getDisplayMode () { return _displayMode; }
|
|
|
|
void GCell::setDisplayMode ( unsigned int mode ) { _displayMode = mode; }
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
|
|
|
|
GCell::GCell ( AnabaticEngine* anabatic, DbU::Unit xmin, DbU::Unit ymin )
|
|
|
|
: Super(anabatic->getCell())
|
2016-07-18 07:48:37 -05:00
|
|
|
, _observable ()
|
|
|
|
, _anabatic (anabatic)
|
2016-08-18 04:59:19 -05:00
|
|
|
, _flags (Flags::HChannelGCell|Flags::Invalidated)
|
2016-07-18 07:48:37 -05:00
|
|
|
, _westEdges ()
|
|
|
|
, _eastEdges ()
|
|
|
|
, _southEdges ()
|
|
|
|
, _northEdges ()
|
|
|
|
, _xmin (xmin)
|
|
|
|
, _ymin (ymin)
|
|
|
|
, _gcontacts ()
|
|
|
|
, _vsegments ()
|
|
|
|
, _hsegments ()
|
|
|
|
, _contacts ()
|
|
|
|
, _depth (Session::getRoutingGauge()->getDepth())
|
|
|
|
, _pinDepth (0)
|
|
|
|
, _blockages (new DbU::Unit [_depth])
|
|
|
|
, _cDensity (0.0)
|
|
|
|
, _densities (new float [_depth])
|
|
|
|
, _feedthroughs (new float [_depth])
|
|
|
|
, _fragmentations(new float [_depth])
|
|
|
|
, _globalsCount (new float [_depth])
|
|
|
|
, _key (this,1)
|
|
|
|
{
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
|
|
|
_blockages [i] = 0;
|
|
|
|
_densities [i] = 0.0;
|
|
|
|
_feedthroughs [i] = 0.0;
|
|
|
|
_fragmentations[i] = 0.0;
|
|
|
|
_globalsCount [i] = 0.0;
|
|
|
|
|
|
|
|
if (Session::getRoutingGauge()->getLayerGauge(i)->getType() == Constant::PinOnly)
|
|
|
|
++_pinDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
updateKey( 1 );
|
|
|
|
}
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
|
|
|
|
void GCell::_postCreate ()
|
|
|
|
{
|
|
|
|
Super::_postCreate();
|
2016-05-26 06:56:16 -05:00
|
|
|
_anabatic->_add( this );
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::create ( AnabaticEngine* anabatic )
|
|
|
|
{
|
|
|
|
if (not anabatic) throw Error( "GCell::create(): NULL anabatic argument." );
|
|
|
|
if (not anabatic->getCell()) throw Error( "GCell::create(): AnabaticEngine has no Cell loaded." );
|
|
|
|
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
anabatic->openSession();
|
2016-05-23 09:15:25 -05:00
|
|
|
GCell* gcell = new GCell ( anabatic
|
|
|
|
, anabatic->getCell()->getAbutmentBox().getXMin()
|
|
|
|
, anabatic->getCell()->getAbutmentBox().getYMin() );
|
|
|
|
gcell->_postCreate();
|
|
|
|
gcell->_revalidate();
|
2016-07-18 07:48:37 -05:00
|
|
|
Session::close();
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
return gcell;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::_create ( DbU::Unit xmin, DbU::Unit ymin )
|
|
|
|
{
|
|
|
|
GCell* gcell = new GCell ( getAnabatic(), xmin, ymin );
|
|
|
|
gcell->_postCreate();
|
|
|
|
return gcell;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell::~GCell ()
|
2016-07-18 07:48:37 -05:00
|
|
|
{
|
|
|
|
cdebug_log(145,0) << "GCell::~GCell()" << endl;
|
|
|
|
|
|
|
|
delete [] _blockages;
|
|
|
|
delete [] _densities;
|
|
|
|
delete [] _feedthroughs;
|
|
|
|
delete [] _fragmentations;
|
|
|
|
delete [] _globalsCount;
|
|
|
|
}
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
|
2016-05-26 11:30:03 -05:00
|
|
|
void GCell::_destroyEdges ()
|
2016-05-23 09:15:25 -05:00
|
|
|
{
|
2016-05-26 11:30:03 -05:00
|
|
|
while (not _westEdges.empty()) (* _westEdges.rbegin())->destroy();
|
|
|
|
while (not _eastEdges.empty()) (* _eastEdges.rbegin())->destroy();
|
|
|
|
while (not _southEdges.empty()) (*_southEdges.rbegin())->destroy();
|
|
|
|
while (not _northEdges.empty()) (*_northEdges.rbegin())->destroy();
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-26 11:30:03 -05:00
|
|
|
void GCell::_preDestroy ()
|
2016-05-23 09:15:25 -05:00
|
|
|
{
|
2016-05-26 11:30:03 -05:00
|
|
|
_destroyEdges();
|
|
|
|
_anabatic->_remove( this );
|
|
|
|
Super::_preDestroy();
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_remove ( Edge* edge, Flags side )
|
|
|
|
{
|
|
|
|
if (side.contains(Flags::WestSide )) erase_element( _westEdges, edge );
|
|
|
|
if (side.contains(Flags::EastSide )) erase_element( _eastEdges, edge );
|
|
|
|
if (side.contains(Flags::SouthSide)) erase_element( _southEdges, edge );
|
|
|
|
if (side.contains(Flags::NorthSide)) erase_element( _northEdges, edge );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_add ( Edge* edge, Flags side )
|
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,1) << "GCell::_add(side): side:" << side << " " << edge << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
if (side.contains(Flags::WestSide)) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Adding to West side of " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
for ( auto iedge=_westEdges.begin() ; iedge != _westEdges.end() ; ++iedge )
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
if ((*iedge)->getAxisMin() > edge->getAxisMin()) {
|
2016-05-23 09:15:25 -05:00
|
|
|
_westEdges.insert( iedge, edge );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_westEdges.push_back( edge );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (side.contains(Flags::EastSide)) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Adding to East side of " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
for ( auto iedge=_eastEdges.begin() ; iedge != _eastEdges.end() ; ++iedge )
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
if ((*iedge)->getAxisMin() > edge->getAxisMin()) {
|
2016-05-23 09:15:25 -05:00
|
|
|
_eastEdges.insert( iedge, edge );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_eastEdges.push_back( edge );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (side.contains(Flags::SouthSide)) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Adding to South side of " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
for ( auto iedge=_southEdges.begin() ; iedge != _southEdges.end() ; ++iedge )
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "| @" << DbU::getValueString((*iedge)->getAxisMin()) << " " << *iedge << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
for ( auto iedge=_southEdges.begin() ; iedge != _southEdges.end() ; ++iedge )
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
if ((*iedge)->getAxisMin() > edge->getAxisMin()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Insert *before* " << *iedge << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
_southEdges.insert( iedge, edge );
|
|
|
|
for ( auto iedge2=_southEdges.begin() ; iedge2 != _southEdges.end() ; ++iedge2 )
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "| @" << DbU::getValueString((*iedge2)->getAxisMin()) << " " << *iedge2 << endl;
|
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_southEdges.push_back( edge );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (side.contains(Flags::NorthSide)) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Adding to North side of " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
for ( auto iedge=_northEdges.begin() ; iedge != _northEdges.end() ; ++iedge )
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
if ((*iedge)->getAxisMin() > edge->getAxisMin()) {
|
2016-05-23 09:15:25 -05:00
|
|
|
_northEdges.insert( iedge, edge );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_northEdges.push_back( edge );
|
|
|
|
}
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
Contact* GCell::hasGContact ( const Net* net ) const
|
Anabatic transient commit 10. Ripup & reroute support in Dijsktra.
* New: In Anabatic:
- In AnabaticEngine, keep track of overflowed edges.
- In AnabaticEngine, getNetsFromedge() to lookup all nets going
through an Edge.
- In Configuration, read the Kite "reserved local" parameter to
decrease the Edge capacity (it's a guessing of the cost of the
local routing).
- In Edge, add an attribute to know if there is an associated
segment of the current net (set by Dijkstra::_traceback()).
Transparently manage the overflowed edges.
- In GCell_Edges, correct a filtering bug when not all sides are
selecteds.
- New GCell::getEdgeTo() to find the edge between two adjacent
GCells.
- New GCell::unrefContact() to automatically removes global contacts
no longer used by any global segments (used during the ripup
step).
- In Dijkstra::load(), now able to "reload" and already partially
or completly routed net (look for Contact of "gcontact" layer
and their attached segments).
- In Dijkstra, keep the last net loaded until the next one is.
Put the cleanup operations in an isolated function "_cleanup()".
- In Dijkstra::_selectFirstsource() and run(), load first source
component made of multiple vertexes.
- In Dijkstra::_trackback(), link the Net segments to the Edges.
- New Dijkstra::ripup(), Dijkstra::_propagateRipup() to perform
the ripup of one edge of a Net (must be loaded in Dijkstra first).
Dijkstra::_tagConnecteds() setup the connexId of a set of Vertexes
- that are connecteds through edges *with* segments.
- In GraphicAnabaticengine & GlobalRoute.cpp, embryo of a global
routing tool with ripup & reroute.
2016-06-26 07:32:32 -05:00
|
|
|
{
|
2016-07-18 07:48:37 -05:00
|
|
|
for ( Contact* contact : _gcontacts ) {
|
2016-07-30 05:15:49 -05:00
|
|
|
if (contact->getNet() == net) return contact;
|
Anabatic transient commit 10. Ripup & reroute support in Dijsktra.
* New: In Anabatic:
- In AnabaticEngine, keep track of overflowed edges.
- In AnabaticEngine, getNetsFromedge() to lookup all nets going
through an Edge.
- In Configuration, read the Kite "reserved local" parameter to
decrease the Edge capacity (it's a guessing of the cost of the
local routing).
- In Edge, add an attribute to know if there is an associated
segment of the current net (set by Dijkstra::_traceback()).
Transparently manage the overflowed edges.
- In GCell_Edges, correct a filtering bug when not all sides are
selecteds.
- New GCell::getEdgeTo() to find the edge between two adjacent
GCells.
- New GCell::unrefContact() to automatically removes global contacts
no longer used by any global segments (used during the ripup
step).
- In Dijkstra::load(), now able to "reload" and already partially
or completly routed net (look for Contact of "gcontact" layer
and their attached segments).
- In Dijkstra, keep the last net loaded until the next one is.
Put the cleanup operations in an isolated function "_cleanup()".
- In Dijkstra::_selectFirstsource() and run(), load first source
component made of multiple vertexes.
- In Dijkstra::_trackback(), link the Net segments to the Edges.
- New Dijkstra::ripup(), Dijkstra::_propagateRipup() to perform
the ripup of one edge of a Net (must be loaded in Dijkstra first).
Dijkstra::_tagConnecteds() setup the connexId of a set of Vertexes
- that are connecteds through edges *with* segments.
- In GraphicAnabaticengine & GlobalRoute.cpp, embryo of a global
routing tool with ripup & reroute.
2016-06-26 07:32:32 -05:00
|
|
|
}
|
2016-07-30 05:15:49 -05:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Contact* GCell::hasGContact ( const Contact* owned ) const
|
|
|
|
{
|
|
|
|
for ( Contact* contact : _gcontacts ) {
|
|
|
|
if (contact == owned) return contact;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Contact* GCell::breakGoThrough ( Net* net )
|
|
|
|
{
|
|
|
|
for ( Edge* edge : _eastEdges ) {
|
|
|
|
for ( Segment* segment : edge->getSegments() ) {
|
|
|
|
if (segment->getNet() == net)
|
|
|
|
return getAnabatic()->breakAt( segment, this );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( Edge* edge : _northEdges ) {
|
|
|
|
for ( Segment* segment : edge->getSegments() ) {
|
|
|
|
if (segment->getNet() == net)
|
|
|
|
return getAnabatic()->breakAt( segment, this );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
Anabatic transient commit 10. Ripup & reroute support in Dijsktra.
* New: In Anabatic:
- In AnabaticEngine, keep track of overflowed edges.
- In AnabaticEngine, getNetsFromedge() to lookup all nets going
through an Edge.
- In Configuration, read the Kite "reserved local" parameter to
decrease the Edge capacity (it's a guessing of the cost of the
local routing).
- In Edge, add an attribute to know if there is an associated
segment of the current net (set by Dijkstra::_traceback()).
Transparently manage the overflowed edges.
- In GCell_Edges, correct a filtering bug when not all sides are
selecteds.
- New GCell::getEdgeTo() to find the edge between two adjacent
GCells.
- New GCell::unrefContact() to automatically removes global contacts
no longer used by any global segments (used during the ripup
step).
- In Dijkstra::load(), now able to "reload" and already partially
or completly routed net (look for Contact of "gcontact" layer
and their attached segments).
- In Dijkstra, keep the last net loaded until the next one is.
Put the cleanup operations in an isolated function "_cleanup()".
- In Dijkstra::_selectFirstsource() and run(), load first source
component made of multiple vertexes.
- In Dijkstra::_trackback(), link the Net segments to the Edges.
- New Dijkstra::ripup(), Dijkstra::_propagateRipup() to perform
the ripup of one edge of a Net (must be loaded in Dijkstra first).
Dijkstra::_tagConnecteds() setup the connexId of a set of Vertexes
- that are connecteds through edges *with* segments.
- In GraphicAnabaticengine & GlobalRoute.cpp, embryo of a global
routing tool with ripup & reroute.
2016-06-26 07:32:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Edge* GCell::getEdgeTo ( GCell* neighbor, Flags sideHint ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : getEdges(sideHint) ) {
|
|
|
|
if (edge->getOpposite(this) == neighbor) return edge;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
Edge* GCell::getEdgeAt ( Flags sideHint, DbU::Unit u ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : getEdges(sideHint) ) {
|
|
|
|
GCell* side = edge->getOpposite(this);
|
|
|
|
if ( (sideHint & (Flags::WestSide |Flags::EastSide )) and (u < side->getYMax()) ) return edge;
|
|
|
|
if ( (sideHint & (Flags::SouthSide|Flags::NorthSide)) and (u < side->getXMax()) ) return edge;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-26 06:56:16 -05:00
|
|
|
GCell* GCell::getWest ( DbU::Unit y ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : _westEdges ) {
|
|
|
|
GCell* side = edge->getOpposite(this);
|
|
|
|
if (y < side->getYMax()) return side;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getEast ( DbU::Unit y ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : _eastEdges ) {
|
|
|
|
GCell* side = edge->getOpposite(this);
|
|
|
|
if (y < side->getYMax()) return side;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getSouth ( DbU::Unit x ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : _southEdges ) {
|
|
|
|
GCell* side = edge->getOpposite(this);
|
|
|
|
if (x < side->getXMax()) return side;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getNorth ( DbU::Unit x ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : _northEdges ) {
|
|
|
|
GCell* side = edge->getOpposite(this);
|
|
|
|
if (x < side->getXMax()) return side;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
GCell* GCell::getNeighborAt ( Flags side, DbU::Unit axis ) const
|
|
|
|
{
|
|
|
|
if (side & Flags::EastSide ) return getEast (axis);
|
|
|
|
if (side & Flags::WestSide ) return getWest (axis);
|
|
|
|
if (side & Flags::NorthSide) return getNorth(axis);
|
|
|
|
if (side & Flags::SouthSide) return getSouth(axis);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-26 06:56:16 -05:00
|
|
|
GCell* GCell::getUnder ( DbU::Unit x, DbU::Unit y ) const
|
|
|
|
{
|
|
|
|
const GCell* current = this;
|
|
|
|
|
2016-08-27 08:59:12 -05:00
|
|
|
if (not this) cerr << Error("*this* is NULL!") << endl;
|
|
|
|
|
2016-05-26 06:56:16 -05:00
|
|
|
while ( current ) {
|
|
|
|
if (not current->isFlat() and current->getBoundingBox().contains(x,y)) break;
|
|
|
|
|
|
|
|
if (x >= current->getXMax()) { current = current->getEast (); continue; }
|
|
|
|
if (y >= current->getYMax()) { current = current->getNorth(); continue; }
|
|
|
|
|
|
|
|
cerr << Error( "GCell::getUnder(): No GCell under (%s,%s), this must *never* happen."
|
|
|
|
, DbU::getValueString(x).c_str()
|
|
|
|
, DbU::getValueString(y).c_str()
|
|
|
|
) << endl;
|
|
|
|
current = NULL; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return const_cast<GCell*>( current );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
Box GCell::getBorder ( const GCell* s, const GCell* t )
|
|
|
|
{
|
|
|
|
Flags flags = Flags::NoFlags;
|
|
|
|
flags |= (s->getXMax() == t->getXMin()) ? Flags::EastSide : 0;
|
|
|
|
flags |= (t->getXMax() == s->getXMin()) ? Flags::WestSide : 0;
|
|
|
|
flags |= (s->getYMax() == t->getYMin()) ? Flags::NorthSide : 0;
|
|
|
|
flags |= (t->getYMax() == s->getYMin()) ? Flags::SouthSide : 0;
|
|
|
|
|
|
|
|
if (flags & Flags::Vertical) {
|
|
|
|
if (flags & Flags::Horizontal) return Box();
|
|
|
|
if (flags & Flags::WestSide)
|
|
|
|
return Box( s->getXMin(), std::max( s->getYMin(), t->getYMin() )
|
|
|
|
, s->getXMin(), std::min( s->getYMax(), t->getYMax() ) );
|
|
|
|
else
|
|
|
|
return Box( t->getXMin(), std::max( s->getYMin(), t->getYMin() )
|
|
|
|
, t->getXMin(), std::min( s->getYMax(), t->getYMax() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & Flags::Horizontal) {
|
|
|
|
if (flags & Flags::Vertical) return Box();
|
|
|
|
if (flags & Flags::NorthSide)
|
|
|
|
return Box( std::max( s->getXMin(), t->getXMin() ), t->getYMin()
|
|
|
|
, std::min( s->getXMax(), t->getXMax() ), t->getYMin() );
|
|
|
|
else
|
|
|
|
return Box( std::max( s->getXMin(), t->getXMin() ), s->getYMin()
|
|
|
|
, std::min( s->getXMax(), t->getXMax() ), s->getYMin() );
|
|
|
|
}
|
|
|
|
|
|
|
|
return Box();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::vcut ( DbU::Unit x )
|
|
|
|
{
|
2016-08-10 16:48:06 -05:00
|
|
|
cdebug_log(110,1) << "GCell::vcut() @x:" << DbU::getValueString(x) << " " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if ( (x < getXMin()) or (x > getXMax()) )
|
|
|
|
throw Error( "GCell::vcut(): Vertical cut axis at %s is outside GCell box,\n"
|
|
|
|
" in %s."
|
|
|
|
, DbU::getValueString(x).c_str()
|
|
|
|
, getString(this).c_str()
|
|
|
|
);
|
|
|
|
|
|
|
|
GCell* chunk = _create( x, getYMin() );
|
2016-08-10 16:48:06 -05:00
|
|
|
cdebug_log(110,0) << "New chunk:" << chunk << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
2016-05-26 11:30:03 -05:00
|
|
|
_moveEdges( chunk, 0, Flags::EastSide );
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( this, chunk, Flags::Horizontal );
|
|
|
|
|
|
|
|
if (not _southEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Split/create south edges." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
size_t iedge = 0;
|
|
|
|
for ( ; (iedge < _southEdges.size()) ; ++iedge ) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "[" << iedge << "] xmax of:"
|
2016-05-23 09:15:25 -05:00
|
|
|
<< _southEdges[iedge]->getOpposite(this)
|
|
|
|
<< " " << _southEdges[iedge] << endl;
|
|
|
|
if (x <= _southEdges[iedge]->getOpposite(this)->getXMax()) break;
|
|
|
|
}
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
|
|
|
|
if ( (x < _southEdges[iedge]->getOpposite(this)->getXMax())
|
|
|
|
or ( (x == _southEdges[iedge]->getOpposite(this)->getXMax())
|
|
|
|
and (chunk->getXMax() == getXMax())) )
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( _southEdges[iedge]->getOpposite(this), chunk, Flags::Vertical );
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
_moveEdges( chunk, iedge+1, Flags::SouthSide );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not _northEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Split/create north edges." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
size_t iedge = 0;
|
|
|
|
for ( ; (iedge < _northEdges.size()) ; ++iedge )
|
|
|
|
if (x <= _northEdges[iedge]->getOpposite(this)->getXMax()) break;
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
|
|
|
|
if ( (x < _northEdges[iedge]->getOpposite(this)->getXMax())
|
|
|
|
or ( (x == _northEdges[iedge]->getOpposite(this)->getXMax())
|
|
|
|
and (chunk->getXMax() == getXMax())) )
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( chunk, _northEdges[iedge]->getOpposite(this), Flags::Vertical );
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
_moveEdges( chunk, iedge+1, Flags::NorthSide );
|
|
|
|
}
|
|
|
|
|
|
|
|
_revalidate();
|
|
|
|
chunk->_revalidate();
|
|
|
|
|
2016-08-10 16:48:06 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
return chunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::hcut ( DbU::Unit y )
|
|
|
|
{
|
2016-08-10 16:48:06 -05:00
|
|
|
cdebug_log(110,1) << "GCell::hcut() @y:" << DbU::getValueString(y) << " " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if ( (y < getYMin()) or (y > getYMax()) )
|
|
|
|
throw Error( "GCell::hcut(): Horizontal cut axis at %s is outside GCell box,\n"
|
|
|
|
" in %s."
|
|
|
|
, DbU::getValueString(y).c_str()
|
|
|
|
, getString(this).c_str()
|
|
|
|
);
|
|
|
|
|
|
|
|
GCell* chunk = _create( getXMin(), y );
|
2016-08-10 16:48:06 -05:00
|
|
|
cdebug_log(110,0) << "New chunk:" << chunk << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
2016-05-26 11:30:03 -05:00
|
|
|
_moveEdges( chunk, 0, Flags::NorthSide );
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( this, chunk, Flags::Vertical );
|
|
|
|
|
|
|
|
if (not _westEdges.empty()) {
|
|
|
|
size_t iedge = 0;
|
|
|
|
for ( ; (iedge < _westEdges.size()) ; ++iedge )
|
|
|
|
if (y <= _westEdges[iedge]->getOpposite(this)->getYMax()) break;
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
|
|
|
|
if ( (y < _westEdges[iedge]->getOpposite(this)->getYMax())
|
|
|
|
or ( (y == _westEdges[iedge]->getOpposite(this)->getYMax())
|
|
|
|
and (chunk->getYMax() == getYMax())) )
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( _westEdges[iedge]->getOpposite(this), chunk, Flags::Horizontal );
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
_moveEdges( chunk, iedge+1, Flags::WestSide );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not _eastEdges.empty()) {
|
|
|
|
size_t iedge = 0;
|
|
|
|
for ( ; (iedge < _eastEdges.size()) ; ++iedge )
|
|
|
|
if (y <= _eastEdges[iedge]->getOpposite(this)->getYMax()) break;
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
|
|
|
|
if ( (y < _eastEdges[iedge]->getOpposite(this)->getYMax())
|
|
|
|
or ( (y == _eastEdges[iedge]->getOpposite(this)->getYMax())
|
|
|
|
and (chunk->getYMax() == getYMax())) )
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( chunk, _eastEdges[iedge]->getOpposite(this), Flags::Horizontal );
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
_moveEdges( chunk, iedge+1, Flags::EastSide );
|
|
|
|
}
|
|
|
|
|
|
|
|
_revalidate();
|
|
|
|
chunk->_revalidate();
|
|
|
|
|
2016-08-10 16:48:06 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
return chunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::doGrid ()
|
|
|
|
{
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
getAnabatic()->openSession();
|
2016-07-18 07:48:37 -05:00
|
|
|
|
2016-09-10 11:49:48 -05:00
|
|
|
DbU::Unit side = Session::getSliceHeight();
|
|
|
|
Interval hspan = getSide( Flags::Horizontal );
|
|
|
|
Interval vspan = getSide( Flags::Vertical );
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if (hspan.getSize() < 3*side) {
|
|
|
|
cerr << Error( "GCell::doGrid(): GCell is too narrow (dx:%s) to build a grid.\n"
|
|
|
|
" (%s)"
|
|
|
|
, DbU::getValueString(hspan.getSize()).c_str()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
2016-07-18 07:48:37 -05:00
|
|
|
Session::close();
|
2016-05-23 09:15:25 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vspan.getSize() < 3*side) {
|
|
|
|
cerr << Error( "GCell::doGrid(): GCell is too narrow (dy:%s) to build a grid.\n"
|
|
|
|
" (%s)"
|
|
|
|
, DbU::getValueString(vspan.getSize()).c_str()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
GCell* row = this;
|
|
|
|
GCell* column = NULL;
|
|
|
|
DbU::Unit ycut = vspan.getVMin()+side;
|
|
|
|
for ( ; ycut < vspan.getVMax() ; ycut += side ) {
|
|
|
|
column = row;
|
|
|
|
row = row->hcut( ycut );
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
row->setType( Flags::MatrixGCell );
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
for ( DbU::Unit xcut = hspan.getVMin()+side ; xcut < hspan.getVMax() ; xcut += side ) {
|
|
|
|
column = column->vcut( xcut );
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
column->setType( Flags::MatrixGCell );
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
column = row;
|
|
|
|
for ( DbU::Unit xcut = hspan.getVMin()+side ; xcut < hspan.getVMax() ; xcut += side ) {
|
|
|
|
column = column->vcut( xcut );
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
column->setType( Flags::MatrixGCell );
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
Solve the template lookup problem in tstream.
* Bug: In Hurricane, in tstream (Commons.h), in the *template* overload of
operator<<(), do not use the operator<<() of ostream as it will be
looked up in "stage 1" (template definition) and so will miss all the
overloads added later and built over getString<>(). Instead, make use
of getString<>(), which, as another template will be looked up in
"stage 2" (template instanciation) and at that point will have all the
needed template specialisation of getString<>().
We also need to define new stream manipulators to be able to create
a matching template overload not dependant from the implementation.
To avoid name clashes, we prefix a 't'. For now, only 'tsetw()' is
refined.
As a side effect, we cannot directly print bit-fields into the stream,
we must go through an intermediate variable (happens once in AutoContact).
2016-07-19 09:02:55 -05:00
|
|
|
setType( Flags::MatrixGCell );
|
|
|
|
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
//size_t hLocal = - getAnabatic()->getConfiguration()->getHEdgeLocal();
|
|
|
|
//size_t vLocal = - getAnabatic()->getConfiguration()->getVEdgeLocal();
|
|
|
|
//for ( ; ibegin < gcells.size() ; ++ibegin ) {
|
|
|
|
// gcells[ibegin]->setType( Flags::MatrixGCell );
|
Solve the template lookup problem in tstream.
* Bug: In Hurricane, in tstream (Commons.h), in the *template* overload of
operator<<(), do not use the operator<<() of ostream as it will be
looked up in "stage 1" (template definition) and so will miss all the
overloads added later and built over getString<>(). Instead, make use
of getString<>(), which, as another template will be looked up in
"stage 2" (template instanciation) and at that point will have all the
needed template specialisation of getString<>().
We also need to define new stream manipulators to be able to create
a matching template overload not dependant from the implementation.
To avoid name clashes, we prefix a 't'. For now, only 'tsetw()' is
refined.
As a side effect, we cannot directly print bit-fields into the stream,
we must go through an intermediate variable (happens once in AutoContact).
2016-07-19 09:02:55 -05:00
|
|
|
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
// for ( Edge* edge : gcells[ibegin]->getEdges(Flags::NorthSide|Flags::EastSide) ) {
|
|
|
|
// if (edge->isHorizontal()) edge->incCapacity( hLocal );
|
|
|
|
// else edge->incCapacity( vLocal );
|
|
|
|
// }
|
|
|
|
//}
|
Anabatic transient commit 10. Ripup & reroute support in Dijsktra.
* New: In Anabatic:
- In AnabaticEngine, keep track of overflowed edges.
- In AnabaticEngine, getNetsFromedge() to lookup all nets going
through an Edge.
- In Configuration, read the Kite "reserved local" parameter to
decrease the Edge capacity (it's a guessing of the cost of the
local routing).
- In Edge, add an attribute to know if there is an associated
segment of the current net (set by Dijkstra::_traceback()).
Transparently manage the overflowed edges.
- In GCell_Edges, correct a filtering bug when not all sides are
selecteds.
- New GCell::getEdgeTo() to find the edge between two adjacent
GCells.
- New GCell::unrefContact() to automatically removes global contacts
no longer used by any global segments (used during the ripup
step).
- In Dijkstra::load(), now able to "reload" and already partially
or completly routed net (look for Contact of "gcontact" layer
and their attached segments).
- In Dijkstra, keep the last net loaded until the next one is.
Put the cleanup operations in an isolated function "_cleanup()".
- In Dijkstra::_selectFirstsource() and run(), load first source
component made of multiple vertexes.
- In Dijkstra::_trackback(), link the Net segments to the Edges.
- New Dijkstra::ripup(), Dijkstra::_propagateRipup() to perform
the ripup of one edge of a Net (must be loaded in Dijkstra first).
Dijkstra::_tagConnecteds() setup the connexId of a set of Vertexes
- that are connecteds through edges *with* segments.
- In GraphicAnabaticengine & GlobalRoute.cpp, embryo of a global
routing tool with ripup & reroute.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-18 07:48:37 -05:00
|
|
|
Session::close();
|
2016-05-23 09:15:25 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_revalidate ()
|
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,1) << "GCell::revalidate() " << this << endl;
|
|
|
|
cdebug_log(110,1) << "West side." << endl; for ( Edge* edge : _westEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
|
|
|
cdebug_log(110,1) << "East side." << endl; for ( Edge* edge : _eastEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
|
|
|
cdebug_log(110,1) << "South side." << endl; for ( Edge* edge : _southEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
|
|
|
cdebug_log(110,1) << "North side." << endl; for ( Edge* edge : _northEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
|
2016-05-26 06:56:16 -05:00
|
|
|
if (_xmin > getXMax()+1)
|
|
|
|
cerr << Error( "GCell::_revalidate(): %s, X Min is greater than Max.", getString(this).c_str() );
|
|
|
|
if (_ymin > getYMax()+1)
|
|
|
|
cerr << Error( "GCell::_revalidate(): %s, Y Min is greater than Max.", getString(this).c_str() );
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
_anabatic->_updateLookup( this );
|
2016-08-27 08:59:12 -05:00
|
|
|
//_anabatic->getMatrix()->show();
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_moveEdges ( GCell* dest, size_t ibegin, Flags flags )
|
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,1) << "GCell::_moveEdges() " << this << endl;
|
|
|
|
cdebug_log(110,0) << " toward " << dest << endl;
|
|
|
|
cdebug_log(110,0) << " ibegin: " << ibegin << " flags:" << flags << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
size_t iclear = ibegin;
|
|
|
|
|
|
|
|
if (flags.contains(Flags::SouthSide) and not _southEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "South side." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if (iclear < _southEdges.size()) {
|
|
|
|
for ( size_t iedge=ibegin ; (iedge < _southEdges.size()) ; ++iedge ) {
|
2016-05-26 06:56:16 -05:00
|
|
|
_southEdges[iedge]->_setTarget( dest );
|
2016-05-23 09:15:25 -05:00
|
|
|
dest->_southEdges.push_back( _southEdges[iedge] );
|
|
|
|
}
|
|
|
|
_southEdges.resize( iclear );
|
|
|
|
} else {
|
|
|
|
if (iclear > _southEdges.size())
|
|
|
|
cerr << Error("GCell::_moveEdges(): On south side, iclear=%u is greater than size()-1=%u\n"
|
|
|
|
" (%s)"
|
|
|
|
, iclear
|
|
|
|
, _southEdges.size()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags.contains(Flags::NorthSide) and not _northEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "North side." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if (iclear < _northEdges.size()) {
|
|
|
|
for ( size_t iedge=ibegin ; (iedge < _northEdges.size()) ; ++iedge ) {
|
2016-05-26 06:56:16 -05:00
|
|
|
_northEdges[iedge]->_setSource( dest );
|
2016-05-23 09:15:25 -05:00
|
|
|
dest->_northEdges.push_back( _northEdges[iedge] );
|
|
|
|
}
|
|
|
|
_northEdges.resize( iclear );
|
|
|
|
} else {
|
|
|
|
if (iclear > _northEdges.size())
|
|
|
|
cerr << Error("GCell::_moveEdges(): On north side, iclear=%u is greater than size()-1=%u\n"
|
|
|
|
" (%s)"
|
|
|
|
, iclear
|
|
|
|
, _northEdges.size()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags.contains(Flags::WestSide) and not _westEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "West side." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if (iclear < _westEdges.size()) {
|
|
|
|
for ( size_t iedge=ibegin ; (iedge < _westEdges.size()) ; ++iedge ) {
|
2016-05-26 06:56:16 -05:00
|
|
|
_westEdges[iedge]->_setTarget( dest );
|
2016-05-23 09:15:25 -05:00
|
|
|
dest->_westEdges.push_back( _westEdges[iedge] );
|
|
|
|
}
|
|
|
|
_westEdges.resize( iclear );
|
|
|
|
} else {
|
|
|
|
if (iclear > _westEdges.size())
|
|
|
|
cerr << Error("GCell::_moveEdges(): On west side, iclear=%u is greater than size()-1=%u\n"
|
|
|
|
" (%s)"
|
|
|
|
, iclear
|
|
|
|
, _westEdges.size()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags.contains(Flags::EastSide) and not _eastEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "East side." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if (iclear < _eastEdges.size()) {
|
|
|
|
for ( size_t iedge=ibegin ; (iedge < _eastEdges.size()) ; ++iedge ) {
|
2016-05-26 06:56:16 -05:00
|
|
|
_eastEdges[iedge]->_setSource( dest );
|
2016-05-23 09:15:25 -05:00
|
|
|
dest->_eastEdges.push_back( _eastEdges[iedge] );
|
|
|
|
}
|
|
|
|
_eastEdges.resize( iclear );
|
|
|
|
} else {
|
|
|
|
if (iclear > _eastEdges.size())
|
|
|
|
cerr << Error("GCell::_moveEdges(): On east side, iclear=%u is greater than size()-1=%u\n"
|
|
|
|
" (%s)"
|
|
|
|
, iclear
|
|
|
|
, _eastEdges.size()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-18 07:57:58 -05:00
|
|
|
void GCell::setXY ( DbU::Unit x, DbU::Unit y )
|
|
|
|
{
|
|
|
|
UpdateSession::open();
|
|
|
|
_xmin = x;
|
|
|
|
_ymin = y;
|
|
|
|
UpdateSession::close();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::updateContactsPosition ()
|
|
|
|
{
|
|
|
|
UpdateSession::open();
|
|
|
|
DbU::Unit xc = (getXMax() + getXMin())/2;
|
|
|
|
DbU::Unit yc = (getYMax() + getYMin())/2;
|
|
|
|
for (vector<Contact*>::iterator it = _gcontacts.begin(); it != _gcontacts.end(); it++){
|
|
|
|
for ( Component* c : (*it)->getSlaveComponents() ){
|
|
|
|
Horizontal* h = dynamic_cast<Horizontal*>(c);
|
|
|
|
Vertical* v = dynamic_cast<Vertical*> (c);
|
|
|
|
if (h){
|
|
|
|
//if (h->getY() == (*it)->getY()) h->setY(yc);
|
|
|
|
h->setY(yc);
|
|
|
|
} else if (v) {
|
|
|
|
//if (v->getX() == (*it)->getX()) v->setX(xc);
|
|
|
|
v->setX(xc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(*it)->setX(xc);
|
|
|
|
(*it)->setY(yc);
|
|
|
|
}
|
|
|
|
UpdateSession::close();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
Contact* GCell::getGContact ( Net* net )
|
|
|
|
{
|
2016-07-18 07:48:37 -05:00
|
|
|
for ( Contact* contact : _gcontacts ) {
|
2016-05-30 11:52:38 -05:00
|
|
|
if (contact->getNet() == net) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(111,0) << "GCell::getGContact(): " << contact << endl;
|
2016-05-30 11:52:38 -05:00
|
|
|
return contact;
|
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
2016-05-30 11:52:38 -05:00
|
|
|
Point center = getBoundingBox().getCenter();
|
|
|
|
Contact* contact = Contact::create( net
|
|
|
|
, _anabatic->getConfiguration()->getGContactLayer()
|
|
|
|
, center.getX()
|
|
|
|
, center.getY()
|
|
|
|
, DbU::fromLambda(2.0)
|
|
|
|
, DbU::fromLambda(2.0)
|
|
|
|
);
|
2016-07-18 07:48:37 -05:00
|
|
|
_gcontacts.push_back( contact );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(111,0) << "GCell::getGContact(): " << contact << endl;
|
2016-05-30 11:52:38 -05:00
|
|
|
return contact;
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Anabatic transient commit 10. Ripup & reroute support in Dijsktra.
* New: In Anabatic:
- In AnabaticEngine, keep track of overflowed edges.
- In AnabaticEngine, getNetsFromedge() to lookup all nets going
through an Edge.
- In Configuration, read the Kite "reserved local" parameter to
decrease the Edge capacity (it's a guessing of the cost of the
local routing).
- In Edge, add an attribute to know if there is an associated
segment of the current net (set by Dijkstra::_traceback()).
Transparently manage the overflowed edges.
- In GCell_Edges, correct a filtering bug when not all sides are
selecteds.
- New GCell::getEdgeTo() to find the edge between two adjacent
GCells.
- New GCell::unrefContact() to automatically removes global contacts
no longer used by any global segments (used during the ripup
step).
- In Dijkstra::load(), now able to "reload" and already partially
or completly routed net (look for Contact of "gcontact" layer
and their attached segments).
- In Dijkstra, keep the last net loaded until the next one is.
Put the cleanup operations in an isolated function "_cleanup()".
- In Dijkstra::_selectFirstsource() and run(), load first source
component made of multiple vertexes.
- In Dijkstra::_trackback(), link the Net segments to the Edges.
- New Dijkstra::ripup(), Dijkstra::_propagateRipup() to perform
the ripup of one edge of a Net (must be loaded in Dijkstra first).
Dijkstra::_tagConnecteds() setup the connexId of a set of Vertexes
- that are connecteds through edges *with* segments.
- In GraphicAnabaticengine & GlobalRoute.cpp, embryo of a global
routing tool with ripup & reroute.
2016-06-26 07:32:32 -05:00
|
|
|
bool GCell::unrefContact ( Contact* unref )
|
|
|
|
{
|
2016-07-18 07:48:37 -05:00
|
|
|
if (_gcontacts.empty()) return false;
|
Anabatic transient commit 10. Ripup & reroute support in Dijsktra.
* New: In Anabatic:
- In AnabaticEngine, keep track of overflowed edges.
- In AnabaticEngine, getNetsFromedge() to lookup all nets going
through an Edge.
- In Configuration, read the Kite "reserved local" parameter to
decrease the Edge capacity (it's a guessing of the cost of the
local routing).
- In Edge, add an attribute to know if there is an associated
segment of the current net (set by Dijkstra::_traceback()).
Transparently manage the overflowed edges.
- In GCell_Edges, correct a filtering bug when not all sides are
selecteds.
- New GCell::getEdgeTo() to find the edge between two adjacent
GCells.
- New GCell::unrefContact() to automatically removes global contacts
no longer used by any global segments (used during the ripup
step).
- In Dijkstra::load(), now able to "reload" and already partially
or completly routed net (look for Contact of "gcontact" layer
and their attached segments).
- In Dijkstra, keep the last net loaded until the next one is.
Put the cleanup operations in an isolated function "_cleanup()".
- In Dijkstra::_selectFirstsource() and run(), load first source
component made of multiple vertexes.
- In Dijkstra::_trackback(), link the Net segments to the Edges.
- New Dijkstra::ripup(), Dijkstra::_propagateRipup() to perform
the ripup of one edge of a Net (must be loaded in Dijkstra first).
Dijkstra::_tagConnecteds() setup the connexId of a set of Vertexes
- that are connecteds through edges *with* segments.
- In GraphicAnabaticengine & GlobalRoute.cpp, embryo of a global
routing tool with ripup & reroute.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
cdebug_log(112,0) << "GCell::unrefContact(): " << unref << endl;
|
|
|
|
|
2016-07-18 07:48:37 -05:00
|
|
|
for ( size_t i=0 ; i< _gcontacts.size() ; ++i ) {
|
|
|
|
if (_gcontacts[i] == unref) {
|
|
|
|
if (_gcontacts[i]->getSlaveComponents().getLocator()->isValid()) return false;
|
Anabatic transient commit 10. Ripup & reroute support in Dijsktra.
* New: In Anabatic:
- In AnabaticEngine, keep track of overflowed edges.
- In AnabaticEngine, getNetsFromedge() to lookup all nets going
through an Edge.
- In Configuration, read the Kite "reserved local" parameter to
decrease the Edge capacity (it's a guessing of the cost of the
local routing).
- In Edge, add an attribute to know if there is an associated
segment of the current net (set by Dijkstra::_traceback()).
Transparently manage the overflowed edges.
- In GCell_Edges, correct a filtering bug when not all sides are
selecteds.
- New GCell::getEdgeTo() to find the edge between two adjacent
GCells.
- New GCell::unrefContact() to automatically removes global contacts
no longer used by any global segments (used during the ripup
step).
- In Dijkstra::load(), now able to "reload" and already partially
or completly routed net (look for Contact of "gcontact" layer
and their attached segments).
- In Dijkstra, keep the last net loaded until the next one is.
Put the cleanup operations in an isolated function "_cleanup()".
- In Dijkstra::_selectFirstsource() and run(), load first source
component made of multiple vertexes.
- In Dijkstra::_trackback(), link the Net segments to the Edges.
- New Dijkstra::ripup(), Dijkstra::_propagateRipup() to perform
the ripup of one edge of a Net (must be loaded in Dijkstra first).
Dijkstra::_tagConnecteds() setup the connexId of a set of Vertexes
- that are connecteds through edges *with* segments.
- In GraphicAnabaticengine & GlobalRoute.cpp, embryo of a global
routing tool with ripup & reroute.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
cdebug_log(112,0) << " Effective destroy." << endl;
|
2016-07-18 07:48:37 -05:00
|
|
|
std::swap( _gcontacts[i], _gcontacts[_gcontacts.size()-1] );
|
|
|
|
_gcontacts[ _gcontacts.size()-1 ]->destroy();
|
|
|
|
_gcontacts.pop_back();
|
Anabatic transient commit 10. Ripup & reroute support in Dijsktra.
* New: In Anabatic:
- In AnabaticEngine, keep track of overflowed edges.
- In AnabaticEngine, getNetsFromedge() to lookup all nets going
through an Edge.
- In Configuration, read the Kite "reserved local" parameter to
decrease the Edge capacity (it's a guessing of the cost of the
local routing).
- In Edge, add an attribute to know if there is an associated
segment of the current net (set by Dijkstra::_traceback()).
Transparently manage the overflowed edges.
- In GCell_Edges, correct a filtering bug when not all sides are
selecteds.
- New GCell::getEdgeTo() to find the edge between two adjacent
GCells.
- New GCell::unrefContact() to automatically removes global contacts
no longer used by any global segments (used during the ripup
step).
- In Dijkstra::load(), now able to "reload" and already partially
or completly routed net (look for Contact of "gcontact" layer
and their attached segments).
- In Dijkstra, keep the last net loaded until the next one is.
Put the cleanup operations in an isolated function "_cleanup()".
- In Dijkstra::_selectFirstsource() and run(), load first source
component made of multiple vertexes.
- In Dijkstra::_trackback(), link the Net segments to the Edges.
- New Dijkstra::ripup(), Dijkstra::_propagateRipup() to perform
the ripup of one edge of a Net (must be loaded in Dijkstra first).
Dijkstra::_tagConnecteds() setup the connexId of a set of Vertexes
- that are connecteds through edges *with* segments.
- In GraphicAnabaticengine & GlobalRoute.cpp, embryo of a global
routing tool with ripup & reroute.
2016-06-26 07:32:32 -05:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-18 07:48:37 -05:00
|
|
|
void GCell::cleanupGlobal ()
|
|
|
|
{
|
|
|
|
for ( size_t i=0 ; i<_gcontacts.size() ; ) {
|
|
|
|
if (not _gcontacts[i]->getSlaveComponents().getLocator()->isValid()) {
|
|
|
|
std::swap( _gcontacts[i], _gcontacts[_gcontacts.size()-1] );
|
|
|
|
_gcontacts[ _gcontacts.size()-1 ]->destroy();
|
|
|
|
_gcontacts.pop_back();
|
|
|
|
} else
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
const Name& GCell::getName () const
|
|
|
|
{ return _extensionName; }
|
|
|
|
|
|
|
|
|
|
|
|
Box GCell::getBoundingBox () const
|
|
|
|
{
|
2016-05-26 06:56:16 -05:00
|
|
|
return Box( getXMin(), getYMin(), getXMax(1), getYMax(1) );
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::translate ( const DbU::Unit&, const DbU::Unit& )
|
|
|
|
{
|
|
|
|
cerr << Error( "GCell::translate(): On %s,\n"
|
|
|
|
" Must never be called on a GCell object (ignored)."
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-26 07:55:34 -05:00
|
|
|
bool GCell::isNorth ( GCell* c ) const
|
2016-06-17 09:26:27 -05:00
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (vector<Edge*>::const_iterator it = _northEdges.begin(); it != _northEdges.end(); it++){
|
2016-06-20 11:36:00 -05:00
|
|
|
if ( (*it)->getOpposite(this)->getId() == c->getId() ) {
|
2016-06-17 09:26:27 -05:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-26 07:55:34 -05:00
|
|
|
bool GCell::isSouth ( GCell* c ) const
|
2016-06-17 09:26:27 -05:00
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (vector<Edge*>::const_iterator it = _southEdges.begin(); it != _southEdges.end(); it++){
|
2016-06-20 11:36:00 -05:00
|
|
|
if ( (*it)->getOpposite(this)->getId() == c->getId() ) {
|
2016-06-17 09:26:27 -05:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-26 07:55:34 -05:00
|
|
|
bool GCell::isEast ( GCell* c ) const
|
2016-06-17 09:26:27 -05:00
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (vector<Edge*>::const_iterator it = _eastEdges.begin(); it != _eastEdges.end(); it++){
|
2016-06-20 11:36:00 -05:00
|
|
|
if ( (*it)->getOpposite(this)->getId() == c->getId() ) {
|
2016-06-17 09:26:27 -05:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-26 07:55:34 -05:00
|
|
|
bool GCell::isWest ( GCell* c ) const
|
2016-06-17 09:26:27 -05:00
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (vector<Edge*>::const_iterator it = _westEdges.begin(); it != _westEdges.end(); it++){
|
2016-06-20 11:36:00 -05:00
|
|
|
if ( (*it)->getOpposite(this)->getId() == c->getId() ) {
|
2016-06-17 09:26:27 -05:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-18 07:48:37 -05:00
|
|
|
bool GCell::isSaturated ( size_t depth ) const
|
|
|
|
{ return getDensity(depth) > Session::getSaturateRatio(); }
|
|
|
|
|
|
|
|
|
|
|
|
Interval GCell::getSide ( unsigned int direction ) const
|
|
|
|
{
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
if (direction & Flags::Vertical) return Interval( getYMin(), getYMax() );
|
|
|
|
return Interval( getXMin(), getXMax() );
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getHStartSegments ()
|
|
|
|
{ return new AutoSegments_AnchorOnGCell (this,Flags::EastSide); }
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getVStartSegments ()
|
|
|
|
{ return new AutoSegments_AnchorOnGCell (this,Flags::NorthSide); }
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getHStopSegments ()
|
|
|
|
{ return new AutoSegments_AnchorOnGCell (this,Flags::WestSide); }
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments GCell::getVStopSegments ()
|
|
|
|
{ return new AutoSegments_AnchorOnGCell (this,Flags::SouthSide); }
|
|
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float GCell::getHCapacity () const
|
|
|
|
{
|
|
|
|
int capacity = 0;
|
|
|
|
if (not _eastEdges.empty()) {
|
|
|
|
for ( Edge* edge : _eastEdges ) capacity += edge->getCapacity();
|
|
|
|
} else {
|
|
|
|
for ( Edge* edge : _westEdges ) capacity += edge->getCapacity();
|
|
|
|
}
|
|
|
|
return (float)capacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float GCell::getVCapacity () const
|
|
|
|
{
|
|
|
|
int capacity = 0;
|
|
|
|
if (not _northEdges.empty()) {
|
|
|
|
for ( Edge* edge : _northEdges ) capacity += edge->getCapacity();
|
|
|
|
} else {
|
|
|
|
for ( Edge* edge : _southEdges ) capacity += edge->getCapacity();
|
|
|
|
}
|
|
|
|
return (float)capacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float GCell::getAverageHVDensity () const
|
|
|
|
{
|
|
|
|
// Average density of all layers mixeds together.
|
|
|
|
float density = 0.0;
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ )
|
|
|
|
density += _densities[i];
|
|
|
|
return density / ((float)(_depth-_pinDepth));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float GCell::getMaxHVDensity () const
|
|
|
|
{
|
|
|
|
// Maximum density between all horizontal vs. all vertical layers.
|
|
|
|
size_t hplanes = 0;
|
|
|
|
size_t vplanes = 0;
|
|
|
|
float hdensity = 0.0;
|
|
|
|
float vdensity = 0.0;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
return std::max(hdensity, vdensity);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float GCell::getDensity ( unsigned int flags ) const
|
|
|
|
{
|
|
|
|
if (isInvalidated() and not(flags & Flags::NoUpdate)) const_cast<GCell*>(this)->updateDensity();
|
|
|
|
|
|
|
|
float density = 0.0;
|
|
|
|
|
|
|
|
if (getAnabatic()->getDensityMode() == AverageHVDensity) {
|
|
|
|
density = getAverageHVDensity();
|
|
|
|
} else if (getAnabatic()->getDensityMode() == MaxHVDensity) {
|
|
|
|
density = getMaxHVDensity();
|
|
|
|
} else if (getAnabatic()->getDensityMode() == AverageHDensity) {
|
|
|
|
size_t hplanes = 0;
|
|
|
|
float hdensity = 0.0;
|
|
|
|
|
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
|
|
|
if (i%2) { hdensity += _densities[i]; ++hplanes; }
|
|
|
|
}
|
|
|
|
if (hplanes) hdensity /= hplanes;
|
|
|
|
|
|
|
|
density = hdensity;
|
|
|
|
} else if (getAnabatic()->getDensityMode() == AverageVDensity) {
|
|
|
|
size_t vplanes = 0;
|
|
|
|
float vdensity = 0.0;
|
|
|
|
|
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
|
|
|
if (i%2 == 0) { vdensity += _densities[i]; ++vplanes; }
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vplanes) vdensity /= vplanes;
|
|
|
|
|
|
|
|
density = vdensity;
|
|
|
|
} else if (getAnabatic()->getDensityMode() == MaxDensity) {
|
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
|
|
|
if (_densities[i] > density) density = _densities[i];
|
|
|
|
}
|
|
|
|
} else if (getAnabatic()->getDensityMode() == MaxHDensity) {
|
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
|
|
|
if ((i%2) and (_densities[i] > density)) density = _densities[i];
|
|
|
|
}
|
|
|
|
} else if (getAnabatic()->getDensityMode() == MaxVDensity) {
|
|
|
|
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
|
|
|
|
if ((i%2 == 0) and (_densities[i] > density)) density = _densities[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return density;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::addBlockage ( size_t depth, DbU::Unit length )
|
|
|
|
{
|
|
|
|
if (depth >= _depth) return;
|
|
|
|
|
|
|
|
_blockages[depth] += length;
|
|
|
|
_flags |= Flags::Invalidated;
|
|
|
|
|
|
|
|
cdebug_log(149,0) << "GCell:addBlockage() " << this << " "
|
|
|
|
<< depth << ":" << DbU::getValueString(_blockages[depth]) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
cdebug_log(149,0) << "remove " << 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::removeHSegment ( AutoSegment* segment )
|
|
|
|
{
|
|
|
|
size_t end = _hsegments.size();
|
|
|
|
size_t begin = 0;
|
|
|
|
|
|
|
|
for ( ; begin < end ; begin++ ) {
|
|
|
|
if (_hsegments[begin] == segment) std::swap( _hsegments[begin], _hsegments[--end] );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_hsegments.size() == end) {
|
|
|
|
cerr << Bug( "%s do not go through %s."
|
2016-08-30 09:05:15 -05:00
|
|
|
, getString(segment).c_str(), _getString().c_str() ) << endl;
|
2016-07-18 07:48:37 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_hsegments.size() - end > 1)
|
|
|
|
cerr << Bug( "%s has multiple occurrences of %s."
|
2016-08-30 09:05:15 -05:00
|
|
|
, _getString().c_str(), getString(segment).c_str() ) << endl;
|
2016-07-18 07:48:37 -05:00
|
|
|
|
|
|
|
_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) std::swap( _vsegments[begin], _vsegments[--end] );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_vsegments.size() == end) {
|
|
|
|
cerr << Bug( "%s do not go through %s."
|
|
|
|
, getString(segment).c_str()
|
|
|
|
, _getString().c_str() ) << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_vsegments.size() - end > 1)
|
|
|
|
cerr << Bug( "%s has multiple occurrences of %s."
|
|
|
|
, _getString().c_str()
|
|
|
|
, getString(segment).c_str() ) << endl;
|
|
|
|
|
|
|
|
_vsegments.erase( _vsegments.begin() + end, _vsegments.end() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::updateContacts ()
|
|
|
|
{ for ( AutoContact* contact : _contacts ) contact->updateGeometry(); }
|
|
|
|
|
|
|
|
|
|
|
|
size_t GCell::updateDensity ()
|
|
|
|
{
|
|
|
|
if (not isInvalidated()) return (isSaturated()) ? 1 : 0;
|
|
|
|
|
|
|
|
_flags.reset( Flags::Saturated );
|
|
|
|
|
|
|
|
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() );
|
|
|
|
|
|
|
|
float hcapacity = getHCapacity ();
|
|
|
|
float vcapacity = getVCapacity ();
|
|
|
|
float ccapacity = hcapacity * vcapacity * 4;
|
|
|
|
DbU::Unit width = getXMax() - getXMin();
|
|
|
|
DbU::Unit height = getYMax() - getYMin();
|
|
|
|
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 ];
|
|
|
|
vector<UsedFragments> ufragments ( _depth );
|
|
|
|
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
|
|
|
ufragments[i].setPitch ( Session::getPitch(i) );
|
|
|
|
_feedthroughs[i] = 0.0;
|
|
|
|
uLengths2 [i] = 0;
|
|
|
|
localCounts [i] = 0.0;
|
|
|
|
_globalsCount[i] = 0.0;
|
|
|
|
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
if (Session::getDirection(i) & Flags::Horizontal) {
|
|
|
|
ufragments[i].setSpan ( getXMin(), getXMax() );
|
|
|
|
ufragments[i].setCapacity( (size_t)hcapacity );
|
|
|
|
} else {
|
|
|
|
ufragments[i].setSpan ( getYMin(), getYMax() );
|
|
|
|
ufragments[i].setCapacity( (size_t)vcapacity );
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute wirelength associated to contacts (in DbU::Unit converted to float).
|
|
|
|
AutoSegment::DepthLengthSet processeds;
|
|
|
|
for ( AutoContact* contact : _contacts ) {
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) uLengths1[i] = 0;
|
|
|
|
contact->getLengths ( uLengths1, processeds );
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
if (Session::getDirection(i) & Flags::Horizontal)
|
|
|
|
uLengths2[i] += uLengths1[i]+hpenalty;
|
|
|
|
else
|
|
|
|
uLengths2[i] += uLengths1[i]+vpenalty; break;
|
2016-07-18 07:48:37 -05: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++ ) {
|
|
|
|
_globalsCount[depth] += 1.0;
|
|
|
|
ufragments[depth].incGlobals();
|
|
|
|
|
|
|
|
if ( layer != _hsegments[i]->getLayer() ) {
|
|
|
|
uLengths2[depth] += count * width;
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
layer = _hsegments[i]->getLayer();
|
|
|
|
depth = Session::getRoutingGauge()->getLayerDepth(layer);
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
_feedthroughs[depth] += 1.0;
|
|
|
|
}
|
|
|
|
if ( count ) {
|
|
|
|
uLengths2[depth] += count * width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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++ ) {
|
|
|
|
_globalsCount[depth] += 1.0;
|
|
|
|
ufragments[depth].incGlobals();
|
|
|
|
|
|
|
|
if ( layer != _vsegments[i]->getLayer() ) {
|
|
|
|
uLengths2[depth] += count * height;
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
layer = _vsegments[i]->getLayer();
|
|
|
|
depth = Session::getRoutingGauge()->getLayerDepth(layer);
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
_feedthroughs[depth] += 1.0;
|
|
|
|
}
|
|
|
|
if ( count ) {
|
|
|
|
uLengths2[depth] += count * height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the blockages.
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
|
|
|
uLengths2[i] += _blockages[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
ufragments[depth].merge( (*isegment)->getAxis(), (*isegment)->getSpanU() );
|
|
|
|
if ( (axis != (*isegment)->getAxis()) or (layer != (*isegment)->getLayer()) ) {
|
|
|
|
count = 0;
|
|
|
|
axis = (*isegment)->getAxis();
|
|
|
|
layer = (*isegment)->getLayer();
|
|
|
|
depth = Session::getRoutingGauge()->getLayerDepth(layer);
|
|
|
|
}
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Normalize: 0 < d < 1.0 (divide by H/V capacity).
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
if (Session::getDirection(i) & Flags::Horizontal) {
|
|
|
|
if (width) {
|
|
|
|
_densities [i] = ((float)uLengths2[i]) / ( hcapacity * (float)width );
|
|
|
|
_feedthroughs [i] += (float)(_blockages[i] / width);
|
|
|
|
_fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)width;
|
|
|
|
} else {
|
|
|
|
_densities [i] = 0;
|
|
|
|
_feedthroughs [i] = 0;
|
|
|
|
_fragmentations[i] = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (height) {
|
|
|
|
_densities [i] = ((float)uLengths2[i]) / ( vcapacity * (float)height );
|
|
|
|
_feedthroughs [i] += (float)(_blockages[i] / height);
|
|
|
|
_fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)height;
|
|
|
|
} else {
|
|
|
|
_densities [i] = 0;
|
|
|
|
_feedthroughs [i] = 0;
|
|
|
|
_fragmentations[i] = 0;
|
|
|
|
}
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_densities[i] >= 1.0) _flags |= Flags::Saturated;
|
|
|
|
}
|
|
|
|
|
2016-08-06 11:19:22 -05:00
|
|
|
if (ccapacity)
|
|
|
|
_cDensity = ( (float)_contacts.size() ) / ccapacity;
|
|
|
|
else
|
|
|
|
_cDensity = 0;
|
2016-07-18 07:48:37 -05:00
|
|
|
_flags.reset( Flags::Invalidated );
|
|
|
|
|
|
|
|
checkDensity();
|
|
|
|
|
|
|
|
return isSaturated() ? 1 : 0 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
void GCell::truncDensities ()
|
|
|
|
{
|
|
|
|
int hcapacity = (int)getHCapacity();
|
|
|
|
int vcapacity = (int)getVCapacity();
|
|
|
|
Box bBox = getBoundingBox();
|
|
|
|
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
|
|
|
if (Session::getDirection(i) & Flags::Horizontal) {
|
|
|
|
if (_blockages[i] > hcapacity * bBox.getWidth())
|
|
|
|
_blockages[i] = hcapacity * bBox.getWidth();
|
|
|
|
} else {
|
|
|
|
if (_blockages[i] > vcapacity * bBox.getHeight())
|
|
|
|
_blockages[i] = vcapacity * bBox.getHeight();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_flags &= ~Flags::Saturated;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-18 07:48:37 -05:00
|
|
|
size_t GCell::checkDensity () const
|
|
|
|
{
|
|
|
|
if (isInvalidated()) const_cast<GCell*>(this)->updateDensity();
|
|
|
|
|
|
|
|
if ( not Session::isInDemoMode() and Session::doWarnGCellOverload() ) {
|
|
|
|
for ( size_t i=0 ; i<_depth ; i++ ) {
|
|
|
|
if (_densities[i] > 1.0) {
|
|
|
|
cparanoid << Warning( "%s overloaded in %s (M2:%.2f M3:%.2f M4:%.2f M5:%.2f)"
|
|
|
|
, _getString().c_str()
|
|
|
|
, getString(Session::getRoutingGauge()->getRoutingLayer(i)->getName()).c_str()
|
|
|
|
, _densities[1] // M2
|
|
|
|
, _densities[2] // M3
|
|
|
|
//, _blockages[2] // M4
|
|
|
|
, _densities[3] // M5
|
|
|
|
, _densities[4] // M6
|
|
|
|
)
|
|
|
|
<< endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return isSaturated() ? 1 : 0 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::hasFreeTrack ( size_t depth, float reserve ) const
|
|
|
|
{
|
|
|
|
if (isInvalidated()) const_cast<GCell*>(this)->updateDensity();
|
|
|
|
|
|
|
|
float capacity = 0.0;
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
if (Session::getDirection(depth) & Flags::Horizontal) capacity = getHCapacity();
|
|
|
|
else capacity = getVCapacity();
|
2016-07-18 07:48:37 -05:00
|
|
|
|
|
|
|
cdebug_log(149,0) << " | hasFreeTrack [" << getId() << "] depth:" << depth << " "
|
|
|
|
<< Session::getRoutingGauge()->getRoutingLayer(depth)->getName()
|
|
|
|
//<< " " << (_densities[depth]*capacity) << " vs. " << capacity
|
|
|
|
<< " " << _feedthroughs[depth] << " vs. " << capacity
|
|
|
|
<< " " << this << endl;
|
|
|
|
|
|
|
|
return (_feedthroughs[depth] + 0.99 + reserve <= capacity);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::rpDesaturate ( set<Net*>& globalNets )
|
|
|
|
{
|
|
|
|
set<RoutingPad*> rps;
|
|
|
|
getRoutingPads( rps );
|
|
|
|
|
|
|
|
set<Net*> rpNets;
|
|
|
|
for ( RoutingPad* rp : rps ) {
|
|
|
|
if (rp->getLayer() != Session::getRoutingLayer(0)) continue;
|
|
|
|
rpNets.insert( rp->getNet() );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rpNets.size() < Session::getSaturateRp()) return;
|
|
|
|
|
|
|
|
cerr << Warning("%s has %zd terminals (h:%zd, v:%zd)"
|
|
|
|
,getString(this).c_str()
|
|
|
|
,rps.size()
|
|
|
|
,_hsegments.size()
|
|
|
|
,_vsegments.size()
|
|
|
|
) << endl;
|
|
|
|
|
|
|
|
AutoSegment* segment;
|
|
|
|
while ( (_densities[1] > 0.5) and stepDesaturate(1,globalNets,segment,Flags::ForceMove) ) {
|
|
|
|
cdebug_log(149,0) << "Moved up: " << segment << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::stepDesaturate ( size_t depth
|
|
|
|
, set<Net*>& globalNets
|
|
|
|
, AutoSegment*& moved
|
|
|
|
, unsigned int flags
|
|
|
|
)
|
|
|
|
{
|
|
|
|
cdebug_log(9000,0) << "Deter| GCell::stepDesaturate() [" << getId() << "] depth:" << depth << endl;
|
|
|
|
|
|
|
|
updateDensity();
|
|
|
|
moved = NULL;
|
|
|
|
|
|
|
|
if (not (flags & Flags::ForceMove) and not isSaturated(depth)) return false;
|
|
|
|
|
|
|
|
vector<AutoSegment*>::iterator isegment;
|
|
|
|
vector<AutoSegment*>::iterator iend;
|
|
|
|
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
if (Session::getDirection(depth) & Flags::Horizontal) {
|
|
|
|
iend = _hsegments.end ();
|
|
|
|
isegment = _hsegments.begin();
|
|
|
|
} else {
|
|
|
|
iend = _vsegments.end ();
|
|
|
|
isegment = _vsegments.begin();
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for ( ; (isegment != iend) ; isegment++ ) {
|
|
|
|
unsigned int segmentDepth = Session::getRoutingGauge()->getLayerDepth((*isegment)->getLayer());
|
|
|
|
|
|
|
|
if (segmentDepth < depth) continue;
|
|
|
|
if (segmentDepth > depth) break;
|
|
|
|
|
|
|
|
globalNets.insert( (*isegment)->getNet() );
|
|
|
|
cdebug_log(9000,0) << "Deter| Move up " << (*isegment) << endl;
|
|
|
|
|
|
|
|
moved = (*isegment);
|
|
|
|
|
|
|
|
if (moved) return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::stepBalance ( size_t depth, GCell::Set& invalidateds )
|
|
|
|
{
|
|
|
|
cdebug_log(149,0) << "stepBalance() - " << this << endl;
|
|
|
|
|
|
|
|
updateDensity();
|
|
|
|
|
|
|
|
vector<AutoSegment*>::iterator isegment;
|
|
|
|
vector<AutoSegment*>::iterator iend;
|
|
|
|
set<Net*> globalNets;
|
|
|
|
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
if (Session::getDirection(depth) & Flags::Horizontal) {
|
|
|
|
iend = _hsegments.end ();
|
|
|
|
isegment = _hsegments.begin();
|
|
|
|
} else {
|
|
|
|
iend = _vsegments.end ();
|
|
|
|
isegment = _vsegments.begin();
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for ( ; (isegment != iend) ; isegment++ ) {
|
|
|
|
unsigned int segmentDepth = Session::getRoutingGauge()->getLayerDepth((*isegment)->getLayer());
|
|
|
|
|
|
|
|
if (segmentDepth < depth) continue;
|
|
|
|
if (segmentDepth > depth) break;
|
|
|
|
|
|
|
|
#if THIS_IS_DISABLED
|
|
|
|
// Hard-coded: reserve 3 tracks (1/20 * 3).
|
|
|
|
if ((*isegment)->canMoveULeft(0.05)) {
|
|
|
|
getAnabatic()->moveULeft(*isegment,globalNets,invalidateds);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ((*isegment)->canMoveURight(0.05)) {
|
|
|
|
getAnabatic()->moveURight(*isegment,globalNets,invalidateds);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::stepNetDesaturate ( size_t depth, set<Net*>& globalNets, GCell::Set& invalidateds )
|
|
|
|
{
|
|
|
|
cdebug_log(9000,0) << "Deter| GCell::stepNetDesaturate() depth:" << depth << endl;
|
|
|
|
cdebug_log(9000,0) << "Deter| " << this << endl;
|
|
|
|
|
|
|
|
updateDensity();
|
|
|
|
|
|
|
|
vector<AutoSegment*>::iterator isegment;
|
|
|
|
vector<AutoSegment*>::iterator iend;
|
|
|
|
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
if (Session::getDirection(depth) & Flags::Horizontal) {
|
|
|
|
iend = _hsegments.end ();
|
|
|
|
isegment = _hsegments.begin ();
|
|
|
|
} else {
|
|
|
|
iend = _vsegments.end ();
|
|
|
|
isegment = _vsegments.begin ();
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for ( ; (isegment != iend) ; isegment++ ) {
|
|
|
|
unsigned int segmentDepth = Session::getRoutingGauge()->getLayerDepth((*isegment)->getLayer());
|
|
|
|
|
|
|
|
if (segmentDepth < depth) continue;
|
|
|
|
if (segmentDepth > depth) break;
|
|
|
|
|
|
|
|
cdebug_log(9000,0) << "Deter| Move up " << (*isegment) << endl;
|
|
|
|
|
2016-07-21 17:14:17 -05:00
|
|
|
if (getAnabatic()->moveUpNetTrunk(*isegment,globalNets,invalidateds))
|
|
|
|
return true;
|
2016-07-18 07:48:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
string GCell::_getTypeName () const
|
|
|
|
{ return getString(_extensionName); }
|
|
|
|
|
|
|
|
|
|
|
|
string GCell::_getString () const
|
|
|
|
{
|
|
|
|
string s = Super::_getString();
|
|
|
|
s.insert( s.size()-1, " "+getString(getBoundingBox()) );
|
|
|
|
s.insert( s.size()-1, " "+getString(_flags) );
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Record* GCell::_getRecord () const
|
|
|
|
{
|
|
|
|
Record* record = Super::_getRecord();
|
2016-07-18 07:48:37 -05:00
|
|
|
record->add( getSlot("_flags" , &_flags ) );
|
|
|
|
record->add( getSlot("_westEdges" , &_westEdges ) );
|
|
|
|
record->add( getSlot("_eastEdges" , &_eastEdges ) );
|
|
|
|
record->add( getSlot("_southEdges" , &_southEdges) );
|
|
|
|
record->add( getSlot("_northEdges" , &_northEdges) );
|
2016-05-23 09:15:25 -05:00
|
|
|
record->add( DbU::getValueSlot("_xmin", &_xmin) );
|
|
|
|
record->add( DbU::getValueSlot("_ymin", &_ymin) );
|
2016-07-18 07:48:37 -05:00
|
|
|
record->add( getSlot ( "_vsegments", &_vsegments ) );
|
|
|
|
record->add( getSlot ( "_hsegments", &_hsegments ) );
|
|
|
|
record->add( getSlot ( "_contacts" , &_contacts ) );
|
|
|
|
record->add( getSlot ( "_depth" , &_depth ) );
|
|
|
|
|
|
|
|
RoutingGauge* rg = getAnabatic()->getConfiguration()->getRoutingGauge();
|
|
|
|
|
|
|
|
for ( size_t depth=0 ; depth<_depth ; ++depth ) {
|
|
|
|
ostringstream s;
|
|
|
|
const Layer* layer = rg->getRoutingLayer(depth)->getBlockageLayer();
|
|
|
|
s << "_blockages[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
|
|
|
|
record->add( getSlot ( s.str(), &_blockages[depth] ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( size_t depth=0 ; depth<_depth ; ++depth ) {
|
|
|
|
ostringstream s;
|
|
|
|
const Layer* layer = rg->getRoutingLayer(depth);
|
|
|
|
s << "_densities[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
|
|
|
|
record->add( getSlot ( s.str(), &_densities[depth] ) );
|
|
|
|
}
|
2016-05-23 09:15:25 -05:00
|
|
|
return record;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-18 07:48:37 -05:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Anabatic::GCellDensitySet".
|
|
|
|
|
|
|
|
|
|
|
|
GCellDensitySet::GCellDensitySet ( size_t depth )
|
|
|
|
: _depth (depth)
|
|
|
|
, _set ()
|
|
|
|
, _requests()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
GCellDensitySet::GCellDensitySet ( size_t depth, const GCell::Vector& gcells )
|
|
|
|
: _depth (depth)
|
|
|
|
, _set ()
|
|
|
|
, _requests()
|
|
|
|
{
|
|
|
|
for ( size_t i=0 ; i<gcells.size() ; i++ )
|
|
|
|
_requests.insert( gcells[i] );
|
|
|
|
requeue();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCellDensitySet::~GCellDensitySet ()
|
|
|
|
{
|
|
|
|
if (not _requests.empty()) {
|
|
|
|
cerr << Warning("~GCellDensitySet(): Still contains %d requests (and %d elements)."
|
|
|
|
,_requests.size(),_set.size()) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCellDensitySet::requeue ()
|
|
|
|
{
|
|
|
|
cdebug_log(149,0) << "GCellDensitySet::requeue()" << endl;
|
|
|
|
|
|
|
|
std::set<GCell*,GCell::CompareByKey>::iterator iinserted;
|
|
|
|
GCell::Set::iterator igcell = _requests.begin();
|
|
|
|
|
|
|
|
// Remove invalidateds GCell from the queue.
|
|
|
|
for ( ; igcell != _requests.end() ; ++igcell ) {
|
|
|
|
iinserted = _set.find(*igcell);
|
|
|
|
if (iinserted != _set.end()) {
|
|
|
|
_set.erase( iinserted );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Re-insert invalidateds GCell in the queue *after* updating the key.
|
|
|
|
for ( igcell = _requests.begin() ; igcell != _requests.end() ; ++igcell ) {
|
|
|
|
(*igcell)->updateKey( _depth );
|
|
|
|
_set.insert( *igcell );
|
|
|
|
}
|
|
|
|
|
|
|
|
_requests.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Utilities.
|
|
|
|
|
|
|
|
|
|
|
|
string getVectorString ( float* v, size_t size )
|
|
|
|
{
|
|
|
|
ostringstream s;
|
|
|
|
|
|
|
|
s << setprecision(3);
|
|
|
|
for ( size_t i=0 ; i<size ; i++ ) {
|
|
|
|
if ( !i ) s << "[";
|
|
|
|
else s << " ";
|
|
|
|
s << v[i];
|
|
|
|
}
|
|
|
|
s << "]";
|
|
|
|
|
|
|
|
return s.str();
|
|
|
|
}
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
|
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah!
* Bug: In Hurricane, in StaticObservable::getObserver(), if the slot
pointer is NULL, do not try to access the owner. Returns NULL, so
the caller can be aware of the situation...
* Change: In Hurricane, in BreakpointWidget & ExceptionWidget some
cosmetic changes (fonts and window sizes).
* Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account
the constraints from the source AutoContact, as it holds the constraints
transmitted by the RoutingPads and sets up by propageConstraintsFromRp().
It is likely to be a bug affecting the original Katabatic as well.
* Change: In Anabatic, in RawGCellsUnder(), check that the segment is not
completly oustside the cell abutment box and truncate the coordinates
to the part that is inside. Use the "shrink" if we reach the east/north
border.
* Change: In Anabatic, in Configuration, no more decorator because we will
use a true derived relationship. Katana *derives* from *Anabatic* and do
not *decorate* it, so the Configuration can do the same. It also implies
that we directly create a Katana engine, not an Anabatic one.
* Change: In Anabatic, in Session, do not allow the opening of the Session
in a standalone fashion (with a static method). Instead it must be opened
using the relevant method of the Anabatic/Katana engine. This ensure we
are opening the right Session type.
* Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment
is not part of the collection by default, but will be included if the
Flags::WithSelf is set.
* Change: In Configuration, all the flags value are now defined in two steps.
Declared in the header and initialized in the module. This is to prevent
the fact that on some cases, in relation with the Python "extern C" part
modules, we need a true allocated variable. It was causing weird linking
problems.
A side effect is that they can no longer be used as entry is switches,
have to replace them by if/else.
* New: In Anabatic, new GCell::getNeighborAt() utility function.
* Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with
the grid type... Back annote all the edges capacity (north & east) with
the reserved local capacity.
* New: Complete portage of Kite over Anabatic. The new engine is christened
"Katana" for Kite-Analogic. When it's capabilities and performances
will be on a part with Kite, it is to completly replace it (and take
back the "Kite" name). Preliminary tests seems to show that, contrary
to intuition (because built on a more complex/slower grid), it is even
slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
|
|
|
bool isLess ( const GCell* lhs, const GCell* rhs, Flags direction )
|
|
|
|
{
|
|
|
|
if (direction & Flags::Horizontal) {
|
|
|
|
if (lhs->getXMin() != rhs->getXMin()) return lhs->getXMin() < rhs->getXMin();
|
|
|
|
} else {
|
|
|
|
if (direction & Flags::Vertical) {
|
|
|
|
if (lhs->getYMin() != rhs->getYMin()) return lhs->getYMin() < rhs->getYMin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return lhs->getId() < rhs->getId();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool isGreater ( const GCell* lhs, const GCell* rhs, Flags direction )
|
|
|
|
{
|
|
|
|
if (direction & Flags::Horizontal) {
|
|
|
|
if (lhs->getXMin() != rhs->getXMin()) return lhs->getXMin() > rhs->getXMin();
|
|
|
|
} else {
|
|
|
|
if (direction & Flags::Vertical) {
|
|
|
|
if (lhs->getYMin() != rhs->getYMin()) return lhs->getYMin() > rhs->getYMin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return lhs->getId() > rhs->getId();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
} // Anabatic namespace.
|