diff --git a/etesian/src/Placement.cpp b/etesian/src/Placement.cpp index 1555b2d2..28e2f218 100644 --- a/etesian/src/Placement.cpp +++ b/etesian/src/Placement.cpp @@ -21,9 +21,10 @@ #include "hurricane/Warning.h" #include "hurricane/DataBase.h" #include "hurricane/UpdateSession.h" -#include "hurricane/Instance.h" #include "hurricane/Plug.h" #include "hurricane/Path.h" +#include "hurricane/Instance.h" +#include "hurricane/Library.h" #include "hurricane/viewer/CellWidget.h" #include "hurricane/viewer/CellViewer.h" #include "crlcore/AllianceFramework.h" @@ -40,18 +41,100 @@ namespace { using Hurricane::DbU; using Hurricane::Box; using Hurricane::Interval; + using Hurricane::DBo; using Hurricane::Occurrence; using Hurricane::Instance; using Hurricane::Path; using Hurricane::Transformation; using Hurricane::DataBase; using Hurricane::Cell; + using Hurricane::Library; using CRL::AllianceFramework; using CRL::CatalogExtension; using CRL::getTransformation; 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". @@ -66,6 +149,8 @@ namespace { inline DbU::Unit getXMin () const; inline DbU::Unit getXMax () const; inline DbU::Unit getWidth () const; + inline Cell* getMasterCell () const; + inline Instance* getInstance () const; inline const Occurrence& getOccurrence () const; inline void translate ( DbU::Unit ); private: @@ -82,17 +167,17 @@ namespace { inline DbU::Unit Tile::getXMax () const { return _xMin+_width; } inline DbU::Unit Tile::getWidth () const { return _width; } inline const Occurrence& Tile::getOccurrence () const { return _occurrence; } + inline Instance* Tile::getInstance () const { return static_cast( _occurrence.getEntity() ); } + inline Cell* Tile::getMasterCell () const { return getInstance()->getMasterCell(); } inline bool Tile::isFixed () const - { - return static_cast( _occurrence.getEntity() )->getPlacementStatus() - == Instance::PlacementStatus::FIXED; - } + { return getInstance()->getPlacementStatus() == Instance::PlacementStatus::FIXED; } + inline void Tile::translate ( DbU::Unit dx ) { - cerr << " Tile::translate(), dx:" << DbU::getValueString(dx) << ", " << _occurrence << endl; - Instance* instance = static_cast( _occurrence.getEntity() ); + cdebug_log(121,0) << " Tile::translate(), dx:" << DbU::getValueString(dx) << ", " << _occurrence << endl; + Instance* instance = getInstance(); Transformation reference = instance->getTransformation(); Transformation transf = Transformation( reference.getTx() + dx , reference.getTy() @@ -137,6 +222,7 @@ namespace { SubSlice ( Slice*, const list::iterator& beginTile ); inline const list::iterator getBeginTile () const; inline const list::iterator getEndTile () const; + inline DbU::Unit getYBottom () const; inline DbU::Unit getXMin () const; inline DbU::Unit getXMax () const; DbU::Unit getAverageChunk ( size_t& ) const; @@ -156,23 +242,25 @@ namespace { class Slice { public: - Slice ( Area*, DbU::Unit ybottom ); - inline DbU::Unit getYBottom () const; - inline DbU::Unit getXMin () const; - inline DbU::Unit getXMax () const; - inline Interval getXSpan () const; - inline Area* getArea () const; - inline EtesianEngine* getEtesian () const; - inline size_t getSpinSlice0 () const; - bool validate () const; - inline list& getTiles (); - void merge ( const Occurrence&, const Box& ); - void addFeeds ( size_t islice ); - void fillHole ( DbU::Unit xmin, DbU::Unit xmax, DbU::Unit ybottom, size_t yspin ); - void buildSubSlices (); - void showSubSlices (); - void insertTies ( DbU::Unit latchUpMax ); - string _getString () const; + Slice ( Area*, DbU::Unit ybottom ); + inline DbU::Unit getYBottom () const; + inline DbU::Unit getXMin () const; + inline DbU::Unit getXMax () const; + inline Interval getXSpan () const; + inline Area* getArea () const; + inline EtesianEngine* getEtesian () const; + inline size_t getSpinSlice0 () const; + inline DbU::Unit getLeftDistance ( Cell* cell ) const; + inline DbU::Unit getRightDistance ( Cell* cell ) const; + bool validate ( DbU::Unit latchUpMax ) const; + inline list& getTiles (); + void merge ( const Occurrence&, const Box& ); + void addFeeds ( size_t islice ); + void fillHole ( DbU::Unit xmin, DbU::Unit xmax, DbU::Unit ybottom, size_t yspin ); + void buildSubSlices (); + void showSubSlices (); + void insertTies ( DbU::Unit latchUpMax ); + string _getString () const; private: Area* _area; DbU::Unit _ybottom; @@ -189,15 +277,39 @@ namespace { { } - bool Slice::validate () const + bool Slice::validate ( DbU::Unit latchUpMax ) const { if (_tiles.empty()) return true; - bool validated = true; - auto iTile = _tiles.begin(); - auto iTileNext = iTile; + 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; + auto iTile = _tiles.begin(); + auto iTileNext = iTile; + auto iTileFeed = _tiles.begin(); ++iTileNext; 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()) { cerr << Error( "Slice::validate(): Overlap in slice @%s between instances,\n" " %s @%s\n" @@ -213,6 +325,7 @@ namespace { ++iTile; ++iTileNext; } + cdebug_log(121,-1); return validated; } @@ -251,23 +364,24 @@ namespace { { if (_tiles.empty()) return; - cerr << "+ Slice @" << DbU::getValueString(_ybottom) << endl; + cdebug_log(121,0) << "+ Slice @" << DbU::getValueString(_ybottom) << endl; for ( const SubSlice& subSlice : _subSlices ) { size_t count = 0; DbU::Unit avg = subSlice.getAverageChunk( count ); - cerr << "| [" << DbU::getValueString(subSlice.getXMin()) - << " " << DbU::getValueString(subSlice.getXMax()) - << "] tiles:" << count - << " avg:" << DbU::getValueString(avg) - << " " << endl; + cdebug_log(121,0) << "| [" << DbU::getValueString(subSlice.getXMin()) + << " " << DbU::getValueString(subSlice.getXMax()) + << "] tiles:" << count + << " avg:" << DbU::getValueString(avg) + << " " << endl; } } 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 ); + cdebug_tabw(121,-1); } @@ -346,21 +460,24 @@ namespace { class Area { public: - Area ( EtesianEngine* ); - ~Area (); - inline EtesianEngine* getEtesian () const; - inline size_t getSpinSlice0 () const; - inline void setSpinSlice0 ( size_t ); - inline DbU::Unit getXMin () const; - inline DbU::Unit getXMax () const; - bool validate () const; - void merge ( const Occurrence&, const Box& ); - void addFeeds (); - void buildSubSlices (); - void showSubSlices (); - void insertTies ( DbU::Unit latchUpMax ); + Area ( EtesianEngine* ); + ~Area (); + inline EtesianEngine* getEtesian () const; + inline size_t getSpinSlice0 () const; + inline void setSpinSlice0 ( size_t ); + inline DbU::Unit getXMin () const; + inline DbU::Unit getXMax () 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 addFeeds (); + void buildSubSlices (); + void showSubSlices (); + void insertTies ( DbU::Unit latchUpMax ); private: EtesianEngine* _etesian; + TieLUT _tieLut; Box _cellAb; DbU::Unit _sliceHeight; vector _slices; @@ -370,6 +487,7 @@ namespace { Area::Area ( EtesianEngine* etesian ) : _etesian (etesian) + , _tieLut () , _cellAb (etesian->getBlockCell()->getAbutmentBox()) , _sliceHeight(_etesian->getSliceHeight()) , _slices () @@ -377,6 +495,18 @@ namespace { size_t slicesNb = _cellAb.getHeight() / _sliceHeight; for ( size_t islice=0 ; islicegetFeedCells().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) ); + } + } + } } @@ -387,18 +517,20 @@ namespace { } - inline EtesianEngine* Area::getEtesian () const { return _etesian; } - inline size_t Area::getSpinSlice0 () const { return _spinSlice0; } - inline void Area::setSpinSlice0 ( size_t spinSlice0 ) { _spinSlice0 = spinSlice0; } - inline DbU::Unit Area::getXMin () const { return _cellAb.getXMin(); } - inline DbU::Unit Area::getXMax () const { return _cellAb.getXMax(); } + inline EtesianEngine* Area::getEtesian () const { return _etesian; } + inline size_t Area::getSpinSlice0 () const { return _spinSlice0; } + inline void Area::setSpinSlice0 ( size_t spinSlice0 ) { _spinSlice0 = spinSlice0; } + inline DbU::Unit Area::getXMin () const { return _cellAb.getXMin(); } + 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; for ( const Slice* slice : _slices ) - validated = validated and slice->validate(); + validated = slice->validate(latchUpMax) and validated; return validated; } @@ -438,7 +570,7 @@ namespace { void Area::insertTies ( DbU::Unit 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 { return (_beginTile == _slice->getTiles().begin()) ? _slice->getXMin() : (*_beginTile).getXMin(); } @@ -485,6 +618,16 @@ namespace { 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(); if (feed == NULL) { cerr << Error( "SubSlice::insertTies(): No feed has been registered, ignoring." ) << endl; @@ -492,8 +635,8 @@ namespace { } DbU::Unit feedWidth = feed->getAbutmentBox().getWidth(); - cerr << "SubSlice::insterTies(): LatchUpMax:" << DbU::getValueString( latchUpMax ) << endl; - cerr << " Direct subSlice walkthrough." << endl; + cdebug_log(121,1) << "SubSlice::insterTies(): LatchUpMax:" << DbU::getValueString( latchUpMax ) << endl; + cdebug_log(121,1) << "Direct subSlice walkthrough." << endl; DbU::Unit xMin = getXMin(); DbU::Unit xMax = getXMax(); @@ -514,15 +657,23 @@ namespace { DbU::Unit tileLength = 0; auto iTile = _beginTile; 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; if (dxLeft >= feedWidth) { - cerr << " Enough space, reset rigth shift." << endl; + cdebug_log(121,0) << "Enough space, reset rigth shift." << endl; leftPosition = (*iTile).getXMin(); tileLength = 0; } + if (cellTieLeft) { + cdebug_log(121,0) << instance->getName() << " contains a tie, reset tile length." << endl; + tileLength = cellTieRight; + } 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; tileLength = 0; } @@ -535,62 +686,86 @@ namespace { ++iTile; } - cerr << " Reverse subSlice walkthrough (feedWidth:" << DbU::getValueString(feedWidth) << ")" << endl; leftPosition = xMax; iTile = endTile; 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) { tileLength = 0; - DbU::Unit prevDxRight = (*iTile).getXMax() - leftPosition; + DbU::Unit prevTileShift = leftPosition - (*iTile).getXMax(); while ( true ) { - DbU::Unit dxRight = (*iTile).getXMax() - leftPosition; - if (dxRight <= 0) { - cerr << " Negative dxRight, all shift has been compensated." << endl; + Instance* instance = (*iTile).getInstance(); + DbU::Unit cellTieLeft = _slice->getLeftDistance ( instance->getMasterCell() ); + DbU::Unit cellTieRight = _slice->getRightDistance( instance->getMasterCell() ); + if (cellTieRight) { + cdebug_log(121,0) << instance->getName() << " contains a tie, reset tile length." << endl; + tileLength = cellTieLeft - (*iTile).getWidth(); + } + + 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; + if (leftPosition > (*iTile).getXMax()) { + cdebug_log(121,0) << "Positive tileShift, all excess has been compensated." << endl; break; } - DbU::Unit leftHole = prevDxRight - dxRight; - 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) - << " width:" << DbU::getValueString((*iTile).getWidth()) << endl; (*iTile).translate( leftPosition - (*iTile).getXMax() ); leftPosition -= (*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; } } + cdebug_tabw(121,-2); } - inline DbU::Unit Slice::getYBottom () const { return _ybottom; } - inline DbU::Unit Slice::getXMin () const { return _area->getXMin(); } - inline DbU::Unit Slice::getXMax () const { return _area->getXMax(); } - inline Interval Slice::getXSpan () const { return Interval( getXMin(), getXMax() ); } - inline Area* Slice::getArea () const { return _area; } - inline EtesianEngine* Slice::getEtesian () const { return getArea()->getEtesian(); } - inline size_t Slice::getSpinSlice0 () const { return getArea()->getSpinSlice0(); } - inline list& Slice::getTiles () { return _tiles; } + inline DbU::Unit Slice::getYBottom () const { return _ybottom; } + inline DbU::Unit Slice::getXMin () const { return _area->getXMin(); } + 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 Area* Slice::getArea () const { return _area; } + inline EtesianEngine* Slice::getEtesian () const { return getArea()->getEtesian(); } + inline size_t Slice::getSpinSlice0 () const { return getArea()->getSpinSlice0(); } + inline list& Slice::getTiles () { return _tiles; } } // Anonymous namespace. @@ -662,8 +837,8 @@ namespace Etesian { area.buildSubSlices(); area.showSubSlices(); if (getConfiguration()->getLatchUpDistance()) { - DbU::Unit tieSpacing = getConfiguration()->getLatchUpDistance()*2; Cell* feed = getFeedCells().getBiggestFeed(); + DbU::Unit tieSpacing = getConfiguration()->getLatchUpDistance()*2 - feed->getAbutmentBox().getWidth(); if (feed != NULL) tieSpacing -= feed->getAbutmentBox().getWidth(); area.insertTies( tieSpacing );