From e711ce8dd29d5dd586a144363299e79098e0e03b Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sun, 15 Dec 2019 19:28:54 +0100 Subject: [PATCH] More configuration parameters for P&R Conductor, for experimenting. * Change: In Hurricane::Viewer::ExceptionWidget & CRL/python/helpers/io.py, downscale icons for non-HiDPI screen. * Change: In CRL/etc/common/display.py, change the display threshold of METAL1 layer so it do not appear at high scaling. * New: In Etesian, activate the "setFixedAbHeight()" feature and export it to Python. Allows to increase the space margin at constant height. To be used by the P&R conductor. * Change: In Unicorn/cgt.py, when running a script, insert the current working directory at head of the sys.path, not at the end. So installed modules do not shadow local one. * New: In Anabatic::Edge, new accessor "getRawcapacity()" to know the full capacity of the edge, that is, the real maximum number of tracks that can go through the associated side. * Change: In Katana/BloatProfile/Slice::tagsOverloaded(), bloating policy change, now bloat all the instances under the GCell, not only the first one. * Change: In KatanaEngine::runGlobalRouter(), restore the search halo growth policy to expanding of 3 GCells every 3 iterations. New metrics displayed, the edge wire length length overload. * Change: In cumulus/plugins/ConductorPlugin.py, now accepts the following configuration parameters: - "anabatic.globalIterationsEstimate", maximum number of global iterations during the bloating computation passes. - "conductor.useFixedAbHeight", tells wether the additionnal blank space must be added so the aspect ratio is kept or the height is kept (and the block become wider). Disable the display of "rubber" to unclutter a little the view. --- anabatic/src/anabatic/Edge.h | 2 + crlcore/etc/common/display.py | 2 +- crlcore/python/helpers/io.py | 4 +- cumulus/src/plugins/ConductorPlugin.py | 30 +++- etesian/src/EtesianEngine.cpp | 2 +- etesian/src/PyEtesianEngine.cpp | 3 + hurricane/src/viewer/ExceptionWidget.cpp | 2 +- hurricane/src/viewer/PyViewer.cpp | 4 +- katana/src/BloatProfile.cpp | 201 +++++++++++++++-------- katana/src/GlobalRoute.cpp | 22 ++- unicorn/src/cgt.py | 2 +- 11 files changed, 186 insertions(+), 88 deletions(-) diff --git a/anabatic/src/anabatic/Edge.h b/anabatic/src/anabatic/Edge.h index 20f25ddd..180a7ff8 100644 --- a/anabatic/src/anabatic/Edge.h +++ b/anabatic/src/anabatic/Edge.h @@ -60,6 +60,7 @@ namespace Anabatic { inline bool isHorizontal () const; inline bool hasNet ( const Net* ) const; inline unsigned int getCapacity () const; + inline unsigned int getRawCapacity () const; inline unsigned int getReservedCapacity () const; inline unsigned int getCapacity ( size_t depth ) const; inline unsigned int getRealOccupancy () const; @@ -137,6 +138,7 @@ namespace Anabatic { inline bool Edge::isHorizontal () const { return _flags.isset(Flags::Horizontal); } inline bool Edge::hasNet ( const Net* owner ) const { return getSegment(owner); } inline unsigned int Edge::getCapacity ( size_t depth ) const { return (_capacities) ? _capacities->getCapacity(depth) : 0; } + inline unsigned int Edge::getRawCapacity () const { return (_capacities) ? _capacities->getCapacity() : 0; } inline unsigned int Edge::getReservedCapacity () const { return _reservedCapacity; } inline unsigned int Edge::getRealOccupancy () const { return _realOccupancy; } inline float Edge::getEstimateOccupancy () const { return _estimateOccupancy; } diff --git a/crlcore/etc/common/display.py b/crlcore/etc/common/display.py index 6f38e44e..6c202ada 100644 --- a/crlcore/etc/common/display.py +++ b/crlcore/etc/common/display.py @@ -229,7 +229,7 @@ def createStyles ( scale=1.0 ): style.addDrawingStyle( group='Active Layers', name='poly2' , color=toRGB('Orange' ), pattern=toHexa('poids2.8' ), border=1, threshold=0.00*scale ) # Routing Layers. - style.addDrawingStyle( group='Routing Layers', name='metal1' , color=toRGB('Blue' ), pattern=toHexa('slash.8' ), border=1, threshold=0.00*scale ) + style.addDrawingStyle( group='Routing Layers', name='metal1' , color=toRGB('Blue' ), pattern=toHexa('slash.8' ), border=1, threshold=0.80*scale ) style.addDrawingStyle( group='Routing Layers', name='metal2' , color=toRGB('Aqua' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale ) style.addDrawingStyle( group='Routing Layers', name='metcap' , color=toRGB('DarkTurquoise'), pattern=toHexa('poids2.8' ), border=2, threshold=0.00*scale ) style.addDrawingStyle( group='Routing Layers', name='metal3' , color=toRGB('LightPink' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale ) diff --git a/crlcore/python/helpers/io.py b/crlcore/python/helpers/io.py index c87b566e..f21f72ca 100644 --- a/crlcore/python/helpers/io.py +++ b/crlcore/python/helpers/io.py @@ -121,8 +121,10 @@ class ErrorWidget ( QDialog ): vLayout.addStretch( 1 ) vLayout.addLayout ( buttonLayout ) + pixmapWidth = 150 + if not Viewer.Graphics.isHighDpi(): pixmapWidth = 70 pixmap = QPixmap( ':/images/angry-birds-red.png' ) - pixmap = pixmap.scaledToWidth( 150 ) + pixmap = pixmap.scaledToWidth( pixmapWidth ) icon = QLabel() icon.setPixmap( pixmap ) diff --git a/cumulus/src/plugins/ConductorPlugin.py b/cumulus/src/plugins/ConductorPlugin.py index 1ca2e576..62b43bd6 100644 --- a/cumulus/src/plugins/ConductorPlugin.py +++ b/cumulus/src/plugins/ConductorPlugin.py @@ -20,6 +20,7 @@ try: import math import Cfg import Hurricane + from Hurricane import DbU from Hurricane import Breakpoint from Hurricane import UpdateSession import Viewer @@ -66,10 +67,25 @@ def ScriptMain ( **kw ): stopLevel = Cfg.getParamInt('conductor.stopLevel').asInt() Breakpoint.setStopLevel( stopLevel ) + Cfg.Configuration.pushDefaultPriority( Cfg.Parameter.Priority.Interactive ) + + grIterations = 10 + if Cfg.hasParameter('anabatic.globalIterations'): + grIterations = Cfg.getParamInt('anabatic.globalIterations').asInt() + + grIterationsEstimate = 7 + if Cfg.hasParameter('anabatic.globalIterationsEstimate'): + grIterationsEstimate = Cfg.getParamInt('anabatic.globalIterationsEstimate').asInt() + Cfg.getParamInt('anabatic.globalIterations').setInt( grIterationsEstimate ) + maxPlaceIterations = 2 if Cfg.hasParameter('conductor.maxPlaceIterations'): maxPlaceIterations = Cfg.getParamInt('conductor.maxPlaceIterations').asInt() + useFixedAbHeight = False + if Cfg.hasParameter('conductor.useFixedAbHeight'): + useFixedAbHeight = Cfg.getParamBool('conductor.useFixedAbHeight').asBool() + cell = None if kw.has_key('cell') and kw['cell']: cell = kw['cell'] @@ -78,6 +94,7 @@ def ScriptMain ( **kw ): if kw.has_key('editor') and kw['editor']: editor = kw['editor'] print ' o Editor found, running in graphic mode.' + editor.setLayerVisible( 'rubber', False ) if cell == None: cell = editor.getCell() if cell == None: @@ -102,7 +119,11 @@ def ScriptMain ( **kw ): etesian = Etesian.EtesianEngine.create( cell ) etesian.setPassNumber( iteration ) if editor: etesian.setViewer( editor ) - if iteration: etesian.resetPlacement() + if iteration: + if useFixedAbHeight and iteration == 1: + etesian.setFixedAbHeight( cell.getAbutmentBox().getHeight() ) + print 'etesian.setFixedAbHeight():', DbU.getValueString(cell.getAbutmentBox().getHeight()) + etesian.resetPlacement() etesian.place() etesian.destroy() etesian = None @@ -110,6 +131,9 @@ def ScriptMain ( **kw ): editor.refresh() editor.fit() + if iteration+1 == maxPlaceIterations: + Cfg.getParamInt('anabatic.globalIterations').setInt( grIterations ) + katana = Katana.KatanaEngine.create( cell ) katana.setPassNumber( iteration ) if editor: katana.setViewer( editor ) @@ -120,6 +144,8 @@ def ScriptMain ( **kw ): ) #| Katana.Flags.ShowFailedNets Breakpoint.stop( 1, 'After routing iteration %d' % iteration ) + if editor: + editor.setShowSelection( False ) if katana.isGlobalRoutingSuccess(): break iteration += 1 @@ -138,6 +164,8 @@ def ScriptMain ( **kw ): #plugins.RSavePlugin.ScriptMain( **kw ) + Cfg.Configuration.popDefaultPriority() + except Exception, e: catch( e ) diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 221a023c..093e008b 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -394,7 +394,7 @@ namespace Etesian { double gcellLength = cellLength*(1.0+spaceMargin) / DbU::toLambda( getSliceHeight() ); double rows = 0.0; - setFixedAbHeight( 0 ); + //setFixedAbHeight( 0 ); if (getFixedAbHeight()) rows = getFixedAbHeight() / getSliceHeight(); else rows = std::ceil( sqrt( gcellLength/aspectRatio ) ); diff --git a/etesian/src/PyEtesianEngine.cpp b/etesian/src/PyEtesianEngine.cpp index 7d78bcc0..150e6578 100644 --- a/etesian/src/PyEtesianEngine.cpp +++ b/etesian/src/PyEtesianEngine.cpp @@ -69,6 +69,7 @@ extern "C" { DirectVoidMethod(EtesianEngine,etesian,setDefaultAb) DirectVoidMethod(EtesianEngine,etesian,resetPlacement) + DirectSetLongAttribute(PyEtesianEngine_setFixedAbHeight,setFixedAbHeight,PyEtesianEngine,EtesianEngine) static PyObject* PyEtesianEngine_get ( PyObject*, PyObject* args ) @@ -208,6 +209,8 @@ extern "C" { , "Set the sub-block (Instance) to place." } , { "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 + , "Use this height when computing the size of the default abutment box (disable aspect ratio)." } , { "resetPlacement" , (PyCFunction)PyEtesianEngine_resetPlacement , METH_NOARGS , "Compute and set the abutment box using the aspect ratio and the space margin." } , { "place" , (PyCFunction)PyEtesianEngine_place , METH_NOARGS diff --git a/hurricane/src/viewer/ExceptionWidget.cpp b/hurricane/src/viewer/ExceptionWidget.cpp index b1a992b1..90b487a4 100644 --- a/hurricane/src/viewer/ExceptionWidget.cpp +++ b/hurricane/src/viewer/ExceptionWidget.cpp @@ -137,7 +137,7 @@ namespace Hurricane { QLabel* leftMargin = new QLabel (); leftMargin->setSizePolicy ( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding ); - leftMargin->setPixmap ( QPixmap(":/images/angry-birds-bomb.png").scaledToWidth(200) ); + leftMargin->setPixmap ( QPixmap(":/images/angry-birds-bomb.png").scaledToWidth( Graphics::isHighDpi() ? 200 : 80 ) ); leftMargin->setStyleSheet ( "QLabel { background-color: #FF9999;" " padding: 5px }" ); diff --git a/hurricane/src/viewer/PyViewer.cpp b/hurricane/src/viewer/PyViewer.cpp index 895bf516..9829d6f2 100644 --- a/hurricane/src/viewer/PyViewer.cpp +++ b/hurricane/src/viewer/PyViewer.cpp @@ -108,9 +108,9 @@ extern "C" { Py_INCREF ( &PyTypeHApplication ); PyModule_AddObject ( module, "HApplication", (PyObject*)&PyTypeHApplication ); Py_INCREF ( &PyTypeGraphics ); - PyModule_AddObject ( module, "Graphics", (PyObject*)&PyTypeGraphics ); + PyModule_AddObject ( module, "Graphics" , (PyObject*)&PyTypeGraphics ); Py_INCREF ( &PyTypeCellViewer ); - PyModule_AddObject ( module, "CellViewer", (PyObject*)&PyTypeCellViewer ); + PyModule_AddObject ( module, "CellViewer" , (PyObject*)&PyTypeCellViewer ); PyDisplayStyle_postModuleInit(); PyCellViewer_postModuleInit(); diff --git a/katana/src/BloatProfile.cpp b/katana/src/BloatProfile.cpp index 2434a2e8..56ceab1a 100644 --- a/katana/src/BloatProfile.cpp +++ b/katana/src/BloatProfile.cpp @@ -52,6 +52,8 @@ namespace { using Anabatic::Edge; using namespace Katana; + class Slices; + // ------------------------------------------------------------------- // Class : "FlatInstance". @@ -116,19 +118,21 @@ namespace { class Slice { public: - inline Slice ( GCell* ); + inline Slice ( Slices*, GCell* ); inline DbU::Unit getY () const; inline void add ( Occurrence ); inline void sort (); void tagOverloadeds ( size_t& count, size_t& newCount ); private: + Slices* _owner; GCell* _left; vector _instances; }; - inline Slice::Slice ( GCell* left ) - : _left (left) + inline Slice::Slice ( Slices* owner, GCell* left ) + : _owner (owner) + , _left (left) , _instances() { } @@ -138,78 +142,17 @@ namespace { inline void Slice::sort () { std::sort( _instances.begin(), _instances.end() ); } - void Slice::tagOverloadeds ( size_t& count, size_t& newCount ) - { - GCell* gcell = _left; - Edge* eastEdge = _left->getEastEdge(); - Edge* northEdge = _left->getNorthEdge(); - bool bloated = false; - - //cerr << "+ Slice @" << DbU::getValueString(getY()) << endl; - - for ( FlatInstance& fi : _instances ) { - //cerr << "| @" << DbU::getValueString(fi.getX()) << " " << fi.getOccurrence() << endl; - - if (fi.getX() >= gcell->getXMax()) { - for ( gcell = gcell->getEast() ; gcell and (fi.getX() > gcell->getXMax()) - ; gcell = gcell->getEast() ) { - //cerr << "| Skip " << gcell << endl; - } - //cerr << "| Advance to " << gcell << endl; - if (not gcell) break; - - bloated = false; - eastEdge = gcell->getEastEdge(); - northEdge = gcell->getNorthEdge(); - } - - unsigned int overload = 0; - - if (eastEdge) { - if (eastEdge->getRealOccupancy() > eastEdge->getCapacity()) { - overload = eastEdge->getRealOccupancy() - eastEdge->getCapacity(); - } - // else if (eastEdge->getHistoricCost() > 3.0) { - // overload = 4; - // } - } - - if (northEdge) { - if (northEdge->getRealOccupancy() > northEdge->getCapacity()) { - overload = std::max( overload, northEdge->getRealOccupancy() - northEdge->getCapacity() ); - } - // else if (northEdge->getHistoricCost() > 3.0) { - // overload = 4; - // } - } - - if (overload and not bloated) { - bloated = true; - BloatState* state = BloatExtension::get( fi.getOccurrence() ); - if (not state) { - state = BloatExtension::create( fi.getOccurrence(), overload ); - //cerr << "> Bloat: " << fi.getOccurrence() << endl; - //cerr << "> Under:" << gcell << endl; - ++newCount; - } else { - state->setTracksCount( state->getTracksCount() + overload ); - } - ++count; - } - } - } - - // ------------------------------------------------------------------- // Class : "Slices". class Slices { public: - Slices ( KatanaEngine* ); - ~Slices (); - inline void add ( Occurrence ); - inline void sort (); - inline void tagOverloadeds (); + Slices ( KatanaEngine* ); + ~Slices (); + inline KatanaEngine* getKatana () const; + inline void add ( Occurrence ); + inline void sort (); + inline void tagOverloadeds (); private: KatanaEngine* _katana; Box _cellAb; @@ -250,7 +193,7 @@ namespace { , getString(left).c_str() ); - _slices.push_back( new Slice( left ) ); + _slices.push_back( new Slice( this, left ) ); left = left->getNorth(); } } @@ -260,6 +203,10 @@ namespace { { for ( Slice* slice : _slices ) delete slice; } + inline KatanaEngine* Slices::getKatana () const + { return _katana; } + + inline void Slices::sort () { for ( Slice* slice : _slices ) slice->sort(); } @@ -293,6 +240,118 @@ namespace { } + void Slice::tagOverloadeds ( size_t& count, size_t& newCount ) + { + GCell* gcell = _left; + size_t iLeft = 0; + size_t iRight = 0; + + while ( gcell ) { + //cerr << "> Under:" << gcell << endl; + + uint32_t overload = 0; + for ( Edge* edge : gcell->getEdges( Flags::NorthSide|Flags::EastSide ) ) { + if (edge->getRealOccupancy() > edge->getCapacity()) { + overload = std::max( overload, edge->getRealOccupancy() - edge->getCapacity() ); + + // if (edge->getRealOccupancy() > edge->getRawCapacity()) { + // overload += 4; + // } + } + } + + iLeft = iRight; + while ( iRight < _instances.size() ) { + if (_instances[iRight].getX() >= gcell->getXMax()) break; + ++iRight; + } + + if (iLeft >= _instances.size()) break; + + if (overload) { + overload += 4; + + for ( size_t i=iLeft ; igetKatana()->getPassNumber() > 0) continue; + + state = BloatExtension::create( _instances[i].getOccurrence(), overload ); + ++newCount; + + //cerr << "| Bloat: " << overload << " " << _instances[i].getOccurrence() << endl; + } else { + state->setTracksCount( state->getTracksCount() + overload ); + } + ++count; + } + } + + gcell = gcell->getEast(); + } + + + // GCell* gcell = _left; + // Edge* eastEdge = _left->getEastEdge(); + // Edge* northEdge = _left->getNorthEdge(); + // bool bloated = false; + + // //cerr << "+ Slice @" << DbU::getValueString(getY()) << endl; + + // for ( FlatInstance& fi : _instances ) { + // //cerr << "| @" << DbU::getValueString(fi.getX()) << " " << fi.getOccurrence() << endl; + + // if (fi.getX() >= gcell->getXMax()) { + // for ( gcell = gcell->getEast() ; gcell and (fi.getX() > gcell->getXMax()) + // ; gcell = gcell->getEast() ) { + // //cerr << "| Skip " << gcell << endl; + // } + // //cerr << "| Advance to " << gcell << endl; + // if (not gcell) break; + + // bloated = false; + // eastEdge = gcell->getEastEdge(); + // northEdge = gcell->getNorthEdge(); + // } + + // unsigned int overload = 0; + + // if (eastEdge) { + // if (eastEdge->getRealOccupancy() > eastEdge->getCapacity()) { + // overload = eastEdge->getRealOccupancy() - eastEdge->getCapacity(); + // } + // // else if (eastEdge->getHistoricCost() > 3.0) { + // // overload = 4; + // // } + // } + + // if (northEdge) { + // if (northEdge->getRealOccupancy() > northEdge->getCapacity()) { + // overload = std::max( overload, northEdge->getRealOccupancy() - northEdge->getCapacity() ); + // } + // // else if (northEdge->getHistoricCost() > 3.0) { + // // overload = 4; + // // } + // } + + // if (overload and not bloated) { + // bloated = true; + // overload += 8; + + // BloatState* state = BloatExtension::get( fi.getOccurrence() ); + // if (not state) { + // state = BloatExtension::create( fi.getOccurrence(), overload ); + // //cerr << "> Bloat: " << fi.getOccurrence() << endl; + // //cerr << "> Under:" << gcell << endl; + // ++newCount; + // } else { + // state->setTracksCount( state->getTracksCount() + overload ); + // } + // ++count; + // } + // } + } + } // Anonymous namespace. diff --git a/katana/src/GlobalRoute.cpp b/katana/src/GlobalRoute.cpp index 0ee138fd..05e166cb 100644 --- a/katana/src/GlobalRoute.cpp +++ b/katana/src/GlobalRoute.cpp @@ -493,6 +493,9 @@ namespace Katana { if (getState() >= EngineState::EngineGlobalLoaded) throw Error ("KatanaEngine::runGlobalRouter(): Global routing already done or loaded."); + if (flags & Flags::ShowBloatedInstances) selectBloatedInstances( this ); + Breakpoint::stop( 1, "Bloated cells from previous placement iteration." ); + startMeasures(); cmess1 << " o Running global routing." << endl; @@ -580,12 +583,14 @@ namespace Katana { edgeOverflowWL = 0; netCount = 0; if (iteration < globalIterations - 1) { + for ( Edge* edge : ovEdges ) { + edgeOverflowWL += edge->getRealOccupancy() - edge->getCapacity(); + } + size_t iEdge = 0; while ( iEdge < ovEdges.size() ) { - Edge* edge = ovEdges[iEdge]; - - edgeOverflowWL += edge->getRealOccupancy() - edge->getCapacity(); - netCount += edge->ripup(); + Edge* edge = ovEdges[iEdge]; + netCount += edge->ripup(); if (iEdge >= ovEdges.size()) break; if (ovEdges[iEdge] == edge) { @@ -597,16 +602,15 @@ namespace Katana { } } - //dijkstra->setSearchAreaHalo( (getSearchHalo() + 3*(iteration/3)) * Session::getSliceHeight() ); - dijkstra->setSearchAreaHalo( 3 * Session::getSliceHeight() ); + dijkstra->setSearchAreaHalo( (getSearchHalo() + 3*(iteration/3)) * Session::getSliceHeight() ); } - cmess2 << " ovE:" << setw(4) << overflow << " " << setw(5) << edgeOverflowWL; + cmess2 << " ovE:" << setw(4) << overflow << " ovWL:" << setw(5) << edgeOverflowWL; cmess2 << " ripup:" << setw(4) << netCount << right; suspendMeasures(); - cmess2 << " " << setw(6) << Timer::getStringMemory(getTimer().getIncrease()) - << " " << setw(5) << Timer::getStringTime (getTimer().getCombTime()) << endl; + cmess2 << " " << setw(7) << Timer::getStringMemory(getTimer().getIncrease()) + << " " << setw(6) << Timer::getStringTime (getTimer().getCombTime()) << endl; resumeMeasures(); ++iteration; diff --git a/unicorn/src/cgt.py b/unicorn/src/cgt.py index 958698d2..df02a73b 100755 --- a/unicorn/src/cgt.py +++ b/unicorn/src/cgt.py @@ -68,7 +68,7 @@ def runScript ( scriptPath, editor ): try: kw = { } if editor: kw[ 'editor' ] = editor - sys.path.append(os.path.dirname(scriptPath)) + sys.path.insert( 0, os.path.dirname(scriptPath) ) module = __import__( os.path.basename(scriptPath), globals(), locals() ) if not module.__dict__.has_key('ScriptMain'):