Added management of tie *inside* cells.

* New: In Etesian/Placement::Area, added support to take into account
    bulk inside cells. Currently only hard-wired configuration for
    FlexLib is available. Should add a front-end to analyse the
    cells of the library to lookup for bulk ties in the future.
This commit is contained in:
Jean-Paul Chaput 2020-12-23 11:22:12 +01:00
parent 70d32528cd
commit 49ffe1e1ba
1 changed files with 274 additions and 99 deletions

View File

@ -21,9 +21,10 @@
#include "hurricane/Warning.h" #include "hurricane/Warning.h"
#include "hurricane/DataBase.h" #include "hurricane/DataBase.h"
#include "hurricane/UpdateSession.h" #include "hurricane/UpdateSession.h"
#include "hurricane/Instance.h"
#include "hurricane/Plug.h" #include "hurricane/Plug.h"
#include "hurricane/Path.h" #include "hurricane/Path.h"
#include "hurricane/Instance.h"
#include "hurricane/Library.h"
#include "hurricane/viewer/CellWidget.h" #include "hurricane/viewer/CellWidget.h"
#include "hurricane/viewer/CellViewer.h" #include "hurricane/viewer/CellViewer.h"
#include "crlcore/AllianceFramework.h" #include "crlcore/AllianceFramework.h"
@ -40,18 +41,100 @@ namespace {
using Hurricane::DbU; using Hurricane::DbU;
using Hurricane::Box; using Hurricane::Box;
using Hurricane::Interval; using Hurricane::Interval;
using Hurricane::DBo;
using Hurricane::Occurrence; using Hurricane::Occurrence;
using Hurricane::Instance; using Hurricane::Instance;
using Hurricane::Path; using Hurricane::Path;
using Hurricane::Transformation; using Hurricane::Transformation;
using Hurricane::DataBase; using Hurricane::DataBase;
using Hurricane::Cell; using Hurricane::Cell;
using Hurricane::Library;
using CRL::AllianceFramework; using CRL::AllianceFramework;
using CRL::CatalogExtension; using CRL::CatalogExtension;
using CRL::getTransformation; using CRL::getTransformation;
using Etesian::EtesianEngine; using Etesian::EtesianEngine;
// -------------------------------------------------------------------
// Class : "::TieDatas".
class TieDatas {
public:
inline TieDatas ( Cell* cell=NULL, DbU::Unit leftDistance=0, DbU::Unit rightDistance=0 );
inline Cell* getCell () const;
inline DbU::Unit getLeftDistance () const;
inline DbU::Unit getRightDistance() const;
private:
Cell* _cell;
DbU::Unit _leftDistance;
DbU::Unit _rightDistance;
};
inline TieDatas::TieDatas ( Cell* cell, DbU::Unit leftDistance, DbU::Unit rightDistance )
: _cell (cell)
, _leftDistance (leftDistance)
, _rightDistance(rightDistance)
{ }
inline Cell* TieDatas::getCell () const { return _cell; }
inline DbU::Unit TieDatas::getLeftDistance () const { return _leftDistance; }
inline DbU::Unit TieDatas::getRightDistance() const { return _rightDistance; }
// -------------------------------------------------------------------
// Class : "::TieLUT".
class TieLUT {
public:
inline TieLUT ();
inline const TieDatas* getTieDatas ( Cell* ) const;
inline DbU::Unit getLeftDistance ( Cell* ) const;
inline DbU::Unit getRightDistance ( Cell* ) const;
inline void addTieDatas ( Cell*, DbU::Unit leftDistance, DbU::Unit rightDistance );
private:
map< Cell*, TieDatas, DBo::CompareById > _tieLut;
};
inline TieLUT::TieLUT ()
: _tieLut()
{ }
inline void TieLUT::addTieDatas ( Cell* cell, DbU::Unit leftDistance, DbU::Unit rightDistance )
{
const TieDatas* datas = getTieDatas( cell );
if (datas) {
cerr << Error( "TieLUT::addTieDatas(): Duplicate datas for % (ignoreds)."
, getString(cell).c_str()
) << endl;
}
_tieLut[ cell ] = TieDatas( cell, leftDistance, rightDistance );
}
inline const TieDatas* TieLUT::getTieDatas ( Cell* cell ) const
{
auto iDatas = _tieLut.find( cell );
return (iDatas != _tieLut.end()) ? &((*iDatas).second) : NULL;
}
inline DbU::Unit TieLUT::getLeftDistance ( Cell* cell ) const
{
const TieDatas* datas = getTieDatas( cell );
return (datas) ? datas->getLeftDistance() : 0;
}
inline DbU::Unit TieLUT::getRightDistance ( Cell* cell ) const
{
const TieDatas* datas = getTieDatas( cell );
return (datas) ? datas->getRightDistance() : 0;
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "::Tile". // Class : "::Tile".
@ -66,6 +149,8 @@ namespace {
inline DbU::Unit getXMin () const; inline DbU::Unit getXMin () const;
inline DbU::Unit getXMax () const; inline DbU::Unit getXMax () const;
inline DbU::Unit getWidth () const; inline DbU::Unit getWidth () const;
inline Cell* getMasterCell () const;
inline Instance* getInstance () const;
inline const Occurrence& getOccurrence () const; inline const Occurrence& getOccurrence () const;
inline void translate ( DbU::Unit ); inline void translate ( DbU::Unit );
private: private:
@ -82,17 +167,17 @@ namespace {
inline DbU::Unit Tile::getXMax () const { return _xMin+_width; } inline DbU::Unit Tile::getXMax () const { return _xMin+_width; }
inline DbU::Unit Tile::getWidth () const { return _width; } inline DbU::Unit Tile::getWidth () const { return _width; }
inline const Occurrence& Tile::getOccurrence () const { return _occurrence; } inline const Occurrence& Tile::getOccurrence () const { return _occurrence; }
inline Instance* Tile::getInstance () const { return static_cast<Instance*>( _occurrence.getEntity() ); }
inline Cell* Tile::getMasterCell () const { return getInstance()->getMasterCell(); }
inline bool Tile::isFixed () const inline bool Tile::isFixed () const
{ { return getInstance()->getPlacementStatus() == Instance::PlacementStatus::FIXED; }
return static_cast<Instance*>( _occurrence.getEntity() )->getPlacementStatus()
== Instance::PlacementStatus::FIXED;
}
inline void Tile::translate ( DbU::Unit dx ) inline void Tile::translate ( DbU::Unit dx )
{ {
cerr << " Tile::translate(), dx:" << DbU::getValueString(dx) << ", " << _occurrence << endl; cdebug_log(121,0) << " Tile::translate(), dx:" << DbU::getValueString(dx) << ", " << _occurrence << endl;
Instance* instance = static_cast<Instance*>( _occurrence.getEntity() ); Instance* instance = getInstance();
Transformation reference = instance->getTransformation(); Transformation reference = instance->getTransformation();
Transformation transf = Transformation( reference.getTx() + dx Transformation transf = Transformation( reference.getTx() + dx
, reference.getTy() , reference.getTy()
@ -137,6 +222,7 @@ namespace {
SubSlice ( Slice*, const list<Tile>::iterator& beginTile ); SubSlice ( Slice*, const list<Tile>::iterator& beginTile );
inline const list<Tile>::iterator getBeginTile () const; inline const list<Tile>::iterator getBeginTile () const;
inline const list<Tile>::iterator getEndTile () const; inline const list<Tile>::iterator getEndTile () const;
inline DbU::Unit getYBottom () const;
inline DbU::Unit getXMin () const; inline DbU::Unit getXMin () const;
inline DbU::Unit getXMax () const; inline DbU::Unit getXMax () const;
DbU::Unit getAverageChunk ( size_t& ) const; DbU::Unit getAverageChunk ( size_t& ) const;
@ -164,7 +250,9 @@ namespace {
inline Area* getArea () const; inline Area* getArea () const;
inline EtesianEngine* getEtesian () const; inline EtesianEngine* getEtesian () const;
inline size_t getSpinSlice0 () const; inline size_t getSpinSlice0 () const;
bool validate () const; inline DbU::Unit getLeftDistance ( Cell* cell ) const;
inline DbU::Unit getRightDistance ( Cell* cell ) const;
bool validate ( DbU::Unit latchUpMax ) const;
inline list<Tile>& getTiles (); inline list<Tile>& getTiles ();
void merge ( const Occurrence&, const Box& ); void merge ( const Occurrence&, const Box& );
void addFeeds ( size_t islice ); void addFeeds ( size_t islice );
@ -189,15 +277,39 @@ namespace {
{ } { }
bool Slice::validate () const bool Slice::validate ( DbU::Unit latchUpMax ) const
{ {
if (_tiles.empty()) return true; if (_tiles.empty()) return true;
cdebug_log(121,1) << "Slice::validate() @Y=" << DbU::getValueString(_ybottom) << endl;
Cell* feed = getEtesian()->getFeedCells().getBiggestFeed();
DbU::Unit feedWidth = feed->getAbutmentBox().getWidth();
DbU::Unit cellLength = 0;
bool validated = true; bool validated = true;
auto iTile = _tiles.begin(); auto iTile = _tiles.begin();
auto iTileNext = iTile; auto iTileNext = iTile;
auto iTileFeed = _tiles.begin();
++iTileNext; ++iTileNext;
while ( iTileNext != _tiles.end() ) { while ( iTileNext != _tiles.end() ) {
cellLength += (*iTile).getWidth();
if ( ((*iTileNext).getXMin() - (*iTile).getXMax() >= feedWidth)
or ((*iTile).getMasterCell() == feed)) {
if ((*iTile).getMasterCell() == feed)
cellLength -= feedWidth;
//if (feed and ((*iTile).getMasterCell() == feed)) {
cdebug_log(121,0) << "cellLength=" << DbU::getValueString(cellLength) << endl;
if (cellLength > latchUpMax) {
while ( (iTileFeed != iTileNext) and (iTileFeed != _tiles.end()) ) {
cdebug_log(121,0) << "| " << DbU::getValueString((*iTileFeed).getXMin())
<< " " << (*iTileFeed).getOccurrence() << endl;
++iTileFeed;
}
} else {
iTileFeed = iTileNext;
}
cellLength = 0;
}
if ((*iTile).getXMax() > (*iTileNext).getXMin()) { if ((*iTile).getXMax() > (*iTileNext).getXMin()) {
cerr << Error( "Slice::validate(): Overlap in slice @%s between instances,\n" cerr << Error( "Slice::validate(): Overlap in slice @%s between instances,\n"
" %s @%s\n" " %s @%s\n"
@ -213,6 +325,7 @@ namespace {
++iTile; ++iTileNext; ++iTile; ++iTileNext;
} }
cdebug_log(121,-1);
return validated; return validated;
} }
@ -251,11 +364,11 @@ namespace {
{ {
if (_tiles.empty()) return; if (_tiles.empty()) return;
cerr << "+ Slice @" << DbU::getValueString(_ybottom) << endl; cdebug_log(121,0) << "+ Slice @" << DbU::getValueString(_ybottom) << endl;
for ( const SubSlice& subSlice : _subSlices ) { for ( const SubSlice& subSlice : _subSlices ) {
size_t count = 0; size_t count = 0;
DbU::Unit avg = subSlice.getAverageChunk( count ); DbU::Unit avg = subSlice.getAverageChunk( count );
cerr << "| [" << DbU::getValueString(subSlice.getXMin()) cdebug_log(121,0) << "| [" << DbU::getValueString(subSlice.getXMin())
<< " " << DbU::getValueString(subSlice.getXMax()) << " " << DbU::getValueString(subSlice.getXMax())
<< "] tiles:" << count << "] tiles:" << count
<< " avg:" << DbU::getValueString(avg) << " avg:" << DbU::getValueString(avg)
@ -266,8 +379,9 @@ namespace {
void Slice::insertTies ( DbU::Unit latchUpMax ) void Slice::insertTies ( DbU::Unit latchUpMax )
{ {
cerr << "Slice::insertTies() @" << DbU::getValueString(_ybottom) << endl; cdebug_log(121,1) << "Slice::insertTies() @" << DbU::getValueString(_ybottom) << endl;
for ( SubSlice& subSlice : _subSlices ) subSlice.insertTies( latchUpMax ); for ( SubSlice& subSlice : _subSlices ) subSlice.insertTies( latchUpMax );
cdebug_tabw(121,-1);
} }
@ -353,7 +467,9 @@ namespace {
inline void setSpinSlice0 ( size_t ); inline void setSpinSlice0 ( size_t );
inline DbU::Unit getXMin () const; inline DbU::Unit getXMin () const;
inline DbU::Unit getXMax () const; inline DbU::Unit getXMax () const;
bool validate () const; inline DbU::Unit getLeftDistance ( Cell* cell ) const;
inline DbU::Unit getRightDistance ( Cell* cell ) const;
bool validate ( DbU::Unit latchUpMax ) const;
void merge ( const Occurrence&, const Box& ); void merge ( const Occurrence&, const Box& );
void addFeeds (); void addFeeds ();
void buildSubSlices (); void buildSubSlices ();
@ -361,6 +477,7 @@ namespace {
void insertTies ( DbU::Unit latchUpMax ); void insertTies ( DbU::Unit latchUpMax );
private: private:
EtesianEngine* _etesian; EtesianEngine* _etesian;
TieLUT _tieLut;
Box _cellAb; Box _cellAb;
DbU::Unit _sliceHeight; DbU::Unit _sliceHeight;
vector<Slice*> _slices; vector<Slice*> _slices;
@ -370,6 +487,7 @@ namespace {
Area::Area ( EtesianEngine* etesian ) Area::Area ( EtesianEngine* etesian )
: _etesian (etesian) : _etesian (etesian)
, _tieLut ()
, _cellAb (etesian->getBlockCell()->getAbutmentBox()) , _cellAb (etesian->getBlockCell()->getAbutmentBox())
, _sliceHeight(_etesian->getSliceHeight()) , _sliceHeight(_etesian->getSliceHeight())
, _slices () , _slices ()
@ -377,6 +495,18 @@ namespace {
size_t slicesNb = _cellAb.getHeight() / _sliceHeight; size_t slicesNb = _cellAb.getHeight() / _sliceHeight;
for ( size_t islice=0 ; islice<slicesNb ; ++islice ) for ( size_t islice=0 ; islice<slicesNb ; ++islice )
_slices.push_back( new Slice( this, _cellAb.getYMin()+islice*_sliceHeight ) ); _slices.push_back( new Slice( this, _cellAb.getYMin()+islice*_sliceHeight ) );
Cell* feed = getEtesian()->getFeedCells().getBiggestFeed();
if (feed) {
Library* library = feed->getLibrary();
if (feed->getLibrary()->getName() == "FlexLib") {
cmess2 << " o Using hard-coded tie/cell datas suited for \"FlexLib\"." << endl;
Cell* masterCell = library->getCell( "sff1_x4" );
if (masterCell) {
_tieLut.addTieDatas( masterCell, DbU::fromMicrons(1.28), DbU::fromMicrons(11.7) );
}
}
}
} }
@ -392,13 +522,15 @@ namespace {
inline void Area::setSpinSlice0 ( size_t spinSlice0 ) { _spinSlice0 = spinSlice0; } inline void Area::setSpinSlice0 ( size_t spinSlice0 ) { _spinSlice0 = spinSlice0; }
inline DbU::Unit Area::getXMin () const { return _cellAb.getXMin(); } inline DbU::Unit Area::getXMin () const { return _cellAb.getXMin(); }
inline DbU::Unit Area::getXMax () const { return _cellAb.getXMax(); } inline DbU::Unit Area::getXMax () const { return _cellAb.getXMax(); }
inline DbU::Unit Area::getLeftDistance ( Cell* cell ) const { return _tieLut.getLeftDistance(cell); }
inline DbU::Unit Area::getRightDistance ( Cell* cell ) const { return _tieLut.getRightDistance(cell); }
bool Area::validate () const bool Area::validate ( DbU::Unit latchUpMax ) const
{ {
bool validated = true; bool validated = true;
for ( const Slice* slice : _slices ) for ( const Slice* slice : _slices )
validated = validated and slice->validate(); validated = slice->validate(latchUpMax) and validated;
return validated; return validated;
} }
@ -438,7 +570,7 @@ namespace {
void Area::insertTies ( DbU::Unit latchUpMax ) void Area::insertTies ( DbU::Unit latchUpMax )
{ {
for ( Slice* slice : _slices ) slice->insertTies( latchUpMax ); for ( Slice* slice : _slices ) slice->insertTies( latchUpMax );
validate(); validate( latchUpMax );
} }
@ -454,6 +586,7 @@ namespace {
} }
} }
inline DbU::Unit SubSlice::getYBottom () const { return _slice->getYBottom(); }
inline DbU::Unit SubSlice::getXMin () const inline DbU::Unit SubSlice::getXMin () const
{ return (_beginTile == _slice->getTiles().begin()) ? _slice->getXMin() : (*_beginTile).getXMin(); } { return (_beginTile == _slice->getTiles().begin()) ? _slice->getXMin() : (*_beginTile).getXMin(); }
@ -485,6 +618,16 @@ namespace {
void SubSlice::insertTies ( DbU::Unit latchUpMax ) void SubSlice::insertTies ( DbU::Unit latchUpMax )
{ {
size_t count = 0;
DbU::Unit averageChunk = getAverageChunk( count );
if (averageChunk > latchUpMax) {
cerr << Error( "SubSlice::insertTies(): Not enough free space to insert polarization ties.\n"
" @Y=%s, begin=%s"
, getString(DbU::getValueString(getYBottom())).c_str()
, getString((*_beginTile).getOccurrence()).c_str()
) << endl;
}
Cell* feed = _slice->getEtesian()->getFeedCells().getBiggestFeed(); Cell* feed = _slice->getEtesian()->getFeedCells().getBiggestFeed();
if (feed == NULL) { if (feed == NULL) {
cerr << Error( "SubSlice::insertTies(): No feed has been registered, ignoring." ) << endl; cerr << Error( "SubSlice::insertTies(): No feed has been registered, ignoring." ) << endl;
@ -492,8 +635,8 @@ namespace {
} }
DbU::Unit feedWidth = feed->getAbutmentBox().getWidth(); DbU::Unit feedWidth = feed->getAbutmentBox().getWidth();
cerr << "SubSlice::insterTies(): LatchUpMax:" << DbU::getValueString( latchUpMax ) << endl; cdebug_log(121,1) << "SubSlice::insterTies(): LatchUpMax:" << DbU::getValueString( latchUpMax ) << endl;
cerr << " Direct subSlice walkthrough." << endl; cdebug_log(121,1) << "Direct subSlice walkthrough." << endl;
DbU::Unit xMin = getXMin(); DbU::Unit xMin = getXMin();
DbU::Unit xMax = getXMax(); DbU::Unit xMax = getXMax();
@ -514,15 +657,23 @@ namespace {
DbU::Unit tileLength = 0; DbU::Unit tileLength = 0;
auto iTile = _beginTile; auto iTile = _beginTile;
while ( true ) { while ( true ) {
Instance* instance = (*iTile).getInstance();
DbU::Unit cellTieLeft = _slice->getLeftDistance ( instance->getMasterCell() );
DbU::Unit cellTieRight = _slice->getRightDistance( instance->getMasterCell() );
DbU::Unit dxLeft = (*iTile).getXMin() - leftPosition; DbU::Unit dxLeft = (*iTile).getXMin() - leftPosition;
if (dxLeft >= feedWidth) { if (dxLeft >= feedWidth) {
cerr << " Enough space, reset rigth shift." << endl; cdebug_log(121,0) << "Enough space, reset rigth shift." << endl;
leftPosition = (*iTile).getXMin(); leftPosition = (*iTile).getXMin();
tileLength = 0; tileLength = 0;
} }
if (cellTieLeft) {
cdebug_log(121,0) << instance->getName() << " contains a tie, reset tile length." << endl;
tileLength = cellTieRight;
}
if (tileLength + (*iTile).getWidth() > latchUpMax) { if (tileLength + (*iTile).getWidth() > latchUpMax) {
cerr << " Length above threshold, insert tie space." << endl; cdebug_log(121,0) << "Length above threshold, insert tie space." << endl;
leftPosition += feedWidth; leftPosition += feedWidth;
tileLength = 0; tileLength = 0;
} }
@ -535,57 +686,81 @@ namespace {
++iTile; ++iTile;
} }
cerr << " Reverse subSlice walkthrough (feedWidth:" << DbU::getValueString(feedWidth) << ")" << endl;
leftPosition = xMax; leftPosition = xMax;
iTile = endTile; iTile = endTile;
if (iTile == _slice->getTiles().end()) --iTile; if (iTile == _slice->getTiles().end()) --iTile;
cdebug_tabw(121,-1);
cdebug_log(121,1) << "Reverse subSlice walkthrough, in excess of "
<< DbU::getValueString((*iTile).getXMax() - leftPosition)
<< " (feedWidth:" << DbU::getValueString(feedWidth) << ")" << endl;
if ((*iTile).getXMax() > leftPosition) { if ((*iTile).getXMax() > leftPosition) {
tileLength = 0; tileLength = 0;
DbU::Unit prevDxRight = (*iTile).getXMax() - leftPosition; DbU::Unit prevTileShift = leftPosition - (*iTile).getXMax();
while ( true ) { while ( true ) {
DbU::Unit dxRight = (*iTile).getXMax() - leftPosition; Instance* instance = (*iTile).getInstance();
if (dxRight <= 0) { DbU::Unit cellTieLeft = _slice->getLeftDistance ( instance->getMasterCell() );
cerr << " Negative dxRight, all shift has been compensated." << endl; DbU::Unit cellTieRight = _slice->getRightDistance( instance->getMasterCell() );
break; if (cellTieRight) {
} cdebug_log(121,0) << instance->getName() << " contains a tie, reset tile length." << endl;
DbU::Unit leftHole = prevDxRight - dxRight; tileLength = cellTieLeft - (*iTile).getWidth();
if (leftHole > feedWidth) {
cerr << " Absorbing shift (wide hole)" << endl;
leftHole -= feedWidth;
leftPosition += leftHole;
prevDxRight = dxRight - leftHole;
tileLength = 0;
} else if (leftHole != 0) {
if (tileLength+(*iTile).getWidth() < latchUpMax) {
cerr << " Absorbing shift (full, below latchUp) delta leftPos:"
<< DbU::getValueString(leftHole) << endl;
leftHole = 0;
} else {
cerr << " Keeping spacing." << endl;
leftPosition -= leftHole;
tileLength = 0;
}
prevDxRight = dxRight - leftHole;
} else {
cerr << " No change in shift." << endl;
} }
cerr << " Left position (+width) " << DbU::getValueString(leftPosition) DbU::Unit tileShift = leftPosition - (*iTile).getXMax();
cdebug_log(121,0) << "tileShift=" << DbU::getValueString(tileShift)
<< " leftHole=" << DbU::getValueString(prevTileShift-tileShift)
<< endl;
DbU::Unit holeLength = tileShift - prevTileShift;
if (holeLength == 0) {
cdebug_log(121,0) << "No change in shift (no hole, abuted tiles)." << endl;
} else {
if (holeLength < feedWidth) {
cdebug_log(121,0) << "Hole is less than a feed width ("
<< DbU::getValueString(holeLength) << " < "
<< DbU::getValueString(feedWidth) << "), should not occur." << endl;
} else {
if (tileLength+(*iTile).getWidth() < latchUpMax) {
cdebug_log(121,0) << "Absorbing whole shift (below latch up distance, tile length="
<< DbU::getValueString(tileLength) << ")" << endl;
} else {
cdebug_log(121,0) << "Absorbing shift, keeping one feed spacing." << endl;
leftPosition -= feedWidth;
tileLength = 0;
}
}
}
cdebug_log(121,0) << "Left position (+width) " << DbU::getValueString(leftPosition)
<< " width:" << DbU::getValueString((*iTile).getWidth()) << endl; << " width:" << DbU::getValueString((*iTile).getWidth()) << endl;
if (leftPosition > (*iTile).getXMax()) {
cdebug_log(121,0) << "Positive tileShift, all excess has been compensated." << endl;
break;
}
(*iTile).translate( leftPosition - (*iTile).getXMax() ); (*iTile).translate( leftPosition - (*iTile).getXMax() );
leftPosition -= (*iTile).getWidth(); leftPosition -= (*iTile).getWidth();
tileLength += (*iTile).getWidth(); tileLength += (*iTile).getWidth();
if (iTile == _beginTile) break; if (iTile == _beginTile) {
cerr << Error( "SubSlice::insertTies(): Not enough free space to insert polarization ties.\n"
" @Y=%s, begin=%s"
, getString(DbU::getValueString(getYBottom())).c_str()
, getString((*iTile).getOccurrence()).c_str()
) << endl;
break;
}
--iTile; --iTile;
} }
} }
cdebug_tabw(121,-2);
} }
inline DbU::Unit Slice::getYBottom () const { return _ybottom; } inline DbU::Unit Slice::getYBottom () const { return _ybottom; }
inline DbU::Unit Slice::getXMin () const { return _area->getXMin(); } inline DbU::Unit Slice::getXMin () const { return _area->getXMin(); }
inline DbU::Unit Slice::getXMax () const { return _area->getXMax(); } inline DbU::Unit Slice::getXMax () const { return _area->getXMax(); }
inline DbU::Unit Slice::getLeftDistance ( Cell* cell ) const { return _area->getLeftDistance(cell); }
inline DbU::Unit Slice::getRightDistance ( Cell* cell ) const { return _area->getRightDistance(cell); }
inline Interval Slice::getXSpan () const { return Interval( getXMin(), getXMax() ); } inline Interval Slice::getXSpan () const { return Interval( getXMin(), getXMax() ); }
inline Area* Slice::getArea () const { return _area; } inline Area* Slice::getArea () const { return _area; }
inline EtesianEngine* Slice::getEtesian () const { return getArea()->getEtesian(); } inline EtesianEngine* Slice::getEtesian () const { return getArea()->getEtesian(); }
@ -662,8 +837,8 @@ namespace Etesian {
area.buildSubSlices(); area.buildSubSlices();
area.showSubSlices(); area.showSubSlices();
if (getConfiguration()->getLatchUpDistance()) { if (getConfiguration()->getLatchUpDistance()) {
DbU::Unit tieSpacing = getConfiguration()->getLatchUpDistance()*2;
Cell* feed = getFeedCells().getBiggestFeed(); Cell* feed = getFeedCells().getBiggestFeed();
DbU::Unit tieSpacing = getConfiguration()->getLatchUpDistance()*2 - feed->getAbutmentBox().getWidth();
if (feed != NULL) if (feed != NULL)
tieSpacing -= feed->getAbutmentBox().getWidth(); tieSpacing -= feed->getAbutmentBox().getWidth();
area.insertTies( tieSpacing ); area.insertTies( tieSpacing );