// 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 #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 { public: typedef Collection Inherit; public: class Locator : public Hurricane::Locator { public: typedef Hurricane::Locator 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* 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* getClone() const; public: virtual Hurricane::Locator* 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::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 (rb1, rb2); } pair 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 (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* GCell_Fences::getClone() const // *********************************************** { return new GCell_Fences(*this); } Locator* 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* 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