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)
, _ySpinSet (false)
, _flatDesign (false)
, _placeArea (cell->getAbutmentBox())
, _surface (NULL)
, _circuit (NULL)
, _placementLB (NULL)
@ -320,8 +321,7 @@ namespace Etesian {
, _fixedAbHeight(0)
, _fixedAbWidth (0)
, _diodeCount (0)
{
}
{ }
void EtesianEngine::_postCreate ()
@ -450,6 +450,27 @@ namespace Etesian {
{ 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 ()
{
_bloatCells.resetDxSpace();
@ -532,6 +553,7 @@ namespace Etesian {
, abWidth
, rows*getSliceHeight()
) );
_placeArea = getCell()->getAbutmentBox();
UpdateSession::close();
if (_viewer) _viewer->getCellWidget()->fitToContents();
@ -629,6 +651,7 @@ namespace Etesian {
// setFixedAbHeight( getBlockCell()->getAbutmentBox().getHeight() );
getBlockCell()->setAbutmentBox( Box() );
getBlockCell()->resetFlags( Cell::Flags::Placed );
_placeArea.makeEmpty();
UpdateSession::close();
dots.finish( Dots::Reset );
@ -646,7 +669,6 @@ namespace Etesian {
cmess1 << " o Converting <" << getCell()->getName() << "> into Coloquinte." << endl;
cmess1 << ::Dots::asString(" - H-pitch" , DbU::getValueString(hpitch)) << endl;
cmess1 << ::Dots::asString(" - V-pitch" , DbU::getValueString(vpitch)) << endl;
cmess2 << " o Looking through the hierarchy." << endl;
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 );
if (not cmess2.enabled()) dots.disable();
size_t instancesNb = 0;
size_t fixedNb = 0;
Box topAb = getBlockCell()->getAbutmentBox();
Box topAb = _placeArea;
Transformation topTransformation;
if (getBlockInstance()) {
topTransformation = getBlockInstance()->getTransformation();

View File

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

View File

@ -14,6 +14,7 @@
// +-----------------------------------------------------------------+
#include "hurricane/isobar/PyBox.h"
#include "hurricane/isobar/PyCell.h"
#include "hurricane/isobar/PyInstance.h"
#include "hurricane/viewer/PyCellViewer.h"
@ -49,6 +50,8 @@ namespace Etesian {
using Isobar::ParseOneArg;
using Isobar::ParseTwoArg;
using Isobar::EntityCast;
using Isobar::PyBox;
using Isobar::PyTypeBox;
using Isobar::PyCell;
using Isobar::PyCell_Link;
using Isobar::PyInstance;
@ -181,6 +184,24 @@ extern "C" {
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 )
{
@ -222,6 +243,8 @@ extern "C" {
, "Select the Cell bloating profile." }
, { "setBlock" , (PyCFunction)PyEtesianEngine_setBlock , METH_VARARGS
, "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
, "Compute and set the abutment box using the aspect ratio and the space margin." }
, { "setFixedAbHeight" , (PyCFunction)PyEtesianEngine_setFixedAbHeight , METH_VARARGS

View File

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

View File

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