coriolis/nimbus/src/NimbusEngine.cpp

1888 lines
51 KiB
C++

//
// This file is part of the Coriolis Project.
// Copyright (C) Laboratoire LIP6 - Departement ASIM
// Universite Pierre et Marie Curie
//
// Main contributors :
// Christophe Alexandre <Christophe.Alexandre@lip6.fr>
// Sophie Belloeil <Sophie.Belloeil@lip6.fr>
// Hugo Clément <Hugo.Clement@lip6.fr>
// Jean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
// Damien Dupuis <Damien.Dupuis@lip6.fr>
// Christian Masson <Christian.Masson@lip6.fr>
// Marek Sroka <Marek.Sroka@lip6.fr>
//
// The Coriolis Project is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// The Coriolis Project is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with the Coriolis Project; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
// License-Tag
//
//
// Date : 29/01/2004
// Author : Hugo Clément <Hugo.Clement@lip6.fr>
//
// Authors-Tag
#include "math.h"
#include "hurricane/Pin.h"
#include "hurricane/Library.h"
#include "hurricane/UpdateSession.h"
#include "crlcore/Utilities.h"
#include "crlcore/LefDefExtension.h"
#include "crlcore/ToolBox.h"
#include "crlcore/CellGauge.h"
#include "crlcore/RoutingGauge.h"
#include "nimbus/Grid.h"
#include "nimbus/Fence.h"
#include "nimbus/GCell.h"
#include "nimbus/GCells.h"
#include "nimbus/RoutTools.h"
#include "nimbus/SplitterContact.h"
#include "nimbus/NimbusEngine.h"
namespace Nimbus {
/*
* ********************************************************************
* Nimbus_GCells declaration
* ********************************************************************
*/
class Nimbus_GCells : public Collection<GCell*> {
public: typedef Collection<GCell*> Inherit;
public: class Locator : public Hurricane::Locator<GCell*> {
public: typedef Hurricane::Locator<GCell*> Inherit;
private: const GCellSet* _nbset;
private: GCellSet::iterator _nbit;
public: Locator(const GCellSet* nbset, GCellSet::iterator nbit);
public: Locator(const Locator& locator);
public: Locator& operator=(const Locator& locator);
public: virtual GCell* getElement() const;
public: virtual Hurricane::Locator<GCell*>* getClone() const;
public: virtual bool isValid() const;
public: virtual void progress();
public: virtual string _getString() const;
};
private: const GCellSet* _nbset;
private: GCellSet::iterator _nbit;
public: Nimbus_GCells(const GCellSet* nbset);
public: Nimbus_GCells(const Nimbus_GCells& gcelles);
public: Nimbus_GCells& operator=(const Nimbus_GCells& gcelles);
public: virtual Collection<GCell*>* getClone() const;
public: virtual Hurricane::Locator<GCell*>* getLocator() const;
public: virtual string _getString() const;
};
/*
* ********************************************************************
* Nimbus_ColumnGCells declaration
* ********************************************************************
*/
class Nimbus_ColumnGCells : public Collection<GCell*> {
public: typedef Collection<GCell*> Inherit;
public: class Locator : public Hurricane::Locator<GCell*> {
public: typedef Hurricane::Locator<GCell*> Inherit;
private: const GCell* _gcell;
public: Locator(const GCell* gcell);
public: Locator(const Locator& locator);
public: Locator& operator=(const Locator& locator);
public: virtual GCell* getElement() const;
public: virtual Hurricane::Locator<GCell*>* getClone() const;
public: virtual bool isValid() const;
public: virtual void progress();
public: virtual string _getString() const;
};
private: const GCell* _upperGCell;
public: Nimbus_ColumnGCells(const GCell* upperGCell);
public: Nimbus_ColumnGCells(const Nimbus_ColumnGCells& gcelles);
public: Nimbus_ColumnGCells& operator=(const Nimbus_ColumnGCells& gcelles);
public: virtual Collection<GCell*>* getClone() const;
public: virtual Hurricane::Locator<GCell*>* getLocator() const;
public: virtual string _getString() const;
};
/*
* ********************************************************************
* Nimbus_RowGCells declaration
* ********************************************************************
*/
class Nimbus_RowGCells : public Collection<GCell*> {
public: typedef Collection<GCell*> Inherit;
public: class Locator : public Hurricane::Locator<GCell*> {
public: typedef Hurricane::Locator<GCell*> Inherit;
private: const GCell* _gcell;
public: Locator(const GCell* gcell);
public: Locator(const Locator& locator);
public: Locator& operator=(const Locator& locator);
public: virtual GCell* getElement() const;
public: virtual Hurricane::Locator<GCell*>* getClone() const;
public: virtual bool isValid() const;
public: virtual void progress();
public: virtual string _getString() const;
};
private: const GCell* _leftGCell;
public: Nimbus_RowGCells(const GCell* left);
public: Nimbus_RowGCells(const Nimbus_RowGCells& gcelles);
public: Nimbus_RowGCells& operator=(const Nimbus_RowGCells& gcelles);
public: virtual Collection<GCell*>* getClone() const;
public: virtual Hurricane::Locator<GCell*>* getLocator() const;
public: virtual string _getString() const;
};
/*
* ********************************************************************
* Nimbus_Fences declaration
* ********************************************************************
*/
class Nimbus_Fences : public Collection<Fence*> {
public: typedef Collection<Fence*> Inherit;
public: class Locator : public Hurricane::Locator<Fence*> {
public: typedef Hurricane::Locator<Fence*> Inherit;
private: const FenceSet* _fcset;
private: FenceSet::iterator _fcit;
public: Locator(const FenceSet* fcset, FenceSet::iterator fcit);
public: Locator(const Locator& locator);
public: Locator& operator=(const Locator& locator);
public: virtual Fence* getElement() const;
public: virtual Hurricane::Locator<Fence*>* getClone() const;
public: virtual bool isValid() const;
public: virtual void progress();
public: virtual string _getString() const;
};
private: const FenceSet* _fcset;
private: FenceSet::iterator _fcit;
public: Nimbus_Fences(const FenceSet* fcset);
public: Nimbus_Fences(const Nimbus_Fences& fences);
public: Nimbus_Fences& operator=(const Nimbus_Fences& fences);
public: virtual Collection<Fence*>* getClone() const;
public: virtual Hurricane::Locator<Fence*>* getLocator() const;
public: virtual string _getString() const;
};
/*
* ********************************************************************
* Nimbus_Layers declaration
* ********************************************************************
*/
class Nimbus_Layers : public Collection<Layer*> {
public: typedef Collection<Layer*> Inherit;
public: class Locator : public Hurricane::Locator<Layer*> {
public: typedef Hurricane::Locator<Layer*> Inherit;
private: const set<Layer*>* _lset;
private: set<Layer*>::iterator _lit;
public: Locator(const set<Layer*>* lset, set<Layer*>::iterator lit);
public: Locator(const Locator& locator);
public: Locator& operator=(const Locator& locator);
public: virtual Layer* getElement() const;
public: virtual Hurricane::Locator<Layer*>* getClone() const;
public: virtual bool isValid() const;
public: virtual void progress();
public: virtual string _getString() const;
};
private: const set<Layer*>* _lset;
private: set<Layer*>::iterator _lit;
public: Nimbus_Layers(const set<Layer*>* lset);
public: Nimbus_Layers(const Nimbus_Layers& layers);
public: Nimbus_Layers& operator=(const Nimbus_Layers& layers);
public: virtual Collection<Layer*>* getClone() const;
public: virtual Hurricane::Locator<Layer*>* getLocator() const;
public: virtual string _getString() const;
};
void NimbusEngine::_preCreate(Cell* cell)
// **************************************
{
if ( cell->isTerminal() )
throw Error("Won't create Nimbus on a standard cell");
#if CORIOLIS_2_DEPRECATED
if (cell->getLibrary() == library) throw Error("Won't create Nimbus on a standard cell");
string libname (getString(library->getName()));
// ********************************************************************************************
//CellGauge* stdCellGauge(NULL);
// Check for CellGauge of library
CellGauge* cellGauge = AllianceFramework::get()->getCellGauge(library->getName());
if (cellGauge)
{
//stdCellGauge = cellGauges[libname];
cmess1 << " o Using existing cell gauge for library: <" << libname << ">" << endl;
}
else
{
//cerr << error << endl;
cmess1 << " o Creating cell gauge for library " << libname << endl;
// read std datas
Cells cells = library->getCells();
CellLocator cellLocator = cells.getLocator();
if (! cellLocator.isValid())
{
string message = "Invalid standard cell library ";
message += getString(library->getName());
throw Error ( message );
}
Cell* gaugeCell = cellLocator.getElement();
DbU::Unit sliceHeight = gaugeCell->getAbutmentBox().getHeight();
DbU::Unit pitch = gaugeCell->getAbutmentBox().getWidth();
cellLocator.progress();
while (cellLocator.isValid())
{
gaugeCell = cellLocator.getElement();
if (gaugeCell->getAbutmentBox().getHeight() != sliceHeight)
throw Error ("Inconsistent standard cell library");
if (gaugeCell->getAbutmentBox().getWidth() < pitch)
pitch = gaugeCell->getAbutmentBox().getWidth();
cellLocator.progress();
}
pitch = DbU::lambda (DbU::getLambda(pitch) / 2);
DbU::Unit sliceStep = pitch;
// Creating CellGauge in the CDataBase
cmess1 << " o adding cell gauge for " << libname << endl;
if (libname == "ibm01") sliceHeight = DbU::lambda(5.04);
AllianceFramework::get()->addCellGauge (CellGauge::create(libname.c_str(), "METAL2", pitch, sliceHeight, sliceStep));
//stdCellGauge = cellGauges[libname];
cmess1 << " o added cell gauge for " << libname << endl;
}
//getCDataBase()->setDefaultCellGauge(library->getName());
// *****************************************************************************************
// Check for routing layer gauge
RoutingGauge* routingGauge = AllianceFramework::get()->getRoutingGauge(library->getName());
if (!routingGauge) throw Error ("Nimbus : unable to find RoutingGauge associated with library : " +
getString(library->getName()));
Fence::setRoutingGauge(Configuration::getDefault()->getCellGauge());
#endif // CORIOLIS_2_DEPRECATED
}
const Name NimbusEngine::_toolName = "Nimbus";
NimbusEngine::NimbusEngine (Cell* cell, const Box& workZone)
// *********************************************************
: Inherit (cell)
, _configuration (new Configuration())
, _depth (0)
, _placementBoxSet()
, _routingBoxSet ()
, _routingLayerSet()
{
if ( not workZone.isEmpty() ) _configuration->setWorkZone(workZone);
}
NimbusEngine* NimbusEngine::create (Cell* cell, const Box& workZone)
// *****************************************************************
{
_preCreate(cell);
NimbusEngine* nimbus = new NimbusEngine (cell,workZone);
nimbus->_postCreate();
if ( nimbus->doPinsPlacement() ) nimbus->placePins();
return nimbus;
}
void NimbusEngine::_postCreate ()
// ******************************
{
Inherit::_postCreate();
// ********************************************************************************************
// fence display slot creation
//_displaySlot = DisplaySlot::create (getCell(), "Nimbus::Fences", 255, 0, 0, "FFFFFFFFFFFFFFFF", 1, 0, 255, 0, "CC33CC33CC33CC33", 1);
_grid = new Grid ( this );
if ( _grid == NULL )
throw Error ("NimbusEngine was unable to create the grid on <%s>"
,getString(getCell()->getName()).c_str());
getGrid()->getRoot()->setAsPlacementLeaf();
getGrid()->getRoot()->setAsRoutingLeaf();
}
void NimbusEngine::_preDestroy ()
// ******************************
{
#if 0
if (_grid)
delete _grid;
delete _configuration;
#endif
Inherit::_preDestroy();
}
const Name& NimbusEngine::staticGetName()
// *************************************
{
return _toolName;
}
void NimbusEngine::computeXSplit ( GCell* gcell, DbU::Unit* XSplit, unsigned nbSplits )
// ************************************************************************************
{
DbU::Unit X = gcell->getXMin();
DbU::Unit width = gcell->getWidth();
unsigned int numColsInf = (unsigned)rint( width / (getPitch() * nbSplits) );
// cerr << "computeXSplit(): width:" << DbU::getValueString(width)
// << " nbsplits:" << nbSplits
// << " " << (width / getPitch())
// << " numColsInf:" << numColsInf << endl;
if (numColsInf == 0)
throw Error ("NimbusEngine::computeXSplit(): %s too narrow to be splitted."
,DbU::getValueString(width).c_str());
DbU::Unit splitWidth = numColsInf * getPitch();
for ( unsigned i = 0 ; i < (nbSplits - 1) ; i++ ) {
XSplit[i] = X + (i+1) * splitWidth;
}
}
void NimbusEngine::computeYSplit ( GCell* gcell, DbU::Unit* YSplit, unsigned nbSplits )
// ************************************************************************************
{
DbU::Unit Y = gcell->getYMin();
DbU::Unit height = gcell->getHeight();
unsigned int numRowsInf = (unsigned)rint( height / (getSliceHeight() * nbSplits) );
if (numRowsInf == 0)
throw Error ("NimbusEngine::computeYSplit(): %s too narrow to be splitted."
,DbU::getValueString(height).c_str());
DbU::Unit splitHeight = numRowsInf * getSliceHeight();
for ( unsigned i = 0 ; i < (nbSplits - 1) ; i++ ) {
YSplit[i] = Y + (i+1) * splitHeight;
}
}
void NimbusEngine::horizontalLongSplit ( unsigned step, DbU::Unit& Y ) const
// **************************************************************
{
if ( !_grid )
throw Error ("NimbusEngine ERROR : Can't horizontalLongSplit because no grid exists!");
_grid->horizontalLongSplit ( step, Y );
return;
}
void NimbusEngine::verticalLongSplit ( unsigned step, DbU::Unit& X ) const
// ************************************************************
{
if ( !_grid )
throw Error ("NimbusEngine ERROR : Can't verticalLongSplit because no grid exists!");
_grid->verticalLongSplit ( step, X );
return;
}
void NimbusEngine::createFences ( unsigned depth )
// *****************************************
{
if ( !_grid )
throw Error ("Nimbus ERROR : Can't createFences because no grid exists!");
_grid->createFences ( depth );
return;
}
void NimbusEngine::placePins()
// *********************
{
UpdateSession::open();
DbU::Unit width = getCell()->getAbutmentBox().getWidth();
DbU::Unit height = getCell()->getAbutmentBox().getHeight();
DbU::Unit xMin = getCell()->getAbutmentBox().getXMin();
DbU::Unit yMin = getCell()->getAbutmentBox().getYMin();
PinIocOrder& northPins = LefDefExtension::getNorthPinIocOrder(getCell());
PinIocOrder& southPins = LefDefExtension::getSouthPinIocOrder(getCell());
PinIocOrder& eastPins = LefDefExtension::getEastPinIocOrder(getCell());
PinIocOrder& westPins = LefDefExtension::getWestPinIocOrder(getCell());
//PinIocOrder& undefinedPins = LefDefExtension::getUndefinedPinIoc(getCell());
unsigned northCount = northPins.size();
DbU::Unit pos = xMin;
if (northCount)
{
if (width - northCount <= 0)
throw Error("not enough place on north side");
DbU::Unit conSpace = width/northCount;
pos += conSpace / 2;
for (PinIocOrder::iterator pit = northPins.begin();
pit != northPins.end();
pit++)
{
Pin* pin = getCell()->getPin(*pit);
if (!pin)
throw Error("Unknown Pin named : " + getString(*pit));
pin->setPosition(pos, getCell()->getAbutmentBox().getYMax());
pos += conSpace;
}
}
unsigned southCount = southPins.size();
pos = xMin;
if (southCount)
{
if (width - southCount <= 0)
throw Error("not enough place on south side");
DbU::Unit conSpace = width/southCount;
pos += conSpace / 2;
for (PinIocOrder::iterator pit = southPins.begin();
pit != southPins.end();
pit++)
{
Pin* pin = getCell()->getPin(*pit);
if (!pin)
throw Error("Unknown Pin named : " + getString(*pit));
pin->setPosition(pos, getCell()->getAbutmentBox().getYMin());
pos += conSpace;
}
}
unsigned eastCount = eastPins.size();
pos = yMin;
if (eastCount)
{
if (height - eastCount <= 0)
throw Error("not enough place on east side");
DbU::Unit conSpace = width/eastCount;
pos += conSpace / 2;
for (PinIocOrder::iterator pit = eastPins.begin();
pit != eastPins.end();
pit++)
{
Pin* pin = getCell()->getPin(*pit);
if (!pin)
throw Error("Unknown Pin named : " + getString(*pit));
pin->setPosition(getCell()->getAbutmentBox().getXMax(), pos);
pos += conSpace;
}
}
unsigned westCount = westPins.size();
pos = yMin;
if (westCount)
{
if (height - westCount <= 0)
throw Error("not enough place on west side");
DbU::Unit conSpace = width/westCount;
pos += conSpace / 2;
for (PinIocOrder::iterator pit = westPins.begin();
pit != westPins.end();
pit++)
{
Pin* pin = getCell()->getPin(*pit);
if (!pin)
throw Error("Unknown Pin named : " + getString(*pit));
pin->setPosition(getCell()->getAbutmentBox().getYMin(), pos);
pos += conSpace;
}
}
UpdateSession::close();
}
void NimbusEngine::progress(int nbSplits)
// ********************************
{
progress ( nbSplits, nbSplits );
}
void NimbusEngine::progress(int nbXSplits, int nbYSplits)
// ************************************************
{
if ( ! (nbXSplits > 1) ) throw Error ( "NimbusEngine.progress error must divide into at least 2 gcells on X coordinate" );
if ( ! (nbYSplits > 1) ) throw Error ( "NimbusEngine.progress error must divide into at least 2 gcells on Y coordinate" );
DbU::Unit sliceHeight = getConfiguration()->getSliceHeight();
for_each_gcell (nb, _grid->getGCells(_depth))
{
if (nb->getHeight() == sliceHeight)
return;
end_for;
}
GCell* gcell = _grid->getRoot();
GCell* r = NULL;
for (unsigned step = 0 ; step < _depth ; step++) {
r = gcell->getSubUpperLeft();
if (!r) {
gcell->makeSub();
r = gcell->getSubUpperLeft();
}
gcell = r;
}
assert(gcell);
assert(gcell->getStep() == _depth);
_depth++;
try {
for ( GCell* nby = gcell ; nby != NULL ; nby = _grid->getRightOf (nby) )
{
DbU::Unit XSplit [nbXSplits-1];
computeXSplit ( nby, XSplit, nbXSplits );
for ( int i = 0 ; i < (nbXSplits-1) ; i++ ) {
_grid->verticalLongSplit (_depth, XSplit[i] );
}
}
for ( GCell* nbx = gcell ; nbx != NULL ; nbx = _grid->getDownOf (nbx) )
{
DbU::Unit YSplit [nbYSplits-1];
computeYSplit ( nbx, YSplit, nbYSplits );
for ( int i = 0 ; i < (nbYSplits-1) ; i++ ) {
_grid->horizontalLongSplit ( _depth, YSplit[i] );
}
}
_grid->createFences(_depth);
} catch (Hurricane::Error &e) {
if (e.getCode() != 1) throw e;
cmess1 << "[WARNING] Finest grid level reached" << endl;
destroyLevel(_depth);
}
}
void NimbusEngine::recDestroy(unsigned depth, GCell* gcell)
{
if (gcell->getDepth() == depth) gcell->destroy();
else for_each_gcell(subgcell, gcell->getSubGCells())
{
recDestroy(depth, subgcell);
end_for;
}
}
void NimbusEngine::destroyLevel(unsigned depth)
{
recDestroy (depth, getGrid()->getRoot());
if (depth > 0) _depth = depth - 1;
}
#if 0
void NimbusEngine::balanceLeaves()
{
GCell* CornerRB = _grid->getUpperLeftCorner(_step);
// Balancing columns
// *****************
{
GCell* col1RB = CornerRB;
GCell* col2RB = NULL;
while (col1RB)
{
col2RB = col1RB->getRightOfMe();
assert (col2RB);
GCell* nb1 = col1RB;
GCell* nb2 = col2RB;
// Cell surface & width summation
// ******************************
while (nb1 != NULL)
{
assert (nb2 != NULL);
cumulatedSurface1 += getCellsSurface (nb1);
cumulatedSurface2 += getCellsSurface (nb2);
cumulatedWidth1 += getCellsWidth (nb1);
cumulatedWidth2 += getCellsWidth (nb2);
nb1 = nb1->getDownOfMe();
nb2 = nb2->getDownOfMe();
}
// Tuning the vertical cut line
// ****************************
// Onto the next column pair
// *************************
col1RB = col2RB->getRightOfMe();
}
}
// Balancing rows
// **************
{
GCell* row1RB = CornerRB;
GCell* row2RB = NULL;
while (row1RB)
{
row2RB = row1RB->getDownOfMe();
assert (row2RB);
GCell* nb1 = row1RB;
GCell* nb2 = row2RB;
// Cell surface & height summation
// *******************************
while (nb1 != NULL)
{
assert (nb2 != NULL);
cumulatedSurface1 += getCellsSurface (nb1);
cumulatedSurface2 += getCellsSurface (nb2);
cumulatedHeight1 += getCellsHeight (nb1);
cumulatedHeight2 += getCellsHeight (nb2);
nb1 = nb1->getRightOfMe();
nb2 = nb2->getRightOfMe();
}
// Tuning the horizontal cut line
// ******************************
// Onto the next row pair
// **********************
row1RB = row2RB->getDownOfMe();
}
}
// Balancing finished
return;
} // balanceLeaves
#endif
#if 0
DbU::Unit NimbusEngine::getStandardCellHeight () const
// ****************************************
{
return _stdCellHeight;
}
#endif
GCell* NimbusEngine::getPlacementLeafContaining(Point& p)
// *************************************************
{
GCell* gcell = getGrid()->getRoot();
while (! (gcell->isAPlacementLeaf()) )
{
bool deeper = false;
for_each_gcell (nb, gcell->getSubGCells())
{
if (nb->strictContains(p))
{
gcell = nb;
deeper = true;
}
end_for;
}
if (!deeper) return NULL;
}
return gcell;
}
bool NimbusEngine::testMargin ( double margin )
// **************************************
{
bool testOK = true;
for_each_gcell ( gcell, getPlacementLeaves() )
{
string message = " - GCell " + getString( gcell ) + " :\t";
double NimbMargin = gcell->testMargin();
if ( NimbMargin < 0 )
{
message += "negative margin = " + getString ( NimbMargin );
testOK = false;
}
else if ( NimbMargin < margin )
{
message += "margin = " + getString ( NimbMargin ) + " < " + getString ( margin );
testOK = false;
}
else
{
message += "margin = " + getString ( NimbMargin ) + " : OK";
}
cmess1 << message << endl;
end_for;
}
return testOK;
}
bool NimbusEngine::testMargin ()
// *****************************
{
bool testOK = true;
for_each_gcell ( gcell, getPlacementLeaves() )
{
string message = " - GCell " + getString( gcell ) + " :\t";
double NimbMargin = gcell->testMargin();
if ( NimbMargin < 0 )
{
message += "negative margin = " + getString ( NimbMargin );
testOK = false;
}
else if ( NimbMargin < getMargin() )
{
message += "margin = " + getString ( NimbMargin ) + " < " + getString ( getMargin() );
testOK = false;
}
else
{
message += "margin = " + getString ( NimbMargin ) + " : OK";
}
cmess1 << message << endl;
end_for;
}
return testOK;
}
GCell* NimbusEngine::getRoutingLeafContaining(Point& p)
// ***********************************************
{
GCell* gcell = getGrid()->getRoot();
while (! (gcell->isARoutingLeaf()) )
{
bool deeper = false;
for_each_gcell (nb, gcell->getSubGCells())
{
if (nb->strictContains(p))
{
gcell = nb;
deeper = true;
}
end_for;
}
if (!deeper) return NULL;
}
return gcell;
}
GCell* NimbusEngine::getCommonAncester(GCell* nb1, GCell* nb2) const
// **************************************************************
{
if (nb1 == nb2) return nb1;
if (!nb1) return nb2;
if (!nb2) return nb1;
if (nb1->getStep() > nb2->getStep())
return getCommonAncester(nb1->getContainer(), nb2);
else
return getCommonAncester(nb1, nb2->getContainer());
return NULL;
}
GCells NimbusEngine::getLeaves() const
// *************************
{
return _grid->getGCells(_depth);
}
GCells NimbusEngine::getLeaves(unsigned step) const
// **************************************
{
if (step > _depth) throw ("[ERROR] Request for an unreached refinement level");
return _grid->getFastGCells(step);
}
Fences NimbusEngine::getFences(unsigned step)
// ************************************
{
if (step > _depth) throw ("[ERROR] Request for an unreached refinement level");
return (_grid->getFences(step));
}
GCells NimbusEngine::getPlacementLeaves() const
// ****************************************
{
return Nimbus_GCells(&_placementBoxSet);
}
GCells NimbusEngine::getRoutingLeaves() const
// **************************************
{
return Nimbus_GCells(&_routingBoxSet);
}
Fences NimbusEngine::getRoutingFences() const
// ************************************
{
return Nimbus_Fences(&_routingFenceSet);
}
GCells NimbusEngine::getColumnGCells( unsigned indexColumn ) const
// *************************************************************
{
GCell* _upperGCell = ((NimbusEngine*)this)->getGrid()->getUpperLeftCorner(((NimbusEngine*)this)->getDepth()); //(Nimbus*)this to avoid const problem
for ( unsigned i = indexColumn ; i > 0 ; i-- ) {
_upperGCell = _upperGCell->getRightOfMe();
if (!_upperGCell)
throw Error ( "NimbusEngine: Invalid Column Index" );
}
return Nimbus_ColumnGCells(_upperGCell);
}
GCells NimbusEngine::getRowGCells( unsigned indexRow ) const
// *******************************************************
{
GCell* _leftGCell = ((NimbusEngine*)this)->getGrid()->getUpperLeftCorner(((NimbusEngine*)this)->getDepth()); //(Nimbus*)this to avoid const problem
for ( unsigned i = indexRow ; i > 0 ; i-- ) {
_leftGCell = _leftGCell->getDownOfMe();
if (!_leftGCell)
throw Error ( "NimbusEngine: Invalid Row Index" );
}
return Nimbus_RowGCells(_leftGCell);
}
Layers NimbusEngine::getRoutingLayers() const
// ************************************
{
return Nimbus_Layers(&_routingLayerSet);
}
void NimbusEngine::flushRoutingFences()
// ******************************
{
for_each_fence(fence, getRoutingFences())
{
fence->_NotRoutingFence();
end_for;
}
_routingFenceSet.clear();
return;
}
void NimbusEngine::addToRoutingFences(Fence* fence)
// ******************************************
{
_routingFenceSet.insert(fence);
return;
}
void NimbusEngine::addToRoutingLayers(Layer* layer)
// ******************************************
{
_routingLayerSet.insert(layer);
return;
}
void NimbusEngine::flushPlacementLeaves()
// ******************************
{
for_each_gcell(gcell, getPlacementLeaves())
{
gcell->_setNotPlacementLeaf();
end_for;
}
_placementBoxSet.clear();
return;
}
void NimbusEngine::flushRoutingLeaves()
// ******************************
{
for_each_gcell(gcell, getRoutingLeaves())
{
gcell->_setNotRoutingLeaf();
end_for;
}
_routingBoxSet.clear();
return;
}
void NimbusEngine::setRoutingLeaf(GCell* gcell)
// ****************************************
{
setLeaf(gcell, _routingBoxSet);
return;
}
void NimbusEngine::setPlacementLeaf(GCell* gcell)
// ******************************************
{
setLeaf(gcell, _placementBoxSet);
return;
}
void NimbusEngine::setSubGCellsAsPlacementLeaves (GCell* gcell)
// **********************************************************
{
gcell->setSubGCellsAsPlacementLeaves();
return;
}
void NimbusEngine::setSubGCellsAsRoutingLeaves (GCell* gcell)
// ********************************************************
{
gcell->setSubGCellsAsRoutingLeaves();
return;
}
void NimbusEngine::setLeaf(GCell* gcell, GCellSet& nbset)
// ***************************************************
{
nbset.insert(gcell);
#if 0
GCell* container = gcell->getContainer();
while (container)
{
GCellSet::iterator nbit = nbset.find(container);
if (nbit != nbset.end())
nbset.erase(nbit);
container = container->getContainer();
}
#endif
return;
}
void NimbusEngine::_removePlacementLeaf(GCell* gcell)
// **********************************************
{
GCellSet::iterator nbit = _placementBoxSet.find(gcell);
if (nbit != _placementBoxSet.end())
_placementBoxSet.erase(nbit);
return;
}
void NimbusEngine::_removeRoutingLeaf(GCell* gcell)
// **********************************************
{
GCellSet::iterator nbit = _routingBoxSet.find(gcell);
if (nbit != _routingBoxSet.end())
_routingBoxSet.erase(nbit);
return;
}
void NimbusEngine::regroup(bool placed, bool fixed)
// *****************
{
grabPlacementModificationFlag();
UpdateSession::open();
for_each_instance(ins, getCell()->getInstances())
{
if ( (ins->getPlacementStatus() == Instance::PlacementStatus::PLACED) && !placed ) continue;
if ( (ins->getPlacementStatus() == Instance::PlacementStatus::FIXED ) && !fixed ) continue;
Box instanceABox = ins->getAbutmentBox();
Point insCenter = ins->getBoundingBox().getCenter();
GCell* nb = getPlacementLeafContaining(insCenter);
if ( nb )
{
Point center = nb->getCenter();
DbU::Unit xPos = center.getX();
DbU::Unit yPos = center.getY();
Box masterABox = ins->getMasterCell()->getAbutmentBox();
ins->setTransformation(
getTransformation(
masterABox,
xPos - instanceABox.getHalfWidth(),
yPos - instanceABox.getHalfHeight(),
Transformation::Orientation::ID)
);
}
else
{
cerr << "Didn't find PlacementLeaf for instance " << ins << endl;
}
end_for;
}
UpdateSession::close();
return;
}
void NimbusEngine::placementLeavesUp ()
// ******************************
{
UpdateSession::open();
grabPlacementModificationFlag();
set<GCell*> gcelles;
set<GCell*> newleaves;
getPlacementLeaves().fill(gcelles);
for_each_gcell (gcell, getPlacementLeaves())
{
GCell* container = gcell->getContainer();
if (container) gcelles.insert (container);
end_for;
}
for(set<GCell*>::iterator nbit = gcelles.begin() ; nbit != gcelles.end() ; nbit++)
{
GCell* nb1 = *nbit;
GCell* nb2 = *nbit;
bool found (false);
while ( (nb2 = nb2->getContainer()) )
{
if ( gcelles.find (nb2) != gcelles.end() )
found = true;
}
if (!found) newleaves.insert (nb1);
}
for(set<GCell*>::iterator nbit = newleaves.begin() ; nbit != newleaves.end() ; nbit++)
{
GCell* nb = *nbit;
nb->setAsPlacementLeaf();
}
hideFences();
showPlacementLeaves();
UpdateSession::close();
return;
}
void NimbusEngine::placementLeavesDown ()
// ******************************
{
UpdateSession::open();
grabPlacementModificationFlag();
set<GCell*> gcelles;
getPlacementLeaves().fill(gcelles);
for(set<GCell*>::iterator nbit = gcelles.begin() ; nbit != gcelles.end() ; nbit++)
{
(*nbit)->setSubGCellsAsPlacementLeaves();
}
hideFences();
showPlacementLeaves();
UpdateSession::close();
return;
}
void NimbusEngine::hideFences()
// **********************
{
for (unsigned step = 1; step <= _depth ; step++)
{
for_each_fence (fence, getFences(step))
{
fence->setInvisible();
end_for;
}
}
return;
}
void NimbusEngine::showPlacementLeaves()
// *******************************
{
for_each_gcell(gcell, getPlacementLeaves())
{
for_each_fence(fence, gcell->getSurroundingFences())
{
fence->setVisible();
end_for;
}
end_for;
}
for_each_go(go, getCell()->getExtensionSlice("Nimbus::Grid")->_getQuadTree()->getGos())
{
Fence* fence (NULL);
if (! (fence = (dynamic_cast<Fence*> (go)) ) ) continue;
if (! fence->isVisible() ) continue;
Fence* pfence (fence);
while ( (pfence = pfence->getParentFence()) ) pfence->setInvisible();
end_for;
}
return;
}
void NimbusEngine::showRoutingLeaves()
// *******************************
{
for_each_gcell(gcell, getRoutingLeaves())
{
for_each_fence(fence, gcell->getSurroundingFences())
{
fence->setVisible();
end_for;
}
end_for;
}
return;
}
void NimbusEngine::invalidateSplitterContactsOppositeCounts(Net* net)
// ************************************************************
{
assert(net);
for_each_component(compo, net->getComponents())
{
if (! (dynamic_cast<SplitterContact*> (compo)) )
continue;
SplitterContact* sc = dynamic_cast<SplitterContact*> (compo);
sc->invalidateOppositeCounts();
end_for;
}
return;
}
void NimbusEngine::invalidateSplitterContactsOppositeCounts()
// ****************************************************
{
for_each_net(net, getCell()->getNets())
{
invalidateSplitterContactsOppositeCounts(net);
end_for;
}
return;
}
string NimbusEngine::_getString() const
// ******************************
{
return "<" + _TName("Nimbus") + ">";
}
Record* NimbusEngine::_getRecord() const
// *************************
{
Record* record = Inherit::_getRecord();
if (record) {
record->add(getSlot("Depth", _depth));
record->add(getSlot("Root Box", _grid->getRoot()));
}
return record;
}
const Name& NimbusEngine::getName () const
{
return _toolName;
}
NimbusEngine* NimbusEngine::get ( Cell* cell )
{
return static_cast<NimbusEngine*>(ToolEngine::get(cell, staticGetName()));
}
/*
* ********************************************************************
* Nimbus_GCells implementation
*
*/
Nimbus_GCells::Nimbus_GCells(const GCellSet* nbset)
// **************************************************************************************
: Inherit()
, _nbset(nbset)
{
assert(nbset);
_nbit = nbset->begin();
}
Nimbus_GCells::Nimbus_GCells(const Nimbus_GCells& gcelles)
// ************************************************************************************
: Inherit()
, _nbset(gcelles._nbset)
, _nbit(gcelles._nbit)
{
}
Nimbus_GCells& Nimbus_GCells::operator=(const Nimbus_GCells& gcelles)
// ****************************************************************
{
_nbset = gcelles._nbset;
_nbit = gcelles._nbit;
return *this;
}
Collection<GCell*>* Nimbus_GCells::getClone() const
// ***********************************************
{
return new Nimbus_GCells(*this);
}
Locator<GCell*>* Nimbus_GCells::getLocator() const
// **********************************************
{
return new Locator(_nbset, _nbit);
}
string Nimbus_GCells::_getString() const
// *************************************
{
string s = "<" + _TName("Nimbus::GCells");
//if (_gcellIterator) s += " " + getString((*_gcellIterator));
s += ">";
return s;
}
/*
* ********************************************************************
* Nimbus_GCells::Locator implementation
*/
Nimbus_GCells::Locator::Locator(const GCellSet* nbset, GCellSet::iterator nbit)
// ************************************************************************************
: Inherit(),
_nbset(nbset),
_nbit(nbit)
{
}
Nimbus_GCells::Locator::Locator(const Locator& locator)
// ****************************************************
: Inherit(),
_nbset(locator._nbset),
_nbit(locator._nbit)
{
}
Nimbus_GCells::Locator& Nimbus_GCells::Locator::operator=(const Locator& locator)
// ******************************************************************************
{
_nbset = locator._nbset;
_nbit = locator._nbit;
return *this;
}
GCell* Nimbus_GCells::Locator::getElement() const
// **************************************************
{
return (*_nbit);
}
Locator<GCell*>* Nimbus_GCells::Locator::getClone() const
// *****************************************************************
{
return new Locator(*this);
}
bool Nimbus_GCells::Locator::isValid() const
// **************************************************
{
return (_nbit != _nbset->end());
}
void Nimbus_GCells::Locator::progress()
// *********************************************
{
_nbit++;
return;
}
string Nimbus_GCells::Locator::_getString() const
// *******************************************************
{
string s = "<" + _TName("Nimbus::GCells::Locator");
if (_nbit != _nbset->end()) s += " " + getString(*_nbit);
s += ">";
return s;
}
/*
* ********************************************************************
* Nimbus_ColumnGCells implementation
*
*/
Nimbus_ColumnGCells::Nimbus_ColumnGCells(const GCell* upperGCell)
// *********************************************************************
: Inherit(),
_upperGCell ( upperGCell )
{
}
Nimbus_ColumnGCells::Nimbus_ColumnGCells(const Nimbus_ColumnGCells& gcelles)
// ********************************************************************************
: Inherit()
{
_upperGCell = gcelles._upperGCell;
}
Nimbus_ColumnGCells& Nimbus_ColumnGCells::operator=(const Nimbus_ColumnGCells& gcelles)
// *******************************************************************************************
{
_upperGCell = gcelles._upperGCell;
return *this;
}
Collection<GCell*>* Nimbus_ColumnGCells::getClone() const
// *********************************************************
{
return new Nimbus_ColumnGCells(*this);
}
Locator<GCell*>* Nimbus_ColumnGCells::getLocator() const
// **********************************************
{
return new Locator(_upperGCell);
}
string Nimbus_ColumnGCells::_getString() const
// *********************************************
{
string s = "<" + _TName("Nimbus::ColumnGCells");
//if (_gcellIterator) s += " " + getString((*_gcellIterator));
s += ">";
return s;
}
/*
* ********************************************************************
* Nimbus_ColumnGCells::Locator implementation
*/
Nimbus_ColumnGCells::Locator::Locator(const GCell* gcell)
// **********************************************************
: Inherit(),
_gcell(gcell)
{
}
Nimbus_ColumnGCells::Locator::Locator(const Locator& locator)
// ************************************************************
: Inherit(),
_gcell(locator._gcell)
{
}
Nimbus_ColumnGCells::Locator& Nimbus_ColumnGCells::Locator::operator=(const Locator& locator)
// **********************************************************************************************
{
_gcell = locator._gcell;
return *this;
}
GCell* Nimbus_ColumnGCells::Locator::getElement() const
// *******************************************************
{
return (GCell*)_gcell;
}
Locator<GCell*>* Nimbus_ColumnGCells::Locator::getClone() const
// ***************************************************************
{
return new Locator(*this);
}
bool Nimbus_ColumnGCells::Locator::isValid() const
// **************************************************
{
return (_gcell != NULL);
}
void Nimbus_ColumnGCells::Locator::progress()
// *********************************************
{
_gcell = _gcell->getDownOfMe();
return;
}
string Nimbus_ColumnGCells::Locator::_getString() const
// *******************************************************
{
string s = "<" + _TName("Nimbus::ColumnGCells::Locator");
s += " " + getString(_gcell);
s += ">";
return s;
}
/*
* ********************************************************************
* Nimbus_RowGCells implementation
*
*/
Nimbus_RowGCells::Nimbus_RowGCells(const GCell* leftGCell)
// *************************************************************
: Inherit(),
_leftGCell ( leftGCell )
{
}
Nimbus_RowGCells::Nimbus_RowGCells(const Nimbus_RowGCells& gcelles)
// ***********************************************************************
: Inherit()
{
_leftGCell = gcelles._leftGCell;
}
Nimbus_RowGCells& Nimbus_RowGCells::operator=(const Nimbus_RowGCells& gcelles)
// *******************************************************************************************
{
_leftGCell = gcelles._leftGCell;
return *this;
}
Collection<GCell*>* Nimbus_RowGCells::getClone() const
// ******************************************************
{
return new Nimbus_RowGCells(*this);
}
Locator<GCell*>* Nimbus_RowGCells::getLocator() const
// *****************************************************
{
return new Locator(_leftGCell);
}
string Nimbus_RowGCells::_getString() const
// ******************************************
{
string s = "<" + _TName("Nimbus::RowGCells");
//if (_gcellIterator) s += " " + getString((*_gcellIterator));
s += ">";
return s;
}
/*
* ********************************************************************
* Nimbus_RowGCells::Locator implementation
*/
Nimbus_RowGCells::Locator::Locator(const GCell* gcell)
// *******************************************************
: Inherit(),
_gcell(gcell)
{
}
Nimbus_RowGCells::Locator::Locator(const Locator& locator)
// *********************************************************
: Inherit(),
_gcell(locator._gcell)
{
}
Nimbus_RowGCells::Locator& Nimbus_RowGCells::Locator::operator=(const Locator& locator)
// ****************************************************************************************
{
_gcell = locator._gcell;
return *this;
}
GCell* Nimbus_RowGCells::Locator::getElement() const
// ****************************************************
{
return (GCell*)_gcell;
}
Locator<GCell*>* Nimbus_RowGCells::Locator::getClone() const
// ************************************************************
{
return new Locator(*this);
}
bool Nimbus_RowGCells::Locator::isValid() const
// **********************************************
{
return (_gcell != NULL);
}
void Nimbus_RowGCells::Locator::progress()
// *****************************************
{
_gcell = _gcell->getRightOfMe();
return;
}
string Nimbus_RowGCells::Locator::_getString() const
// ***************************************************
{
string s = "<" + _TName("Nimbus::RowGCells::Locator");
s += " " + getString(_gcell);
s += ">";
return s;
}
/*
* ********************************************************************
* Nimbus_Fences implementation
*
*/
Nimbus_Fences::Nimbus_Fences(const FenceSet* fcset)
// **************************************************************************************
: Inherit()
, _fcset(fcset)
{
assert(fcset);
_fcit = fcset->begin();
}
Nimbus_Fences::Nimbus_Fences(const Nimbus_Fences& fences)
// ************************************************************************************
: Inherit()
, _fcset(fences._fcset)
, _fcit(fences._fcit)
{
}
Nimbus_Fences& Nimbus_Fences::operator=(const Nimbus_Fences& fences)
// ****************************************************************
{
_fcset = fences._fcset;
_fcit = fences._fcit;
return *this;
}
Collection<Fence*>* Nimbus_Fences::getClone() const
// ***********************************************
{
return new Nimbus_Fences(*this);
}
Locator<Fence*>* Nimbus_Fences::getLocator() const
// **********************************************
{
return new Locator(_fcset, _fcit);
}
string Nimbus_Fences::_getString() const
// *************************************
{
string s = "<" + _TName("Nimbus::Fences");
//if (_fenceIterator) s += " " + getString((*_fenceIterator));
s += ">";
return s;
}
/*
* ********************************************************************
* Nimbus_Fences::Locator implementation
*/
Nimbus_Fences::Locator::Locator(const FenceSet* fcset, FenceSet::iterator fcit)
// ************************************************************************************
: Inherit(),
_fcset(fcset),
_fcit(fcit)
{
}
Nimbus_Fences::Locator::Locator(const Locator& locator)
// ****************************************************
: Inherit(),
_fcset(locator._fcset),
_fcit(locator._fcit)
{
}
Nimbus_Fences::Locator& Nimbus_Fences::Locator::operator=(const Locator& locator)
// ******************************************************************************
{
_fcset = locator._fcset;
_fcit = locator._fcit;
return *this;
}
Fence* Nimbus_Fences::Locator::getElement() const
// **************************************************
{
return (*_fcit);
}
Locator<Fence*>* Nimbus_Fences::Locator::getClone() const
// *****************************************************************
{
return new Locator(*this);
}
bool Nimbus_Fences::Locator::isValid() const
// **************************************************
{
return (_fcit != _fcset->end());
}
void Nimbus_Fences::Locator::progress()
// *********************************************
{
_fcit++;
return;
}
string Nimbus_Fences::Locator::_getString() const
// *******************************************************
{
string s = "<" + _TName("Nimbus::Fences::Locator");
if (_fcit != _fcset->end()) s += " " + getString(*_fcit);
s += ">";
return s;
}
/*
* ********************************************************************
* Nimbus_Layers implementation
*
*/
Nimbus_Layers::Nimbus_Layers(const set<Layer*>* lset)
// **************************************************************************************
: Inherit()
, _lset(lset)
{
assert(lset);
_lit = lset->begin();
}
Nimbus_Layers::Nimbus_Layers(const Nimbus_Layers& layers)
// ************************************************************************************
: Inherit()
, _lset(layers._lset)
, _lit(layers._lit)
{
}
Nimbus_Layers& Nimbus_Layers::operator=(const Nimbus_Layers& layers)
// ****************************************************************
{
_lset = layers._lset;
_lit = layers._lit;
return *this;
}
Collection<Layer*>* Nimbus_Layers::getClone() const
// ***********************************************
{
return new Nimbus_Layers(*this);
}
Locator<Layer*>* Nimbus_Layers::getLocator() const
// **********************************************
{
return new Locator(_lset, _lit);
}
string Nimbus_Layers::_getString() const
// *************************************
{
string s = "<" + _TName("Nimbus::Layers");
//if (_layerIterator) s += " " + getString((*_layerIterator));
s += ">";
return s;
}
/*
* ********************************************************************
* Nimbus_Layers::Locator implementation
*/
Nimbus_Layers::Locator::Locator(const set<Layer*>* lset, set<Layer*>::iterator lit)
// ************************************************************************************
: Inherit(),
_lset(lset),
_lit(lit)
{
}
Nimbus_Layers::Locator::Locator(const Locator& locator)
// ****************************************************
: Inherit(),
_lset(locator._lset),
_lit(locator._lit)
{
}
Nimbus_Layers::Locator& Nimbus_Layers::Locator::operator=(const Locator& locator)
// ******************************************************************************
{
_lset = locator._lset;
_lit = locator._lit;
return *this;
}
Layer* Nimbus_Layers::Locator::getElement() const
// **************************************************
{
return (*_lit);
}
Locator<Layer*>* Nimbus_Layers::Locator::getClone() const
// *****************************************************************
{
return new Locator(*this);
}
bool Nimbus_Layers::Locator::isValid() const
// **************************************************
{
return (_lit != _lset->end());
}
void Nimbus_Layers::Locator::progress()
// *********************************************
{
_lit++;
return;
}
string Nimbus_Layers::Locator::_getString() const
// *******************************************************
{
string s = "<" + _TName("Nimbus::Layers::Locator");
if (_lit != _lset->end()) s += " " + getString(*_lit);
s += ">";
return s;
}
} // namespace Nimbus