coriolis/nimbus/src/GCell.cpp

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