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.
This commit is contained in:
Jean-Paul Chaput 2019-12-15 19:28:54 +01:00
parent 9812f2fc3a
commit e711ce8dd2
11 changed files with 186 additions and 88 deletions

View File

@ -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; }

View File

@ -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 )

View File

@ -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 )

View File

@ -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 )

View File

@ -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 ) );

View File

@ -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

View File

@ -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 }" );

View File

@ -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();

View File

@ -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<FlatInstance> _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 ; i<iRight ; ++i ) {
BloatState* state = BloatExtension::get( _instances[i].getOccurrence() );
if (not state) {
if (_owner->getKatana()->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.

View File

@ -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;

View File

@ -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'):