Allow to do the placement in a sub-area in Etesian.

* New: In EtesianEngine, add a "placedArea" attribute to restrict the
    placement area to a part only of the whole abutement box. This a
    way to exclude some area containing *big* hard block.
      The placer terribly slow down when tring to "push aside" cells
    from the area taken by the block.
      This will be also used to restrict the clock tree covered area.
      It is far from optimal but will do for now.
    NOTE: The placeArea must be expressed in the coordinate system of
          the sub-block to be placed, if one has been defined.
This commit is contained in:
Jean-Paul Chaput 2021-02-01 16:24:44 +01:00
parent 2ba7bb4fca
commit 9df5f5f1b7
5 changed files with 102 additions and 33 deletions

View File

@ -301,6 +301,7 @@ namespace Etesian {
, _block (NULL) , _block (NULL)
, _ySpinSet (false) , _ySpinSet (false)
, _flatDesign (false) , _flatDesign (false)
, _placeArea (cell->getAbutmentBox())
, _surface (NULL) , _surface (NULL)
, _circuit (NULL) , _circuit (NULL)
, _placementLB (NULL) , _placementLB (NULL)
@ -320,8 +321,7 @@ namespace Etesian {
, _fixedAbHeight(0) , _fixedAbHeight(0)
, _fixedAbWidth (0) , _fixedAbWidth (0)
, _diodeCount (0) , _diodeCount (0)
{ { }
}
void EtesianEngine::_postCreate () void EtesianEngine::_postCreate ()
@ -450,6 +450,27 @@ namespace Etesian {
{ return _configuration; } { return _configuration; }
void EtesianEngine::setPlaceArea ( const Box& placeArea )
{
Box topAb = getBlockCell()->getAbutmentBox();
if (not topAb.contains(placeArea)) {
cerr << Warning( "EtesianEngine::setPlaceArea(): placedArea is not *fully* inside topAb, trucating.\n"
" * placedArea=%s\n"
" * topAb=%s\n"
, getString(placeArea).c_str()
, getString(topAb).c_str()
) << endl;
_placeArea = topAb.getIntersection( placeArea );
}
DbU::Unit sliceHeight = getSliceHeight();
_placeArea = Box( DbU::toCeil ( placeArea.getXMin(), sliceHeight )
, DbU::toCeil ( placeArea.getYMin(), sliceHeight )
, DbU::toFloor( placeArea.getXMax(), sliceHeight )
, DbU::toFloor( placeArea.getYMax(), sliceHeight )
);
}
void EtesianEngine::setDefaultAb () void EtesianEngine::setDefaultAb ()
{ {
_bloatCells.resetDxSpace(); _bloatCells.resetDxSpace();
@ -532,6 +553,7 @@ namespace Etesian {
, abWidth , abWidth
, rows*getSliceHeight() , rows*getSliceHeight()
) ); ) );
_placeArea = getCell()->getAbutmentBox();
UpdateSession::close(); UpdateSession::close();
if (_viewer) _viewer->getCellWidget()->fitToContents(); if (_viewer) _viewer->getCellWidget()->fitToContents();
@ -629,6 +651,7 @@ namespace Etesian {
// setFixedAbHeight( getBlockCell()->getAbutmentBox().getHeight() ); // setFixedAbHeight( getBlockCell()->getAbutmentBox().getHeight() );
getBlockCell()->setAbutmentBox( Box() ); getBlockCell()->setAbutmentBox( Box() );
getBlockCell()->resetFlags( Cell::Flags::Placed ); getBlockCell()->resetFlags( Cell::Flags::Placed );
_placeArea.makeEmpty();
UpdateSession::close(); UpdateSession::close();
dots.finish( Dots::Reset ); dots.finish( Dots::Reset );
@ -646,7 +669,6 @@ namespace Etesian {
cmess1 << " o Converting <" << getCell()->getName() << "> into Coloquinte." << endl; cmess1 << " o Converting <" << getCell()->getName() << "> into Coloquinte." << endl;
cmess1 << ::Dots::asString(" - H-pitch" , DbU::getValueString(hpitch)) << endl; cmess1 << ::Dots::asString(" - H-pitch" , DbU::getValueString(hpitch)) << endl;
cmess1 << ::Dots::asString(" - V-pitch" , DbU::getValueString(vpitch)) << endl; cmess1 << ::Dots::asString(" - V-pitch" , DbU::getValueString(vpitch)) << endl;
cmess2 << " o Looking through the hierarchy." << endl; cmess2 << " o Looking through the hierarchy." << endl;
for( Occurrence occurrence : getCell()->getTerminalNetlistInstanceOccurrences() ) for( Occurrence occurrence : getCell()->getTerminalNetlistInstanceOccurrences() )
@ -664,13 +686,15 @@ namespace Etesian {
} }
} }
} }
cmess2 << " - Whole place area: " << getBlockCell()->getAbutmentBox() << "." << endl;
cmess2 << " - Sub-place Area: " << _placeArea << "." << endl;
Dots dots ( cmess2, " ", 80, 1000 ); Dots dots ( cmess2, " ", 80, 1000 );
if (not cmess2.enabled()) dots.disable(); if (not cmess2.enabled()) dots.disable();
size_t instancesNb = 0; size_t instancesNb = 0;
size_t fixedNb = 0; size_t fixedNb = 0;
Box topAb = getBlockCell()->getAbutmentBox(); Box topAb = _placeArea;
Transformation topTransformation; Transformation topTransformation;
if (getBlockInstance()) { if (getBlockInstance()) {
topTransformation = getBlockInstance()->getTransformation(); topTransformation = getBlockInstance()->getTransformation();

View File

@ -355,16 +355,17 @@ namespace Etesian {
Area::Area ( EtesianEngine* etesian ) Area::Area ( EtesianEngine* etesian )
: _etesian (etesian) : _etesian (etesian)
, _tieLut () , _tieLut ()
, _cellAb (etesian->getCell()->getAbutmentBox()) , _placeArea (etesian->getPlaceArea())
, _sliceHeight(_etesian->getSliceHeight()) , _sliceHeight(_etesian->getSliceHeight())
, _slices () , _slices ()
{ {
if (etesian->getBlockInstance()) if (etesian->getBlockInstance()) {
_cellAb = etesian->getBlockInstance()->getAbutmentBox(); _placeArea = etesian->toCell( etesian->getPlaceArea() );
}
size_t slicesNb = _cellAb.getHeight() / _sliceHeight; size_t slicesNb = _placeArea.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, _placeArea.getYMin()+islice*_sliceHeight ) );
Cell* feed = getEtesian()->getFeedCells().getBiggestFeed(); Cell* feed = getEtesian()->getFeedCells().getBiggestFeed();
if (feed) { if (feed) {
@ -402,13 +403,13 @@ namespace Etesian {
void Area::merge ( const Occurrence& occurrence, const Box& flatAb ) void Area::merge ( const Occurrence& occurrence, const Box& flatAb )
{ {
if (flatAb.getYMin() < _cellAb.getYMin()) { if (flatAb.getYMin() < _placeArea.getYMin()) {
cerr << Warning("Area::merge(): Attempt to merge instance outside the Cell abutment box.") << endl; cerr << Warning("Area::merge(): Attempt to merge instance outside the placement area.") << endl;
return; return;
} }
size_t ibegin = (flatAb.getYMin()-_cellAb.getYMin()) / _sliceHeight; size_t ibegin = (flatAb.getYMin()-_placeArea.getYMin()) / _sliceHeight;
size_t iend = (flatAb.getYMax()-_cellAb.getYMin()) / _sliceHeight; size_t iend = (flatAb.getYMax()-_placeArea.getYMin()) / _sliceHeight;
for ( size_t islice=ibegin ; islice<iend ; ++islice ) { for ( size_t islice=ibegin ; islice<iend ; ++islice ) {
_slices[islice]->merge( occurrence, flatAb ); _slices[islice]->merge( occurrence, flatAb );
@ -444,7 +445,7 @@ namespace Etesian {
Record* record = new Record(getString(this)); Record* record = new Record(getString(this));
record->add( getSlot( "_etesian" , _etesian ) ); record->add( getSlot( "_etesian" , _etesian ) );
record->add( getSlot( "_tieLut" , &_tieLut ) ); record->add( getSlot( "_tieLut" , &_tieLut ) );
record->add( getSlot( "_cellAb" , _cellAb ) ); record->add( getSlot( "_placeArea" , _placeArea ) );
record->add( DbU::getValueSlot( "_sliceHeight", &_sliceHeight ) ); record->add( DbU::getValueSlot( "_sliceHeight", &_sliceHeight ) );
record->add( getSlot( "_slices" , &_slices ) ); record->add( getSlot( "_slices" , &_slices ) );
record->add( getSlot( "_spinSlice0" , _spinSlice0 ) ); record->add( getSlot( "_spinSlice0" , _spinSlice0 ) );
@ -636,10 +637,10 @@ namespace Etesian {
DbU::Unit y = blockDiodeArea.getYCenter(); DbU::Unit y = blockDiodeArea.getYCenter();
if ((y < _cellAb.getYMin()) or (y >= _cellAb.getYMax())) return NULL; if ((y < _placeArea.getYMin()) or (y >= _placeArea.getYMax())) return NULL;
if (not blockDiodeArea.intersect(_cellAb)) return NULL; if (not blockDiodeArea.intersect(_placeArea)) return NULL;
size_t islice = (y - _cellAb.getYMin()) / _sliceHeight; size_t islice = (y - _placeArea.getYMin()) / _sliceHeight;
return _slices[islice]->createDiodeUnder( rp, blockDiodeArea, xHint ); return _slices[islice]->createDiodeUnder( rp, blockDiodeArea, xHint );
} }
@ -658,17 +659,16 @@ namespace Etesian {
if (_area) delete _area; if (_area) delete _area;
_area = new Area ( this ); _area = new Area ( this );
Box topCellAb = getCell()->getAbutmentBox(); Box topPlaceArea = _area->getPlaceArea();
_area->setSpinSlice0( _yspinSlice0 ); _area->setSpinSlice0( _yspinSlice0 );
if (getBlockInstance()) { if (getBlockInstance()) {
topCellAb = getBlockInstance()->getAbutmentBox();
for ( Instance* instance : getCell()->getInstances() ) { for ( Instance* instance : getCell()->getInstances() ) {
if (instance == getBlockInstance()) continue; if (instance == getBlockInstance()) continue;
if (instance->getPlacementStatus() == Instance::PlacementStatus::FIXED) { if (instance->getPlacementStatus() == Instance::PlacementStatus::FIXED) {
Box overlapAb = instance->getAbutmentBox(); Box overlapAb = instance->getAbutmentBox();
overlapAb = topCellAb.getIntersection( overlapAb ); overlapAb = topPlaceArea.getIntersection( overlapAb );
if (not overlapAb.isEmpty()) { if (not overlapAb.isEmpty()) {
_area->merge( Occurrence(instance), overlapAb ); _area->merge( Occurrence(instance), overlapAb );
} }
@ -690,15 +690,16 @@ namespace Etesian {
Occurrence cellOccurrence = toCell( occurrence ); Occurrence cellOccurrence = toCell( occurrence );
cellOccurrence.getPath().getTransformation().applyOn( instanceAb ); cellOccurrence.getPath().getTransformation().applyOn( instanceAb );
if (not topCellAb.contains(instanceAb)) { if (not topPlaceArea.contains(instanceAb)) {
cerr << Warning( "EtesianEngine::readSlices(): Instance %s is not fully enclosed in the top cell.\n" if (instance->getPlacementStatus() != Instance::PlacementStatus::FIXED)
" * topCellAb=%s\n" cerr << Warning( "EtesianEngine::readSlices(): Instance %s is not fully enclosed in the top cell.\n"
" * instanceAb=%s cell=%s" " * topPlaceArea=%s\n"
, getString(instance->getName()).c_str() " * instanceAb=%s cell=%s"
, getString(topCellAb).c_str() , getString(instance->getName()).c_str()
, getString(instanceAb).c_str() , getString(topPlaceArea).c_str()
, getString(instance->getCell()).c_str() , getString(instanceAb).c_str()
) << endl; , getString(instance->getCell()).c_str()
) << endl;
continue; continue;
} }

View File

@ -14,6 +14,7 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#include "hurricane/isobar/PyBox.h"
#include "hurricane/isobar/PyCell.h" #include "hurricane/isobar/PyCell.h"
#include "hurricane/isobar/PyInstance.h" #include "hurricane/isobar/PyInstance.h"
#include "hurricane/viewer/PyCellViewer.h" #include "hurricane/viewer/PyCellViewer.h"
@ -49,6 +50,8 @@ namespace Etesian {
using Isobar::ParseOneArg; using Isobar::ParseOneArg;
using Isobar::ParseTwoArg; using Isobar::ParseTwoArg;
using Isobar::EntityCast; using Isobar::EntityCast;
using Isobar::PyBox;
using Isobar::PyTypeBox;
using Isobar::PyCell; using Isobar::PyCell;
using Isobar::PyCell_Link; using Isobar::PyCell_Link;
using Isobar::PyInstance; using Isobar::PyInstance;
@ -181,6 +184,24 @@ extern "C" {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
// ---------------------------------------------------------------
// Attribute Method : "PyEtesianEngine_setPLaceArea ()"
static PyObject* PyEtesianEngine_setPlaceArea ( PyEtesianEngine *self, PyObject* args )
{
cdebug_log(34,0) << "EtesianEngine.setPLaceArea()" << endl;
HTRY
METHOD_HEAD ( "EtesianEngine.setPLaceArea()" )
PyBox* pyBox;
if (not PyArg_ParseTuple(args,"O!:EtesianEngine.setPLaceArea", &PyTypeBox, &pyBox)) {
PyErr_SetString( ConstructorError, "EtesianEngine.setPlaceArea(): Parameter is not an Box." );
return NULL;
}
etesian->setPlaceArea( *PYBOX_O(pyBox) );
HCATCH
Py_RETURN_NONE;
}
static PyObject* PyEtesianEngine_place ( PyEtesianEngine* self ) static PyObject* PyEtesianEngine_place ( PyEtesianEngine* self )
{ {
@ -222,6 +243,8 @@ extern "C" {
, "Select the Cell bloating profile." } , "Select the Cell bloating profile." }
, { "setBlock" , (PyCFunction)PyEtesianEngine_setBlock , METH_VARARGS , { "setBlock" , (PyCFunction)PyEtesianEngine_setBlock , METH_VARARGS
, "Set the sub-block (Instance) to place." } , "Set the sub-block (Instance) to place." }
, { "setPlaceArea" , (PyCFunction)PyEtesianEngine_setPlaceArea , METH_VARARGS
, "Set the sub-area into wich place the cells." }
, { "setDefaultAb" , (PyCFunction)PyEtesianEngine_setDefaultAb , METH_NOARGS , { "setDefaultAb" , (PyCFunction)PyEtesianEngine_setDefaultAb , METH_NOARGS
, "Compute and set the abutment box using the aspect ratio and the space margin." } , "Compute and set the abutment box using the aspect ratio and the space margin." }
, { "setFixedAbHeight" , (PyCFunction)PyEtesianEngine_setFixedAbHeight , METH_VARARGS , { "setFixedAbHeight" , (PyCFunction)PyEtesianEngine_setFixedAbHeight , METH_VARARGS

View File

@ -97,6 +97,7 @@ namespace Etesian {
inline const FeedCells& getFeedCells () const; inline const FeedCells& getFeedCells () const;
inline Cell* getDiodeCell () const; inline Cell* getDiodeCell () const;
std::string getUniqueDiodeName (); std::string getUniqueDiodeName ();
inline const Box& getPlaceArea () const;
inline Area* getArea () const; inline Area* getArea () const;
inline Hurricane::CellViewer* getViewer () const; inline Hurricane::CellViewer* getViewer () const;
inline void setViewer ( Hurricane::CellViewer* ); inline void setViewer ( Hurricane::CellViewer* );
@ -115,11 +116,13 @@ namespace Etesian {
inline DbU::Unit toDbU ( int64_t ) const; inline DbU::Unit toDbU ( int64_t ) const;
inline Occurrence toCell ( Occurrence ) const; inline Occurrence toCell ( Occurrence ) const;
inline Point toCell ( const Point& ) const; inline Point toCell ( const Point& ) const;
inline Box toCell ( const Box& ) const;
inline Transformation toCell ( Transformation ) const; inline Transformation toCell ( Transformation ) const;
inline Path toBlock ( Path ) const; inline Path toBlock ( Path ) const;
inline Occurrence toBlock ( Occurrence ) const; inline Occurrence toBlock ( Occurrence ) const;
inline Point toBlock ( const Point& ) const; inline Point toBlock ( const Point& ) const;
inline Transformation toBlock ( const Transformation& ) const; inline Transformation toBlock ( const Transformation& ) const;
void setPlaceArea ( const Box& );
size_t toColoquinte (); size_t toColoquinte ();
void preplace (); void preplace ();
void roughLegalize ( float minDisruption, unsigned options ); void roughLegalize ( float minDisruption, unsigned options );
@ -144,6 +147,7 @@ namespace Etesian {
bool _placed; bool _placed;
bool _ySpinSet; bool _ySpinSet;
bool _flatDesign; bool _flatDesign;
Box _placeArea;
coloquinte::box<coloquinte::int_t>* _surface; coloquinte::box<coloquinte::int_t>* _surface;
coloquinte::netlist* _circuit; coloquinte::netlist* _circuit;
coloquinte::placement_t* _placementLB; coloquinte::placement_t* _placementLB;
@ -208,15 +212,21 @@ namespace Etesian {
inline Cell* EtesianEngine::getBlockCell () const { return (_block) ? _block->getMasterCell() : getCell(); } inline Cell* EtesianEngine::getBlockCell () const { return (_block) ? _block->getMasterCell() : getCell(); }
inline Instance* EtesianEngine::getBlockInstance () const { return _block; } inline Instance* EtesianEngine::getBlockInstance () const { return _block; }
inline void EtesianEngine::setBlock ( Instance* block ) { _block = block; _placed = _block->getMasterCell()->isPlaced(); }
inline void EtesianEngine::setFixedAbHeight ( DbU::Unit abHeight ) { _fixedAbHeight = abHeight; } inline void EtesianEngine::setFixedAbHeight ( DbU::Unit abHeight ) { _fixedAbHeight = abHeight; }
inline void EtesianEngine::setFixedAbWidth ( DbU::Unit abWidth ) { _fixedAbWidth = abWidth; } inline void EtesianEngine::setFixedAbWidth ( DbU::Unit abWidth ) { _fixedAbWidth = abWidth; }
inline void EtesianEngine::setSpaceMargin ( double margin ) { getConfiguration()->setSpaceMargin(margin); } inline void EtesianEngine::setSpaceMargin ( double margin ) { getConfiguration()->setSpaceMargin(margin); }
inline void EtesianEngine::setAspectRatio ( double ratio ) { getConfiguration()->setAspectRatio(ratio); } inline void EtesianEngine::setAspectRatio ( double ratio ) { getConfiguration()->setAspectRatio(ratio); }
inline DbU::Unit EtesianEngine::toDbU ( int64_t v ) const { return v*getSliceStep(); } inline DbU::Unit EtesianEngine::toDbU ( int64_t v ) const { return v*getSliceStep(); }
inline uint32_t EtesianEngine::_getNewDiodeId () { return _diodeCount++; } inline uint32_t EtesianEngine::_getNewDiodeId () { return _diodeCount++; }
inline const Box& EtesianEngine::getPlaceArea () const { return _placeArea; }
inline Area* EtesianEngine::getArea () const { return _area; } inline Area* EtesianEngine::getArea () const { return _area; }
inline void EtesianEngine::setBlock ( Instance* block )
{
_block = block;
_placed = _block->getMasterCell()->isPlaced();
_placeArea = _block->getMasterCell()->getAbutmentBox();
}
inline Occurrence EtesianEngine::toCell ( Occurrence blockOccurrence ) const inline Occurrence EtesianEngine::toCell ( Occurrence blockOccurrence ) const
{ {
@ -243,6 +253,15 @@ namespace Etesian {
} }
inline Box EtesianEngine::toCell ( const Box& blockBox ) const
{
if (not _block) return blockBox;
Box cellBox = blockBox;
_block->getTransformation().applyOn( cellBox );
return cellBox;
}
inline Transformation EtesianEngine::toCell ( Transformation blockTransf ) const inline Transformation EtesianEngine::toCell ( Transformation blockTransf ) const
{ {
if (not _block) return blockTransf; if (not _block) return blockTransf;

View File

@ -266,6 +266,7 @@ namespace Etesian {
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;
inline const Box& getPlaceArea () const;
inline DbU::Unit getLeftDistance ( Cell* cell ) const; inline DbU::Unit getLeftDistance ( Cell* cell ) const;
inline DbU::Unit getRightDistance ( Cell* cell ) const; inline DbU::Unit getRightDistance ( Cell* cell ) const;
bool validate ( DbU::Unit latchUpMax ) const; bool validate ( DbU::Unit latchUpMax ) const;
@ -280,7 +281,7 @@ namespace Etesian {
private: private:
EtesianEngine* _etesian; EtesianEngine* _etesian;
TieLUT _tieLut; TieLUT _tieLut;
Box _cellAb; Box _placeArea;
DbU::Unit _sliceHeight; DbU::Unit _sliceHeight;
std::vector<Slice*> _slices; std::vector<Slice*> _slices;
size_t _spinSlice0; size_t _spinSlice0;
@ -290,8 +291,9 @@ namespace Etesian {
inline EtesianEngine* Area::getEtesian () const { return _etesian; } inline EtesianEngine* Area::getEtesian () const { return _etesian; }
inline size_t Area::getSpinSlice0 () const { return _spinSlice0; } inline size_t Area::getSpinSlice0 () const { return _spinSlice0; }
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 _placeArea.getXMin(); }
inline DbU::Unit Area::getXMax () const { return _cellAb.getXMax(); } inline DbU::Unit Area::getXMax () const { return _placeArea.getXMax(); }
inline const Box& Area::getPlaceArea () const { return _placeArea; }
inline DbU::Unit Area::getLeftDistance ( Cell* cell ) const { return _tieLut.getLeftDistance(cell); } inline DbU::Unit Area::getLeftDistance ( Cell* cell ) const { return _tieLut.getLeftDistance(cell); }
inline DbU::Unit Area::getRightDistance ( Cell* cell ) const { return _tieLut.getRightDistance(cell); } inline DbU::Unit Area::getRightDistance ( Cell* cell ) const { return _tieLut.getRightDistance(cell); }
inline string Area::_getString () const { return "<Etesian::Area>"; } inline string Area::_getString () const { return "<Etesian::Area>"; }