1392 lines
32 KiB
C++
1392 lines
32 KiB
C++
|
|
// This file is part of the Coriolis Project.
|
|
// Copyright (C) Laboratoire LIP6 - Departement ASIM
|
|
// Universite Pierre et Marie Curie
|
|
//
|
|
// Date : 29/01/2004
|
|
// Author : Hugo Clément <Hugo.Clement@lip6.fr>
|
|
|
|
#include "hurricane/Cell.h"
|
|
#include "hurricane/Instance.h"
|
|
#include "crlcore/CellGauge.h"
|
|
#include "nimbus/VFence.h"
|
|
#include "nimbus/HFence.h"
|
|
#include "nimbus/GCell.h"
|
|
#include "nimbus/NimbusEngine.h"
|
|
|
|
namespace Nimbus {
|
|
|
|
|
|
/*
|
|
* ********************************************************************
|
|
* GCell_Fences declaration
|
|
* ********************************************************************
|
|
*/
|
|
class GCell_Fences : public Collection<Fence*> {
|
|
|
|
public: typedef Collection<Fence*> Inherit;
|
|
|
|
public: class Locator : public Hurricane::Locator<Fence*> {
|
|
|
|
public: typedef Hurricane::Locator<Fence*> Inherit;
|
|
|
|
private: const GCell* _nb;
|
|
private: Fence* _fence;
|
|
|
|
public: Locator(const GCell* gcell = NULL, Fence* fence = NULL);
|
|
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 GCell* _nb;
|
|
private: Fence* _fence;
|
|
|
|
public: GCell_Fences(const GCell* gcell);
|
|
public: GCell_Fences(const GCell_Fences& fences);
|
|
|
|
public: GCell_Fences& operator=(const GCell_Fences& fences);
|
|
|
|
public: virtual Collection<Fence*>* getClone() const;
|
|
public: virtual Hurricane::Locator<Fence*>* getLocator() const;
|
|
|
|
public: virtual string _getString() const;
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
* ********************************************************************
|
|
* Implementation of GCell
|
|
*
|
|
*/
|
|
|
|
GCell::GCell (NimbusEngine* nimbus, unsigned step, const Box& box, GCell* container)
|
|
// ***************************************************************************
|
|
: Inherit ()
|
|
, _nimbus (nimbus)
|
|
, _box(box)
|
|
, _step (step)
|
|
, _container (container)
|
|
, _nextOfGCellGCellSet (NULL)
|
|
, _subGCells()
|
|
, _subFences()
|
|
, _upfence (NULL)
|
|
, _downfence (NULL)
|
|
, _leftfence (NULL)
|
|
, _rightfence (NULL)
|
|
, _isAPlacementLeaf(false)
|
|
, _isARoutingLeaf(false)
|
|
{}
|
|
|
|
|
|
GCell* GCell::create(NimbusEngine* nimbus, unsigned step, const Box& box, GCell* container)
|
|
{
|
|
if (!nimbus)
|
|
throw Error("Can't create GCell : empty nimbus");
|
|
|
|
GCell* gcell = new GCell(nimbus, step, box, container);
|
|
gcell->_postCreate();
|
|
return gcell;
|
|
}
|
|
|
|
void GCell::_preDestroy ()
|
|
// ******************
|
|
{
|
|
if (_upfence)
|
|
_upfence->destroy();
|
|
if (_downfence)
|
|
_downfence->destroy();
|
|
if (_leftfence)
|
|
_leftfence->destroy();
|
|
if (_rightfence)
|
|
_rightfence->destroy();
|
|
|
|
if (_container) {
|
|
_container->removeSubGCell (this);
|
|
}
|
|
|
|
for_each_gcell (gcell, getSubGCells())
|
|
{
|
|
gcell->destroy();
|
|
end_for;
|
|
}
|
|
|
|
for (RBPavement::iterator rbpit = _pavement.begin();
|
|
rbpit != _pavement.end();
|
|
rbpit++)
|
|
{
|
|
delete rbpit->second;
|
|
}
|
|
}
|
|
|
|
Cell* GCell::getCell () const
|
|
// **************************
|
|
{
|
|
return _nimbus->getCell();
|
|
}
|
|
|
|
void GCell::setXMax (DbU::Unit x)
|
|
//**************************
|
|
{
|
|
DbU::Unit diff = x - getXMax();
|
|
_box.inflate (0, 0, diff, 0);
|
|
DbU::Unit width = getXMax() - getXMin();
|
|
if (_upfence) { _upfence ->setSize(width); _upfence ->computeCapacity(); }
|
|
if (_downfence) { _downfence ->setSize(width); _downfence ->computeCapacity(); }
|
|
return;
|
|
}
|
|
|
|
void GCell::setYMax (DbU::Unit y)
|
|
//**************************
|
|
{
|
|
DbU::Unit diff = y - getYMax();
|
|
_box.inflate (0, 0, 0, diff);
|
|
DbU::Unit height = getYMax() - getYMin();
|
|
if (_leftfence) { _leftfence ->setSize(height); _leftfence ->computeCapacity(); }
|
|
if (_rightfence) { _rightfence ->setSize(height); _rightfence ->computeCapacity(); }
|
|
return;
|
|
}
|
|
|
|
void GCell::setXMin (DbU::Unit x)
|
|
//**************************
|
|
{
|
|
DbU::Unit diff = getXMin() - x;
|
|
_box.inflate (diff, 0, 0, 0);
|
|
DbU::Unit width = getXMax() - getXMin();
|
|
if (_upfence) { _upfence ->setSize(width); _upfence ->computeCapacity(); }
|
|
if (_downfence) { _downfence ->setSize(width); _downfence ->computeCapacity(); }
|
|
return;
|
|
}
|
|
|
|
void GCell::setYMin (DbU::Unit y)
|
|
// **************************
|
|
{
|
|
DbU::Unit diff = getYMin() - y;
|
|
_box.inflate (0, diff, 0, 0);
|
|
DbU::Unit height = getYMax() - getYMin();
|
|
if (_leftfence) { _leftfence ->setSize(height); _leftfence ->computeCapacity(); }
|
|
if (_rightfence) { _rightfence ->setSize(height); _rightfence ->computeCapacity(); }
|
|
return;
|
|
}
|
|
|
|
bool GCell::hasSubGCells () const
|
|
// ******************************
|
|
{
|
|
return (!(getSubGCells().isEmpty()));
|
|
}
|
|
|
|
bool GCell::horizontalIsCrossed (DbU::Unit& Y) const
|
|
//*********************************
|
|
{
|
|
return (Interval (getYMin(), getYMax())).contains (Y);
|
|
}
|
|
|
|
bool GCell::verticalIsCrossed (DbU::Unit& X) const
|
|
//*********************************
|
|
{
|
|
return (Interval (getXMin(), getXMax())).contains (X);
|
|
}
|
|
|
|
bool GCell::strictContains(const Point& point) const
|
|
// *************************************************
|
|
{
|
|
return strictContains(point.getX(), point.getY());
|
|
}
|
|
|
|
bool GCell::strictContains(const DbU::Unit& x, const DbU::Unit& y) const
|
|
//* **********************************************************
|
|
{
|
|
bool res = (!isEmpty()) && (getXMin() <= x) && (getYMin() <= y);
|
|
if (getRightFence()) res &= (x < getXMax()); else res &= (x <= getXMax());
|
|
if (getUpFence()) res &= (y < getYMax()); else res &= (y <= getYMax());
|
|
return res;
|
|
}
|
|
|
|
void GCell::makeSub ()
|
|
// *******************
|
|
{
|
|
assert (!hasSubGCells());
|
|
Box box (getXMin(), getYMin(), getXMax(), getYMax());
|
|
GCell* gcell = new GCell (_nimbus, _step + 1, box, this);
|
|
addSubGCell (gcell);
|
|
return;
|
|
}
|
|
|
|
void GCell::subVSplit (DbU::Unit& X)
|
|
// ****************************
|
|
{
|
|
RBList tmp;
|
|
getSubGCells().fill(tmp);
|
|
|
|
for (
|
|
RBList::iterator lrbit = tmp.begin() ;
|
|
lrbit != tmp.end() ;
|
|
lrbit++
|
|
)
|
|
{
|
|
if ( (*lrbit)->hasSubGCells() ) {
|
|
throw Error("Nimbus: unable to split a gcell");
|
|
cerr << "Don't know how to split" << endl;
|
|
}
|
|
|
|
if ( (*lrbit)->verticalIsCrossed(X) ) {
|
|
|
|
RBPair subs = (*lrbit)->vSplitMe (X);
|
|
//removeSubGCell ( (*lrbit) );
|
|
(*lrbit)->destroy();
|
|
addSubGCell (subs.first);
|
|
addSubGCell (subs.second);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void GCell::subHSplit (DbU::Unit& Y)
|
|
// ****************************
|
|
{
|
|
RBList tmp;
|
|
getSubGCells().fill(tmp);
|
|
|
|
for (
|
|
RBList::iterator lrbit = tmp.begin() ;
|
|
lrbit != tmp.end() ;
|
|
lrbit++
|
|
)
|
|
{
|
|
if ( (*lrbit)->hasSubGCells() ) {
|
|
throw Error("Nimbus: unable to split a gcell");
|
|
cerr << "Don't know how to split" << endl;
|
|
}
|
|
|
|
if ( (*lrbit)->horizontalIsCrossed(Y) ) {
|
|
|
|
RBPair subs = (*lrbit)->hSplitMe (Y);
|
|
//removeSubGCell ( (*lrbit) );
|
|
(*lrbit)->destroy();
|
|
addSubGCell (subs.first);
|
|
addSubGCell (subs.second);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
pair <GCell*, GCell*> GCell::vSplitMe (DbU::Unit& coord)
|
|
// ************************************************
|
|
{
|
|
Box b1 = Box
|
|
( getXMin()
|
|
, getYMin()
|
|
, coord
|
|
, getYMax()
|
|
);
|
|
Box b2 = Box
|
|
( coord //+ getUnit (5)
|
|
, getYMin()
|
|
, getXMax()
|
|
, getYMax()
|
|
);
|
|
|
|
GCell* rb1 = new GCell (_nimbus, _step, b1, _container);
|
|
GCell* rb2 = new GCell (_nimbus, _step, b2, _container);
|
|
|
|
assert ( rb1 && rb2 );
|
|
|
|
return pair<GCell*, GCell*> (rb1, rb2);
|
|
}
|
|
|
|
pair <GCell*, GCell*> GCell::hSplitMe (DbU::Unit& coord)
|
|
// ************************************************
|
|
{
|
|
Box b1 = Box
|
|
( getXMin()
|
|
, getYMin()
|
|
, getXMax()
|
|
, coord
|
|
);
|
|
Box b2 = Box
|
|
( getXMin()
|
|
, coord
|
|
, getXMax()
|
|
, getYMax()
|
|
);
|
|
|
|
GCell* rb1 = new GCell (_nimbus, _step, b1, _container);
|
|
GCell* rb2 = new GCell (_nimbus, _step, b2, _container);
|
|
|
|
assert ( rb1 && rb2 );
|
|
|
|
return pair<GCell*, GCell*> (rb1, rb2);
|
|
}
|
|
|
|
|
|
void GCell::addSubGCell (GCell* gcell)
|
|
// ***********************************
|
|
{
|
|
_subGCells._insert (gcell);
|
|
addToPavement (gcell);
|
|
|
|
return;
|
|
}
|
|
|
|
void GCell::addInnerFence (Fence* fence)
|
|
//* ************************************
|
|
{
|
|
if (
|
|
fence->getGCell1()->getContainer()
|
|
==
|
|
fence->getGCell2()->getContainer()
|
|
)
|
|
{
|
|
_subFences._insert (fence);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
bool GCell::isAStrictSubGCellOf (GCell* gcell) const
|
|
// *************************************************
|
|
{
|
|
if ( (gcell == this) || (gcell == NULL)) return false;
|
|
if ( ! getContainer() ) return false;
|
|
return getContainer()->isASubGCellOf(gcell);
|
|
}
|
|
|
|
bool GCell::isASubGCellOf (GCell* gcell) const
|
|
// *******************************************
|
|
{
|
|
if (gcell == this) return true;
|
|
GCell* container = getContainer();
|
|
if (!container) return false;
|
|
return container->isASubGCellOf (gcell);
|
|
}
|
|
|
|
void GCell::setAsPlacementLeaf()
|
|
// *****************************
|
|
{
|
|
recFlushSubPlacementLeaves (this);
|
|
_nimbus->setPlacementLeaf(this);
|
|
_isAPlacementLeaf = true;
|
|
GCell* nb = getContainer();
|
|
while (nb)
|
|
{
|
|
_nimbus->_removePlacementLeaf(nb);
|
|
nb->_setNotPlacementLeaf();
|
|
nb = nb->getContainer();
|
|
}
|
|
#if 0
|
|
if (getContainer())
|
|
getContainer()->_setNotPlacementLeaf();
|
|
#endif
|
|
for_each_fence(fence, getSurroundingFences())
|
|
{
|
|
fence->setVisible();
|
|
if (fence->getParentFence())
|
|
fence->getParentFence()->setInvisible();
|
|
end_for;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void GCell::recFlushSubPlacementLeaves(GCell* gcell)
|
|
// *************************************************
|
|
{
|
|
for_each_gcell(nb, gcell->getSubGCells())
|
|
{
|
|
nb->_setNotPlacementLeaf();
|
|
_nimbus->_removePlacementLeaf(nb);
|
|
recFlushSubPlacementLeaves(nb);
|
|
end_for;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void GCell::setSubGCellsAsPlacementLeaves()
|
|
// ****************************************
|
|
{
|
|
for_each_gcell(gcell, getSubGCells())
|
|
{
|
|
gcell->setAsPlacementLeaf();
|
|
end_for;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void GCell::setAsRoutingLeaf()
|
|
// ***************************
|
|
{
|
|
recFlushSubRoutingLeaves (this);
|
|
_nimbus->setRoutingLeaf(this);
|
|
_isARoutingLeaf = true;
|
|
GCell* nb = getContainer();
|
|
while (nb)
|
|
{
|
|
_nimbus->_removeRoutingLeaf(nb);
|
|
nb->_setNotRoutingLeaf();
|
|
nb = nb->getContainer();
|
|
}
|
|
return;
|
|
}
|
|
|
|
void GCell::recFlushSubRoutingLeaves(GCell* gcell)
|
|
// **********************************************
|
|
{
|
|
for_each_gcell(nb, gcell->getSubGCells())
|
|
{
|
|
nb->_setNotRoutingLeaf();
|
|
_nimbus->_removeRoutingLeaf(nb);
|
|
recFlushSubRoutingLeaves(nb);
|
|
end_for;
|
|
}
|
|
return;
|
|
}
|
|
|
|
double GCell::testMargin()
|
|
//* **********************
|
|
{
|
|
DbU::Unit sliceHeight = _nimbus->getConfiguration()->getSliceHeight();
|
|
if ( isEmpty() || _box.isPonctual() || _box.isFlat() )
|
|
throw Error ( "Very very strange GCell" );
|
|
if ( getHeight() % sliceHeight )
|
|
throw Error("GCell Height must be a multiple of Slice Height");
|
|
unsigned nRows = getHeight() / sliceHeight;
|
|
DbU::Unit areaTotalWidth = getWidth() * nRows;
|
|
DbU::Unit instanceWidthSum = 0;
|
|
for_each_instance ( instance, _nimbus->getCell()->getInstancesUnder ( this->_box ) ) {
|
|
instanceWidthSum += instance->getMasterCell()->getAbutmentBox().getWidth();
|
|
end_for;
|
|
}
|
|
double margin = 1.0 - DbU::getLambda(instanceWidthSum) / DbU::getLambda(areaTotalWidth);
|
|
return margin;
|
|
}
|
|
|
|
void GCell::setSubGCellsAsRoutingLeaves()
|
|
// **************************************
|
|
{
|
|
for_each_gcell(gcell, getSubGCells())
|
|
{
|
|
gcell->setAsRoutingLeaf();
|
|
end_for;
|
|
}
|
|
return;
|
|
}
|
|
|
|
GCell* GCell::getRoutingLeaf()
|
|
// ***************************
|
|
{
|
|
if (isARoutingLeaf()) return this;
|
|
if (getContainer()) return getContainer()->getRoutingLeaf();
|
|
return NULL;
|
|
}
|
|
|
|
GCell* GCell::getPlacementLeaf()
|
|
// *****************************
|
|
{
|
|
if (isAPlacementLeaf()) return this;
|
|
if (getContainer()) return getContainer()->getPlacementLeaf();
|
|
return NULL;
|
|
}
|
|
|
|
void GCell::removeSubGCell (GCell* gcell)
|
|
// **************************************
|
|
{
|
|
_subGCells._remove (gcell);
|
|
removeFromPavement (gcell);
|
|
|
|
return;
|
|
}
|
|
|
|
// Gestion du pavage
|
|
|
|
void GCell::addToPavement (GCell* gcell) {
|
|
|
|
DbU::Unit X = gcell->getXCenter();
|
|
DbU::Unit Y = gcell->getYCenter();
|
|
|
|
if (_pavement.find(X) == _pavement.end()) {
|
|
_pavement[X] = new RBMap;
|
|
}
|
|
|
|
(*(_pavement[X]))[Y] = gcell;
|
|
|
|
return;
|
|
}
|
|
|
|
void GCell::removeFromPavement (GCell* gcell) {
|
|
|
|
DbU::Unit X = gcell->getXCenter();
|
|
DbU::Unit Y = gcell->getYCenter();
|
|
|
|
RBMap* col = (_pavement[X]);
|
|
assert (col);
|
|
|
|
RBMap::iterator rbrm = col->find(Y);
|
|
assert (rbrm != col->end());
|
|
|
|
col->erase (rbrm);
|
|
|
|
if (col->empty())
|
|
_pavement.erase (_pavement.find(X));
|
|
|
|
return;
|
|
}
|
|
|
|
void GCell::dumpPavement () const
|
|
// ********************************
|
|
{
|
|
for (
|
|
RBPavement::const_iterator rbpit = _pavement.begin() ;
|
|
rbpit != _pavement.end() ;
|
|
rbpit++
|
|
)
|
|
{
|
|
cout << " - Line " << (*rbpit).first << " :";
|
|
|
|
for (
|
|
RBMap::iterator rbmit = ((*rbpit).second)->begin() ;
|
|
rbmit != ((*rbpit).second)->end() ;
|
|
rbmit++
|
|
)
|
|
{
|
|
cout << " (" << (*rbmit).first << ", " << (*rbmit).second << ")";
|
|
}
|
|
|
|
cout << endl;
|
|
}
|
|
|
|
return;
|
|
} // dumpPavement
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// a droite
|
|
//
|
|
GCell* GCell::_computeSubRightOf (const GCell* gcell) const
|
|
{
|
|
// "X + 1"
|
|
assert (gcell->getContainer() == this);
|
|
|
|
DbU::Unit X = gcell->getXCenter();
|
|
DbU::Unit Y = gcell->getYCenter();
|
|
|
|
RBPavement::const_iterator col = _pavement.find(X);
|
|
assert (col != _pavement.end());
|
|
|
|
col++;
|
|
|
|
if (col == _pavement.end())
|
|
return NULL;
|
|
|
|
RBMap::const_iterator rbit = ((*col).second)->find(Y);
|
|
assert (rbit != ((*col).second)->end());
|
|
|
|
return (*rbit).second;
|
|
}
|
|
|
|
GCell* GCell::getSubRightOf (GCell* gcell) const
|
|
{
|
|
// "X + 1"
|
|
assert (gcell->getContainer() == this);
|
|
|
|
if (gcell->getRightFence())
|
|
return (gcell->getRightFence()->getRightGCell());
|
|
|
|
GCell* nb = _computeSubRightOf (gcell);
|
|
#if 0
|
|
if (gcell) {
|
|
VFence* vfence = VFence::create (gcell, gcell);
|
|
assert (vfence);
|
|
gcell->setRightFence(vfence);
|
|
gcell->setLeftFence(vfence);
|
|
}
|
|
#endif
|
|
|
|
return nb;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// a gauche
|
|
//
|
|
GCell* GCell::_computeSubLeftOf (const GCell* gcell) const
|
|
{
|
|
// "X - 1"
|
|
|
|
assert (gcell->getContainer() == this);
|
|
|
|
DbU::Unit X = gcell->getXCenter();
|
|
DbU::Unit Y = gcell->getYCenter();
|
|
|
|
RBPavement::const_iterator col = _pavement.find(X);
|
|
assert (col != _pavement.end());
|
|
|
|
if (col == _pavement.begin())
|
|
return NULL;
|
|
|
|
col--;
|
|
|
|
RBMap::const_iterator rbit = ((*col).second)->find(Y);
|
|
assert (rbit != ((*col).second)->end());
|
|
|
|
return (*rbit).second;
|
|
}
|
|
|
|
GCell* GCell::getSubLeftOf (GCell* gcell) const
|
|
{
|
|
// "X - 1"
|
|
|
|
assert (gcell->getContainer() == this);
|
|
|
|
if (gcell->getLeftFence())
|
|
return (gcell->getLeftFence()->getLeftGCell());
|
|
|
|
GCell* nb = _computeSubLeftOf (gcell);
|
|
#if 0
|
|
if (gcell) {
|
|
VFence* vfence = new VFence (gcell, gcell);
|
|
assert (vfence);
|
|
gcell->setLeftFence(vfence);
|
|
gcell->setRightFence(vfence);
|
|
}
|
|
#endif
|
|
|
|
return nb;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// en bas
|
|
//
|
|
GCell* GCell::_computeSubDownOf (const GCell* gcell) const
|
|
{
|
|
// "Y - 1"
|
|
|
|
assert (gcell->getContainer() == this);
|
|
|
|
DbU::Unit X = gcell->getXCenter();
|
|
DbU::Unit Y = gcell->getYCenter();
|
|
|
|
RBPavement::const_iterator col = _pavement.find(X);
|
|
assert (col != _pavement.end());
|
|
|
|
RBMap::const_iterator rbit = ((*col).second)->find(Y);
|
|
assert (rbit != ((*col).second)->end());
|
|
|
|
if (rbit == ((*col).second)->begin())
|
|
return NULL;
|
|
|
|
rbit--;
|
|
|
|
return (*rbit).second;
|
|
}
|
|
|
|
GCell* GCell::getSubDownOf (GCell* gcell) const
|
|
{
|
|
// "Y - 1"
|
|
|
|
assert (gcell->getContainer() == this);
|
|
|
|
if (gcell->getDownFence())
|
|
return (gcell->getDownFence()->getDownGCell());
|
|
|
|
GCell* nb = _computeSubDownOf (gcell);
|
|
#if 0
|
|
if (gcell) {
|
|
HFence* hfence = new HFence (gcell, gcell);
|
|
assert (hfence);
|
|
gcell->setDownFence(hfence);
|
|
gcell->setUpFence(hfence);
|
|
}
|
|
#endif
|
|
|
|
return nb;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// en haut
|
|
//
|
|
GCell* GCell::_computeSubUpOf (const GCell* gcell) const
|
|
{
|
|
// "Y + 1"
|
|
|
|
assert (gcell->getContainer() == this);
|
|
|
|
DbU::Unit X = gcell->getXCenter();
|
|
DbU::Unit Y = gcell->getYCenter();
|
|
|
|
RBPavement::const_iterator col = _pavement.find(X);
|
|
assert (col != _pavement.end());
|
|
|
|
RBMap::const_iterator rbit = ((*col).second)->find(Y);
|
|
assert (rbit != ((*col).second)->end());
|
|
|
|
rbit++;
|
|
|
|
if (rbit == ((*col).second)->end())
|
|
return NULL;
|
|
|
|
return (*rbit).second;
|
|
}
|
|
GCell* GCell::getSubUpOf (GCell* gcell) const
|
|
{
|
|
// "Y + 1"
|
|
|
|
assert (gcell->getContainer() == this);
|
|
|
|
if (gcell->getUpFence())
|
|
return (gcell->getUpFence()->getUpGCell());
|
|
|
|
GCell* nb = _computeSubUpOf (gcell);
|
|
#if 0
|
|
if (gcell) {
|
|
HFence* hfence = new HFence (gcell, gcell);
|
|
assert (hfence);
|
|
gcell->setUpFence(hfence);
|
|
gcell->setDownFence(hfence);
|
|
}
|
|
#endif
|
|
|
|
return nb;
|
|
}
|
|
|
|
GCell* GCell::getSubUpperLeft () const
|
|
{
|
|
if (!hasSubGCells())
|
|
return NULL;
|
|
|
|
RBPavement::const_iterator col = _pavement.begin();
|
|
assert (col != _pavement.end());
|
|
|
|
RBMap::const_reverse_iterator rbit = ((*col).second)->rbegin();
|
|
#ifndef NDEBUG
|
|
RBMap::const_reverse_iterator rbend = ((*col).second)->rend();
|
|
#endif
|
|
assert (rbit != rbend);
|
|
|
|
return (*rbit).second;
|
|
}
|
|
|
|
GCell* GCell::getSubUpperRight () const
|
|
{
|
|
if (!hasSubGCells())
|
|
return NULL;
|
|
|
|
RBPavement::const_reverse_iterator col = _pavement.rbegin();
|
|
assert (col != _pavement.rend());
|
|
|
|
RBMap::const_reverse_iterator rbit = ((*col).second)->rbegin();
|
|
#ifndef NDEBUG
|
|
RBMap::const_reverse_iterator rbend = ((*col).second)->rend();
|
|
#endif
|
|
assert (rbit != rbend);
|
|
|
|
return (*rbit).second;
|
|
}
|
|
|
|
GCell* GCell::getSubBottomRight () const
|
|
{
|
|
if (!hasSubGCells())
|
|
return NULL;
|
|
|
|
RBPavement::const_reverse_iterator col = _pavement.rbegin();
|
|
assert (col != _pavement.rend());
|
|
|
|
RBMap::const_iterator rbit = ((*col).second)->begin();
|
|
assert (rbit != ((*col).second)->end());
|
|
|
|
return (*rbit).second;
|
|
}
|
|
|
|
GCell* GCell::getSubBottomLeft () const
|
|
{
|
|
if (!hasSubGCells())
|
|
return NULL;
|
|
|
|
RBPavement::const_iterator col = _pavement.begin();
|
|
assert (col != _pavement.end());
|
|
|
|
RBMap::const_iterator rbit = ((*col).second)->begin();
|
|
assert (rbit != ((*col).second)->end());
|
|
|
|
return (*rbit).second;
|
|
}
|
|
|
|
/*
|
|
* ********************************************************************
|
|
* Up Down Left Right of Me !!!!
|
|
* ********************************************************************
|
|
*
|
|
* ********************************************************************
|
|
*/
|
|
|
|
/*
|
|
* ********************************************************************
|
|
*
|
|
* Voisin de gauche
|
|
*/
|
|
|
|
/*
|
|
* montee/descente recursive
|
|
*/
|
|
GCell* GCell::_recGetLeftOfMe () const
|
|
{
|
|
GCell* gcell = NULL;
|
|
|
|
if (_container) {
|
|
// essai de raccource par les Fence
|
|
gcell = _container->getLeftOfMe();
|
|
|
|
if (!gcell) {
|
|
// essai par calcul
|
|
gcell = _container->computeLeftOfMe();
|
|
}
|
|
}
|
|
|
|
if (!gcell) return NULL;
|
|
|
|
// on verifie au'on tient la boite a droite de notre container
|
|
assert (gcell->getStep() == _container->getStep());
|
|
GCell* resnb = gcell->getSubUpperRight();
|
|
DbU::Unit Y = getYCenter();
|
|
|
|
while ( !
|
|
( resnb->horizontalIsCrossed(Y) )
|
|
)
|
|
{
|
|
resnb = gcell->getSubDownOf(resnb);
|
|
if (!resnb) break;
|
|
}
|
|
|
|
return resnb;
|
|
}
|
|
/*
|
|
* ********************************************************************
|
|
*/
|
|
|
|
/*
|
|
* ********************************************************************
|
|
*
|
|
* Voisin de droite
|
|
*/
|
|
|
|
/*
|
|
* rec -> remonter jusqu'a trouver une droite sinon renvoi NULL
|
|
*/
|
|
GCell* GCell::_recGetRightOfMe () const
|
|
{
|
|
GCell* gcell = NULL;
|
|
|
|
if (_container) {
|
|
// essai de raccource par les Fence
|
|
gcell = _container->getRightOfMe();
|
|
|
|
if (!gcell) {
|
|
// essai par calcul
|
|
gcell = _container->computeRightOfMe();
|
|
}
|
|
}
|
|
if (!gcell) return NULL;
|
|
|
|
// on verifie au'on tient la boite a droite de notre container
|
|
assert (gcell->getStep() == _container->getStep());
|
|
GCell* resnb = gcell->getSubUpperLeft();
|
|
DbU::Unit Y = getYCenter();
|
|
|
|
while ( !
|
|
( resnb->horizontalIsCrossed(Y) )
|
|
)
|
|
{
|
|
resnb = gcell->getSubDownOf(resnb);
|
|
if (!resnb) break;
|
|
}
|
|
|
|
return resnb;
|
|
}
|
|
/*
|
|
* ********************************************************************
|
|
*/
|
|
|
|
/*
|
|
* ********************************************************************
|
|
*
|
|
* Voisin du haut
|
|
*/
|
|
|
|
/*
|
|
* rec ->
|
|
*/
|
|
GCell* GCell::_recGetUpOfMe () const
|
|
{
|
|
GCell* gcell = NULL;
|
|
|
|
if (_container) {
|
|
// essai de raccource par les Fence
|
|
gcell = _container->getUpOfMe();
|
|
|
|
if (!gcell) {
|
|
// essai par calcul
|
|
gcell = _container->computeUpOfMe();
|
|
}
|
|
}
|
|
if (!gcell) return NULL;
|
|
|
|
// on verifie au'on tient la boite a droite de notre container
|
|
assert (gcell->getStep() == _container->getStep());
|
|
GCell* resnb = gcell->getSubBottomLeft();
|
|
DbU::Unit X = getXCenter();
|
|
|
|
while ( !
|
|
( resnb->verticalIsCrossed(X) )
|
|
)
|
|
{
|
|
resnb = gcell->getSubRightOf(resnb);
|
|
if (!resnb) break;
|
|
}
|
|
|
|
return resnb;
|
|
}
|
|
/*
|
|
* ********************************************************************
|
|
*/
|
|
|
|
/*
|
|
* ********************************************************************
|
|
*
|
|
* Voisin du bas
|
|
*/
|
|
|
|
/*
|
|
* rec ->
|
|
*/
|
|
GCell* GCell::_recGetDownOfMe () const
|
|
{
|
|
GCell* gcell = NULL;
|
|
|
|
if (_container) {
|
|
// essai de raccource par les Fence
|
|
gcell = _container->getDownOfMe();
|
|
|
|
if (!gcell) {
|
|
// essai par calcul
|
|
gcell = _container->computeDownOfMe();
|
|
}
|
|
}
|
|
if (!gcell) return NULL;
|
|
|
|
// on verifie au'on tient la boite a droite de notre container
|
|
assert (gcell->getStep() == _container->getStep());
|
|
GCell* resnb = gcell->getSubUpperLeft();
|
|
DbU::Unit X = getXCenter();
|
|
|
|
while ( !
|
|
( resnb->verticalIsCrossed(X) )
|
|
)
|
|
{
|
|
resnb = gcell->getSubRightOf(resnb);
|
|
if (!resnb) break;
|
|
}
|
|
|
|
return resnb;
|
|
}
|
|
/*
|
|
* ********************************************************************
|
|
*/
|
|
|
|
/*
|
|
* ********************************************************************
|
|
* haut bas droite gauche par calcul
|
|
*/
|
|
GCell* GCell::computeUpOfMe () const
|
|
{
|
|
if (!_container) return NULL;
|
|
|
|
GCell* gcell = _container->_computeSubUpOf (this);
|
|
if (!gcell) gcell = _recGetUpOfMe();
|
|
|
|
return gcell;
|
|
}
|
|
|
|
GCell* GCell::computeDownOfMe () const
|
|
{
|
|
if (!_container) return NULL;
|
|
|
|
GCell* gcell = _container->_computeSubDownOf (this);
|
|
if (!gcell) gcell = _recGetDownOfMe();
|
|
|
|
return gcell;
|
|
}
|
|
|
|
GCell* GCell::computeRightOfMe () const
|
|
{
|
|
if (!_container) return NULL;
|
|
|
|
GCell* gcell = _container->_computeSubRightOf (this);
|
|
if (!gcell) gcell = _recGetRightOfMe();
|
|
|
|
return gcell;
|
|
}
|
|
|
|
GCell* GCell::computeLeftOfMe () const
|
|
{
|
|
if (!_container) return NULL;
|
|
|
|
GCell* gcell = _container->_computeSubLeftOf (this);
|
|
if (!gcell) gcell = _recGetLeftOfMe();
|
|
|
|
return gcell;
|
|
}
|
|
|
|
/*
|
|
* ********************************************************************
|
|
* haut bas droite gauche par les frontières
|
|
*/
|
|
GCell* GCell::getRightOfMe () const
|
|
{
|
|
if (!_rightfence) return NULL;
|
|
return _rightfence->getRightGCell();
|
|
}
|
|
GCell* GCell::getLeftOfMe () const
|
|
{
|
|
if (!_leftfence) return NULL;
|
|
return _leftfence->getLeftGCell();
|
|
}
|
|
GCell* GCell::getUpOfMe () const
|
|
{
|
|
if (!_upfence) return NULL;
|
|
return _upfence->getUpGCell();
|
|
}
|
|
GCell* GCell::getDownOfMe () const
|
|
{
|
|
if (!_downfence) return NULL;
|
|
return _downfence->getDownGCell();
|
|
}
|
|
|
|
/*
|
|
* ********************************************************************
|
|
* traversée de boite
|
|
*
|
|
*/
|
|
Fence* GCell::getOppositeFence (const Fence* fence) const
|
|
{
|
|
if (fence == _upfence)
|
|
return _downfence;
|
|
else if (fence == _downfence)
|
|
return _upfence;
|
|
else if (fence == _leftfence)
|
|
return _rightfence;
|
|
else if (fence == _rightfence)
|
|
return _leftfence;
|
|
else
|
|
throw Error ("getOppositeFence : not a fence of mine");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* RBList implementation
|
|
*
|
|
*/
|
|
GCell::GCellSet::GCellSet()
|
|
// ************************
|
|
: Inherit()
|
|
{
|
|
}
|
|
|
|
unsigned GCell::GCellSet::_getHashValue(GCell* gcell) const
|
|
{
|
|
return ( (unsigned int)( (unsigned long)gcell ) ) / 2;
|
|
}
|
|
|
|
GCell* GCell::GCellSet::_getNextElement(GCell* gcell) const
|
|
{
|
|
return gcell->_getNextOfGCellGCellSet();
|
|
}
|
|
|
|
void GCell::GCellSet::_setNextElement(GCell* gcell, GCell* nextGCell) const
|
|
{
|
|
gcell->_setNextOfGCellGCellSet(nextGCell);
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* SubFenceSet implementation
|
|
*
|
|
*/
|
|
GCell::SubFenceSet::SubFenceSet()
|
|
// ******************************
|
|
: Inherit()
|
|
{
|
|
}
|
|
|
|
unsigned GCell::SubFenceSet::_getHashValue(Fence* fence) const
|
|
{
|
|
return ( (unsigned int)( (unsigned long)fence ) ) / 2;
|
|
}
|
|
|
|
Fence* GCell::SubFenceSet::_getNextElement(Fence* fence) const
|
|
{
|
|
return fence->_getNextOfGCellSubFenceSet();
|
|
}
|
|
|
|
void GCell::SubFenceSet::_setNextElement(Fence* fence, Fence* nextFence) const
|
|
{
|
|
fence->_setNextOfGCellSubFenceSet(nextFence);
|
|
return;
|
|
}
|
|
|
|
|
|
string GCell::_getString() const
|
|
// ******************************
|
|
{
|
|
if (isEmpty())
|
|
return "<" + _TName("GCell") + " empty>";
|
|
else
|
|
return
|
|
"<" + _TName("GCell") + " " + getString(_step) + " " +
|
|
DbU::getValueString(getXMin()) + " " + DbU::getValueString(getYMin()) + " " +
|
|
DbU::getValueString(getXMax()) + " " + DbU::getValueString(getYMax()) +
|
|
">";
|
|
}
|
|
|
|
Record* GCell::_getRecord() const
|
|
// ************************
|
|
{
|
|
Record* record = Inherit::_getRecord();
|
|
|
|
if (!record)
|
|
record = new Record(getString(this));
|
|
|
|
record->add(getSlot("Container", _container));
|
|
record->add(getSlot("UpFence", _upfence));
|
|
record->add(getSlot("DownFence", _downfence));
|
|
record->add(getSlot("LeftFence", _leftfence));
|
|
record->add(getSlot("RightFence", _rightfence));
|
|
record->add(getSlot("Step", _step));
|
|
record->add(getSlot("isAplacementLeaf", _isAPlacementLeaf));
|
|
record->add(getSlot("isARoutingLeaf", _isARoutingLeaf));
|
|
//record->add(getSlot("Fences", &_surroundingFences));
|
|
record->add(getSlot("SubGCells", &_subGCells));
|
|
|
|
return record;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* ********************************************************************
|
|
* Collection des fences
|
|
*/
|
|
Fences GCell::getSurroundingFences () const
|
|
{
|
|
return GCell_Fences(this);
|
|
}
|
|
|
|
|
|
/*
|
|
* ********************************************************************
|
|
*
|
|
* GCell_Fences implementation
|
|
*/
|
|
|
|
GCell_Fences::GCell_Fences(const GCell* gcell)
|
|
// *******************************************
|
|
: Inherit()
|
|
, _nb(gcell)
|
|
, _fence(NULL)
|
|
{
|
|
if (_nb->getRightFence()) {
|
|
_fence = _nb->getRightFence();
|
|
return;
|
|
}
|
|
if (_nb->getLeftFence()) {
|
|
_fence = _nb->getLeftFence();
|
|
return;
|
|
}
|
|
if (_nb->getUpFence()) {
|
|
_fence = _nb->getUpFence();
|
|
return;
|
|
}
|
|
if (_nb->getDownFence()) {
|
|
_fence = _nb->getDownFence();
|
|
return;
|
|
}
|
|
_fence = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
GCell_Fences::GCell_Fences(const GCell_Fences& fences)
|
|
// ***************************************************
|
|
: Inherit()
|
|
, _nb(fences._nb)
|
|
, _fence(fences._fence)
|
|
{
|
|
}
|
|
|
|
GCell_Fences& GCell_Fences::operator=(const GCell_Fences& fences)
|
|
// **************************************************************
|
|
{
|
|
_nb = fences._nb;
|
|
_fence = fences._fence;
|
|
return *this;
|
|
}
|
|
|
|
Collection<Fence*>* GCell_Fences::getClone() const
|
|
// ***********************************************
|
|
{
|
|
return new GCell_Fences(*this);
|
|
}
|
|
|
|
Locator<Fence*>* GCell_Fences::getLocator() const
|
|
// **********************************************
|
|
{
|
|
return new Locator(_nb, _fence);
|
|
}
|
|
|
|
string GCell_Fences::_getString() const
|
|
// ************************************
|
|
{
|
|
string s = "<" + _TName("GCell::Fences");
|
|
if (_nb) s += " " + getString(_nb);
|
|
s += ">";
|
|
return s;
|
|
}
|
|
|
|
/*
|
|
* ********************************************************************
|
|
* GCell_Fences::Locator implementation
|
|
*/
|
|
GCell_Fences::Locator::Locator(const GCell* gcell, Fence* fence)
|
|
// *************************************************************
|
|
: Inherit(),
|
|
_nb(gcell),
|
|
_fence(fence)
|
|
{
|
|
}
|
|
|
|
GCell_Fences::Locator::Locator(const Locator& locator)
|
|
// ***************************************************
|
|
: Inherit(),
|
|
_nb(locator._nb),
|
|
_fence(locator._fence)
|
|
{
|
|
}
|
|
|
|
GCell_Fences::Locator& GCell_Fences::Locator::operator=(const Locator& locator)
|
|
// ****************************************************************************
|
|
{
|
|
_nb = locator._nb;
|
|
_fence = locator._fence;
|
|
return *this;
|
|
}
|
|
|
|
Fence* GCell_Fences::Locator::getElement() const
|
|
// *********************************************
|
|
{
|
|
return _fence;
|
|
}
|
|
|
|
Locator<Fence*>* GCell_Fences::Locator::getClone() const
|
|
// *****************************************************
|
|
{
|
|
return new Locator(*this);
|
|
}
|
|
|
|
bool GCell_Fences::Locator::isValid() const
|
|
// ****************************************
|
|
{
|
|
return (_fence != NULL);
|
|
}
|
|
|
|
void GCell_Fences::Locator::progress()
|
|
// ***********************************
|
|
{
|
|
bool found = false;
|
|
|
|
if ( _nb->getRightFence() ) {
|
|
|
|
if (_fence == _nb->getRightFence())
|
|
found = true;
|
|
|
|
}
|
|
|
|
if ( _nb->getLeftFence() ) {
|
|
|
|
if (found) {
|
|
_fence = _nb->getLeftFence();
|
|
return;
|
|
}
|
|
|
|
if (_fence == _nb->getLeftFence())
|
|
found = true;
|
|
}
|
|
|
|
if ( _nb->getUpFence() ) {
|
|
|
|
if (found) {
|
|
_fence = _nb->getUpFence();
|
|
return;
|
|
}
|
|
|
|
if (_fence == _nb->getUpFence())
|
|
found = true;
|
|
}
|
|
|
|
if ( _nb->getDownFence() ) {
|
|
|
|
if (found) {
|
|
_fence = _nb->getDownFence();
|
|
return;
|
|
}
|
|
|
|
if (_fence == _nb->getDownFence())
|
|
found = true;
|
|
}
|
|
|
|
if (found) {
|
|
_fence = NULL;
|
|
return;
|
|
}
|
|
|
|
throw Error ("Fence collection strangeness");
|
|
|
|
return;
|
|
}
|
|
|
|
string GCell_Fences::Locator::_getString() const
|
|
// *********************************************
|
|
{
|
|
string s = "<" + _TName("GCells::Fences::Locator");
|
|
if (_nb) s += " " + getString(_nb);
|
|
s += ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Nimbus
|