From 9df5f5f1b79797924d187f8f23e071163dd6213d Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Mon, 1 Feb 2021 16:24:44 +0100 Subject: [PATCH] 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. --- etesian/src/EtesianEngine.cpp | 32 +++++++++++++++--- etesian/src/Placement.cpp | 51 +++++++++++++++-------------- etesian/src/PyEtesianEngine.cpp | 23 +++++++++++++ etesian/src/etesian/EtesianEngine.h | 21 +++++++++++- etesian/src/etesian/Placement.h | 8 +++-- 5 files changed, 102 insertions(+), 33 deletions(-) diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 487796d9..ba860b07 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -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(); diff --git a/etesian/src/Placement.cpp b/etesian/src/Placement.cpp index b7c0d24a..e8851cf9 100644 --- a/etesian/src/Placement.cpp +++ b/etesian/src/Placement.cpp @@ -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 ; islicegetFeedCells().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 ; islicemerge( 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; } diff --git a/etesian/src/PyEtesianEngine.cpp b/etesian/src/PyEtesianEngine.cpp index a9159e3f..12258222 100644 --- a/etesian/src/PyEtesianEngine.cpp +++ b/etesian/src/PyEtesianEngine.cpp @@ -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 diff --git a/etesian/src/etesian/EtesianEngine.h b/etesian/src/etesian/EtesianEngine.h index 88e9f337..5bcb9a41 100644 --- a/etesian/src/etesian/EtesianEngine.h +++ b/etesian/src/etesian/EtesianEngine.h @@ -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* _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; diff --git a/etesian/src/etesian/Placement.h b/etesian/src/etesian/Placement.h index f71c566b..338ae8a6 100644 --- a/etesian/src/etesian/Placement.h +++ b/etesian/src/etesian/Placement.h @@ -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 _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 ""; }