diff --git a/nimbus/cmake_modules/FindNIMBUS.cmake b/nimbus/cmake_modules/FindNIMBUS.cmake index 39defb5c..dfa1e24c 100644 --- a/nimbus/cmake_modules/FindNIMBUS.cmake +++ b/nimbus/cmake_modules/FindNIMBUS.cmake @@ -15,7 +15,7 @@ IF(UNIX) # # Look for an installation. # - FIND_PATH(NIMBUS_INCLUDE_PATH NAMES nimbus/Nimbus.h PATHS + FIND_PATH(NIMBUS_INCLUDE_PATH NAMES nimbus/NimbusEngine.h PATHS # Look in other places. ${CORIOLIS_DIR_SEARCH} PATH_SUFFIXES include/coriolis2 diff --git a/nimbus/src/CMakeLists.txt b/nimbus/src/CMakeLists.txt index c1d6d798..4740acbb 100644 --- a/nimbus/src/CMakeLists.txt +++ b/nimbus/src/CMakeLists.txt @@ -1,11 +1,12 @@ include ( ${QT_USE_FILE} ) - include_directories ( ${HURRICANE_INCLUDE_DIR} - ${NIMBUS_SOURCE_DIR}/src + include_directories ( ${NIMBUS_SOURCE_DIR}/src + ${HURRICANE_INCLUDE_DIR} ${CORIOLIS_INCLUDE_DIR} ) - set ( includes nimbus/SplitterContact.h nimbus/SplitterContacts.h + set ( includes nimbus/Configuration.h + nimbus/SplitterContact.h nimbus/SplitterContacts.h nimbus/Splitter.h nimbus/Splitters.h nimbus/Fence.h nimbus/Fences.h nimbus/HFence.h @@ -15,10 +16,11 @@ nimbus/StepProperty.h nimbus/GCell.h nimbus/GCells.h nimbus/Grid.h - nimbus/Nimbus.h + nimbus/NimbusEngine.h nimbus/RoutTools.h ) - set ( cpps SplitterContact.cpp + set ( cpps Configuration.cpp + SplitterContact.cpp Splitter.cpp Fence.cpp FenceProperty.cpp @@ -28,7 +30,7 @@ GCell.cpp Grid.cpp StepProperty.cpp - Nimbus.cpp + NimbusEngine.cpp RoutTools.cpp ) diff --git a/nimbus/src/Fence.cpp b/nimbus/src/Fence.cpp new file mode 100644 index 00000000..3d569bfe --- /dev/null +++ b/nimbus/src/Fence.cpp @@ -0,0 +1,760 @@ + +// 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 "nimbus/NimbusEngine.h" + + +namespace Nimbus { + + + using namespace std; + + const Name Fence::_extensionName = "Nimbus::Grid"; + + +/* + * ******************************************************************** + * Fence_Splitters declaration + * ******************************************************************** + */ +class Fence_Splitters : public Collection { + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + + public: typedef Hurricane::Locator Inherit; + + private: const SplitterSet* _spset; + private: SplitterSet::iterator _spit; + + public: Locator(const SplitterSet* spset, SplitterSet::iterator spit); + public: Locator(const Locator& locator); + + public: Locator& operator=(const Locator& locator); + + public: virtual Splitter* getElement() const; + public: virtual Hurricane::Locator* getClone() const; + + public: virtual bool isValid() const; + public: virtual void progress(); + + public: virtual string _getString() const; + }; + + + private: const SplitterSet* _spset; + private: SplitterSet::iterator _spit; + + public: Fence_Splitters(const SplitterSet* spset); + public: Fence_Splitters(const Fence_Splitters& splitters); + + public: Fence_Splitters& operator=(const Fence_Splitters& splitters); + + public: virtual Collection* getClone() const; + public: virtual Hurricane::Locator* getLocator() const; + + public: virtual string _getString() const; +}; + + +/* + * ******************************************************************** + * Fence_GCells declaration + * ******************************************************************** + */ +class Fence_GCells : public Collection { + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + + public: typedef Hurricane::Locator Inherit; + + private: const Fence* _fence; + private: GCell* _gc; + + public: Locator(const Fence* fence, GCell* gcell = NULL); + public: Locator(const Locator& locator); + + public: Locator& operator=(const Locator& locator); + + public: virtual GCell* getElement() const; + public: virtual Hurricane::Locator* getClone() const; + + public: virtual bool isValid() const; + + public: virtual void progress(); + + public: virtual string _getString() const; + }; + + + private: const Fence* _fence; + private: GCell* _gc; + + public: Fence_GCells(const Fence* fence); + public: Fence_GCells(const Fence_GCells& gcelles); + + public: Fence_GCells& operator=(const Fence_GCells& gcelles); + + public: virtual Collection* getClone() const; + public: virtual Hurricane::Locator* getLocator() const; + + public: virtual string _getString() const; +}; + + +RoutingGauge* Fence::_routingGauge = NULL; + + +/* + * ******************************************************************** + * Fence implementation + * + */ + + +Fence::Fence ( Grid* grid, DbU::Unit size, unsigned capacity, unsigned occupancy, bool visible) + : Inherit (grid->getCell()) + , _splitters () + , _components () + , _occupancy (occupancy) + , _capacity (capacity) + , _frontLine (NULL) + , _nextOfFenceSubFenceSet(NULL) + , _nextOfGCellSubFenceSet(NULL) + , _nextOfGridFenceSet(NULL) + , _isARoutingFence(false) + , _visible(visible) + , _step (0) + , _size (size) + , _grid (grid) + , _subFences() +{ + return; +} + +Fence::~Fence () +{ + return; +} + +void Fence::_preDestroy() { + + //throw Error ("[ERROR] Fence deletion temporarily disabled (to be fixed...)"); + + Inherit::_preDestroy(); + + Fence* parentFence = getParentFence(); + if (parentFence) parentFence->removeSubFence(this); + + for ( + SplitterSet::iterator spit = _splitters.begin() ; + spit != _splitters.end() ; + spit++ + ) + { + (*spit)->onDeletedFence(); + } +#if 0 + // remove Fence property ? + for ( + ComponentSet::iterator cit = _components.begin() ; + cit != _components.end() ; + cit++ + ) + { + (*cit)->onDeletedFence(); + } +#endif + + return; +} + +void Fence::_postCreate () +{ + Inherit::_postCreate(); + + //getGCell1()->addSurroundingFence (this); + //getGCell2()->addSurroundingFence (this); + Fence* parentFence = getParentFence(); + if (parentFence) parentFence->addSubFence(this); + + computeCapacity(); + + return; +}; + +void Fence::setAsRoutingFence() +{ + if (_isARoutingFence) return; + _isARoutingFence = true; + + _grid->getNimbus()->addToRoutingFences(this); + + return; +} + +void Fence::destroy() +{ + _preDestroy(); + delete this; +} + +void Fence::computeCapacity() +{ + +#if 0 + unsigned pitch = static_cast(getValue (getCDataBase()->getPitch())); + unsigned nlayers = getGrid()->getNimbus()->getNumberOfRoutingLayers(); + + //Name alu1 ("alu1"); + double capa (0); + for_each_layergauge (routingLayerGauge, _routingGauge) + { + capa += routingLayerGauge->getTrackNumber(fence->getMin(), fence->getMax()); + end_for; + } + + + setCapacity(static_cast(capa/2)); + +#endif + return; +} + +void Fence::_moveTo (DbU::Unit target) +{ + for_each_fence (subfence, getSubFences()) + { + subfence->_moveTo (target); + end_for; + } + return; +} + +DbU::Unit Fence::getDistance() const { + + Point p1 = getGCell1()->getCenter(); + Point p2 = getGCell2()->getCenter(); + + return p1.manhattanDistance(p2); +} + +void Fence::attachSplitter (Splitter* splitter) +{ + _splitters.insert(splitter); + _occupancy ++; + + return; +} + +void Fence::detachSplitter (Splitter* splitter) +{ + SplitterSet::iterator spit = _splitters.find (splitter); + + if (spit != _splitters.end()) { + _splitters.erase (spit); + _occupancy --; + } else { + throw Error ("DetachSplitter: the splitter is not attached to this fence"); + } + + return; +} + +void Fence::attachComponent (Component* component) +{ + _components.insert(component); + _occupancy ++; + + return; +} + +void Fence::detachComponent (Component* component) +{ + ComponentSet::iterator cit = _components.find (component); + + if (cit != _components.end()) { + _components.erase (cit); + _occupancy --; + } else { + throw Error ("DetachComponent: the component is not attached to this fence"); + } + + return; +} + +string Fence::_getString() const { + return "<" + _TName ( "Fence" ) + + " " + getString ( getX() ) + + " " + getString ( getY() ) + ">"; +} + +Record* Fence::_getRecord() const { + Record* record = Inherit::_getRecord(); + + if (record) { + record->add(getSlot("Capacity", _capacity)); + record->add(getSlot("Occupancy", _occupancy)); + record->add(getSlot("Size", _size)); + record->add(getSlot("Step", _step)); + record->add(getSlot("Visible", _visible)); + record->add(getSlot("RoutingFence", _isARoutingFence)); + record->add(getSlot("X", getX())); + record->add(getSlot("Y", getY())); + } + + return record; +} + +// void Fence::_Draw(View* view, BasicLayer* basicLayer, const Box& updateArea, const Transformation& transformation) +// { +// if (!isVisible()) return; +// Point p1 = transformation.getPoint(getP1()); +// Point p2 = transformation.getPoint(getP2()); + +// DbU::Unit halfWidth; +// DbU::Unit pitch = getCDataBase()->getDefaultCGPitch(); + +// if (_capacity != 0) +// halfWidth = DbU::lambda( (((getValue(_size)/10) * ((double)_occupancy)) / ((double)_capacity))/2 ); +// else +// halfWidth = DbU::lambda( (((getValue(_size)/10) * ((double)_occupancy)) / 1 )/2 ); + +// if (p1.getX() == p2.getX()) +// { +// Point pp1 = Point (p1.getX() + halfWidth, p1.getY() + pitch); +// Point pp2 = Point (p2.getX() - halfWidth, p2.getY() - pitch); +// view->FillRectangle (pp1, pp2); + +// Point pp1f = Point (p1.getX() + DbU::lambda(getValue(_size)/20), p1.getY() + pitch); +// Point pp2f = Point (p2.getX() - DbU::lambda(getValue(_size)/20), p2.getY() - pitch); +// view->DrawRectangle (pp1f, pp2f); +// } +// else if (p1.getY() == p2.getY()) +// { +// Point pp1 = Point (p1.getX() + pitch, p1.getY() + halfWidth); +// Point pp2 = Point (p2.getX() - pitch, p2.getY() - halfWidth ); +// view->FillRectangle (pp1, pp2); + +// Point pp1f = Point (p1.getX() + pitch, p1.getY() + DbU::lambda(getValue(_size)/20)); +// Point pp2f = Point (p2.getX() - pitch, p2.getY() - DbU::lambda(getValue(_size)/20)); +// view->DrawRectangle (pp1f, pp2f); +// } +// else +// { +// view->DrawLine(p1, p2); +// } + +// return; +// } + +// void Fence::_Highlight(View* view, const Box& updateArea, const Transformation& transformation) +// { +// Point p1 = transformation.getPoint(getP1()); +// Point p2 = transformation.getPoint(getP2()); + +// view->DrawLine(p1, p2); + +// return; +// } + +Box Fence::getBoundingBox () const +{ + Box box; + + Point p1 = getP1(); + Point p2 = getP2(); + + if (p1.getX() == p2.getX()) + { + Point pp1f = Point (p1.getX() + (_size/20), p1.getY() + DbU::lambda(1)); + Point pp2f = Point (p2.getX() - (_size/20), p2.getY() - DbU::lambda(1)); + + box = Box(pp1f); + box.merge(pp2f); + } + else if (p1.getY() == p2.getY()) + { + Point pp1f = Point (p1.getX() + DbU::lambda(1), p1.getY() + (_size/20)); + Point pp2f = Point (p2.getX() - DbU::lambda(1), p2.getY() - (_size/20)); + + box = Box(pp1f); + box.merge(pp2f); + } + else + { + box = Box(p1); + box.merge(p2); + } + box.inflate(DbU::lambda(1), DbU::lambda(2)); + + return box; +} + +void Fence::setFrontLine(FrontLine* frontLine) +{ + if (getFrontLine() != frontLine) throw Error ("Fence is in another frontline already"); + _frontLine = frontLine; + return; +} + +FrontLine* Fence::getFrontLine() +{ + if (!_frontLine) + { + Fence* parentFence = getParentFence(); + if (parentFence) _frontLine = parentFence->getFrontLine(); + } + return _frontLine; +} + +Splitters Fence::getSplitters () const +{ + return Fence_Splitters(&_splitters); +} + +GCells Fence::getGCells () const +{ + return Fence_GCells(this); +} + +void Fence::addSubFence (Fence* fence) +{ + _subFences._insert(fence); + return; +} + +void Fence::removeSubFence (Fence* fence) +{ + _subFences._remove(fence); + return; +} + +GCell* Fence::getOppositeGCell (GCell* gcell) const { + + if (getGCell1() == gcell) { + return getGCell2(); + } else if (getGCell2() == gcell) { + return getGCell1(); + } + + throw Error ("[ERROR] fence: not a gcell of mine"); +} + +Fence* Fence::getParentFence() const { + + GCell* gc1 = getGCell1()->getContainer(); + GCell* gc2 = getGCell2()->getContainer(); + + if (gc1 == gc2) return NULL; + + return _grid->getFenceBetween(gc1,gc2); +} + +Splitter* Fence::getNetSplitter(Net* net) const +{ + for ( + SplitterSet::iterator spit = _splitters.begin() ; + spit != _splitters.end(); + spit++ + ) + { + if ( (*spit)->getNet() == net ) + return (*spit); + } + return NULL; +} + +Cell* Fence::getCell() const { + return _grid->getCell(); +} + +// bool Fence::_IsInterceptedBy(View* view, const Point& point, const DbU::Unit& aperture) const +// { +// if (!isVisible()) return false; + +// Box box(point); +// box.inflate(aperture); +// return getBoundingBox().intersect(box); +// } + + +/* + * ******************************************************************** + * Fence_Splitters implementation + * + */ + +Fence_Splitters::Fence_Splitters(const SplitterSet* spset) +// ************************************************************************************** +: Inherit() + , _spset(spset) +{ + assert(spset); + _spit = spset->begin(); +} + +Fence_Splitters::Fence_Splitters(const Fence_Splitters& splitters) +// ************************************************************************************ +: Inherit() + , _spset(splitters._spset) + , _spit(splitters._spit) +{ +} + +Fence_Splitters& Fence_Splitters::operator=(const Fence_Splitters& splitters) +// **************************************************************** +{ + _spset = splitters._spset; + _spit = splitters._spit; + return *this; +} + +Collection* Fence_Splitters::getClone() const +// *********************************************** +{ + return new Fence_Splitters(*this); +} + +Locator* Fence_Splitters::getLocator() const +// ********************************************** +{ + return new Locator(_spset, _spit); +} + +string Fence_Splitters::_getString() const +// ************************************* +{ + string s = "<" + _TName("Fence::Splitters"); + //if (_splitterIterator) s += " " + getString((*_splitterIterator)); + s += ">"; + return s; +} + +/* + * ******************************************************************** + * Fence_Splitters::Locator implementation + */ +Fence_Splitters::Locator::Locator(const SplitterSet* spset, SplitterSet::iterator spit) +// ************************************************************************************ +: Inherit(), + _spset(spset), + _spit(spit) +{ +} + +Fence_Splitters::Locator::Locator(const Locator& locator) +// **************************************************** +: Inherit(), + _spset(locator._spset), + _spit(locator._spit) +{ +} + +Fence_Splitters::Locator& Fence_Splitters::Locator::operator=(const Locator& locator) +// ****************************************************************************** +{ + _spset = locator._spset; + _spit = locator._spit; + return *this; +} + +Splitter* Fence_Splitters::Locator::getElement() const +// ************************************************** +{ + return (*_spit); +} + +Locator* Fence_Splitters::Locator::getClone() const +// ***************************************************************** +{ + return new Locator(*this); +} + +bool Fence_Splitters::Locator::isValid() const +// ************************************************** +{ + return (_spit != _spset->end()); +} + +void Fence_Splitters::Locator::progress() +// ********************************************* +{ + _spit++; + + return; +} + +string Fence_Splitters::Locator::_getString() const +// ******************************************************* +{ + string s = "<" + _TName("Fence::Splitters::Locator"); + if (_spit != _spset->end()) s += " " + getString(*_spit); + s += ">"; + return s; +} + + + + + + + + + +/* + * ******************************************************************** + * Fence_GCells implementation + */ +Fence_GCells::Fence_GCells(const Fence* fence) +// ************************************************************************************** +: Inherit() + , _fence(fence) + , _gc(fence->getGCell1()) +{ +} + +Fence_GCells::Fence_GCells(const Fence_GCells& gcelles) +// ************************************************************************************ +: Inherit() + , _fence(gcelles._fence) + , _gc(gcelles._gc) +{ +} + +Fence_GCells& Fence_GCells::operator=(const Fence_GCells& gcelles) +// **************************************************************** +{ + _fence = gcelles._fence; + _gc = gcelles._gc; + return *this; +} + +Collection* Fence_GCells::getClone() const +// *********************************************** +{ + return new Fence_GCells(*this); +} + +Locator* Fence_GCells::getLocator() const +// ********************************************** +{ + return new Locator(_fence, _gc); +} + +string Fence_GCells::_getString() const +// ************************************* +{ + string s = "<" + _TName("Fence::GCells"); + if (_gc) s += " " + getString(_gc); + s += ">"; + return s; +} + +/* + * ******************************************************************** + * Fence_GCells::Locator implementation + */ +Fence_GCells::Locator::Locator(const Fence* fence, GCell* gcell) +// ******************************************************** +: Inherit(), + _fence(fence), + _gc(gcell) +{ +} + +Fence_GCells::Locator::Locator(const Locator& locator) +// **************************************************** +: Inherit(), + _fence(locator._fence), + _gc(locator._gc) +{ +} + +Fence_GCells::Locator& Fence_GCells::Locator::operator=(const Locator& locator) +// ****************************************************************************** +{ + _fence = locator._fence; + _gc = locator._gc; + return *this; +} + +GCell* Fence_GCells::Locator::getElement() const +// ************************************************** +{ + return _gc; +} + +Locator* Fence_GCells::Locator::getClone() const +// ***************************************************************** +{ + return new Locator(*this); +} + +bool Fence_GCells::Locator::isValid() const +// ************************************************** +{ + return (_gc != NULL); +} + +void Fence_GCells::Locator::progress() +// ********************************************* +{ + if (_gc == _fence->getGCell1()) { + _gc = _fence->getGCell2(); + } else { + _gc = NULL; + } + + return; +} + +string Fence_GCells::Locator::_getString() const +// ******************************************************* +{ + string s = "<" + _TName("Fence::GCells::Locator"); + if (_gc) s += " " + getString(_gc); + s += ">"; + return s; +} + + +/* + * ******************************************************************** + * SubFenceSet implementation + * + */ +Fence::SubFenceSet::SubFenceSet() +// ******************************* + : Inherit() +{ +} + +unsigned Fence::SubFenceSet::_getHashValue(Fence* fence) const +{ + return ( (unsigned int)( (unsigned long)fence ) ) / 2; +} + +Fence* Fence::SubFenceSet::_getNextElement(Fence* fence) const +{ + return fence->_getNextOfFenceSubFenceSet(); +} + +void Fence::SubFenceSet::_setNextElement(Fence* fence, Fence* nextFence) const +{ + fence->_setNextOfFenceSubFenceSet(nextFence); + return; +} + + + +} // namespace Nimbus diff --git a/nimbus/src/FrontLine.cpp b/nimbus/src/FrontLine.cpp new file mode 100644 index 00000000..b99e05f2 --- /dev/null +++ b/nimbus/src/FrontLine.cpp @@ -0,0 +1,115 @@ +// +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// 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 +// +// Authors-Tag + + +#include "nimbus/NimbusEngine.h" + +namespace Nimbus { + + using namespace Hurricane; + + /* + * ******************************************************************** + * FrontLine implementation + * + */ + + FrontLine::FrontLine () + : _rootFences() + { + } + + FrontLine::~FrontLine () + { + } + + FrontLine* FrontLine::create () + { + FrontLine* frontline = new FrontLine (); + if (!frontline) throw Error("unable to create a frontline"); + frontline->_postCreate (); + return frontline; + } + + void FrontLine::destroy () + { + throw Error("Deletion of FrontLine undefined yet"); + return; + } + + void FrontLine::_preDestroy () + { + return; + } + + void FrontLine::_postCreate () + { + return; + } + + void FrontLine::addRootFence (Fence* fence) + { + // We may add some sanity checks here + // but we don't because FrontLine are created + // by an already consistency checked routine + _rootFences.push_back (fence); + fence->setFrontLine(this); + return; + } + + void FrontLine::moveTo (DbU::Unit target) + { + for ( + vector::iterator fit = _rootFences.begin() ; + fit != _rootFences.end() ; + fit++ + ) + { + (*fit)->_moveTo (target); + } + return; + } + + +} // namespace Nimbus + +#if 0 +Slot* getSlot (const string& name, Nimbus::FrontLine* frontline) +{ + return new StandardSlot(name, frontline); +} +#endif diff --git a/nimbus/src/GCell.cpp b/nimbus/src/GCell.cpp new file mode 100644 index 00000000..e9b0d3df --- /dev/null +++ b/nimbus/src/GCell.cpp @@ -0,0 +1,1388 @@ + +// 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 "crlcore/AllianceFramework.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 = AllianceFramework::get()->getCellGauge()->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(); + RBMap::const_reverse_iterator rbend = ((*col).second)->rend(); + 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(); + RBMap::const_reverse_iterator rbend = ((*col).second)->rend(); + 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 diff --git a/nimbus/src/Grid.cpp b/nimbus/src/Grid.cpp new file mode 100644 index 00000000..df80c8aa --- /dev/null +++ b/nimbus/src/Grid.cpp @@ -0,0 +1,1199 @@ + +// 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 + +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/UpdateSession.h" +#include "crlcore/Utilities.h" +#include "crlcore/ToolBox.h" +#include "crlcore/CellGauge.h" +#include "crlcore/LefDefExtension.h" +#include "crlcore/AllianceFramework.h" +#include "nimbus/GCell.h" +#include "nimbus/Fence.h" +#include "nimbus/VFence.h" +#include "nimbus/HFence.h" +#include "nimbus/StepProperty.h" +#include "nimbus/Grid.h" +#include "nimbus/NimbusEngine.h" + +namespace Nimbus { + +#define RG_HORIZONTAL 0 +#define RG_VERTICAL 1 + + + +/* + * ******************************************************************** + * GCell_GCells declaration + * ******************************************************************** + */ +class Grid_GCells : public Collection { + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + + public: typedef Hurricane::Locator Inherit; + + private: GCell* _nb; + private: unsigned _direction; + + public: Locator(GCell* gcell = NULL); + public: Locator(const Locator& locator); + + public: Locator& operator=(const Locator& locator); + + public: virtual GCell* getElement() const; + public: virtual Hurricane::Locator* getClone() const; + + public: virtual bool isValid() const; + + public: virtual void progress(); + + public: virtual string _getString() const; + }; + + + private: GCell* _nb; + private: unsigned _step; + + public: Grid_GCells(const Grid* grid, unsigned step); + public: Grid_GCells(const Grid_GCells& gcelles); + + public: Grid_GCells& operator=(const Grid_GCells& gcelles); + + public: virtual Collection* getClone() const; + public: virtual Hurricane::Locator* getLocator() const; + + public: virtual string _getString() const; +}; + +/* + * ******************************************************************** + * GCell_GCells declaration + * ******************************************************************** + */ +class Grid_FastGCells : public Collection { + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + + public: typedef Hurricane::Locator Inherit; + + private: GCell* _nb; + private: unsigned _direction; + + public: Locator(GCell* gcell = NULL); + public: Locator(const Locator& locator); + + public: Locator& operator=(const Locator& locator); + + public: virtual GCell* getElement() const; + public: virtual Hurricane::Locator* getClone() const; + + public: virtual bool isValid() const; + + public: virtual void progress(); + + public: virtual string _getString() const; + }; + + + private: GCell* _nb; + private: unsigned _step; + + public: Grid_FastGCells(const Grid* grid, unsigned step); + public: Grid_FastGCells(const Grid_FastGCells& gcelles); + + public: Grid_FastGCells& operator=(const Grid_FastGCells& gcelles); + + public: virtual Collection* getClone() const; + public: virtual Hurricane::Locator* getLocator() const; + + public: virtual string _getString() const; +}; + + + +/* + * ******************************************************************** + * Grid + * + * ******************************************************************** + */ +Grid::Grid (NimbusEngine* nimbus) +//******************************* + : _nimbus (nimbus) + , _cell (nimbus->getCell()) + , _rootGCell(NULL) + , _layer (NULL) + , _fences () +{ + _layer = DataBase::getDB()->getTechnology()->getLayer (Name ("SPL1")); + if ( _layer == NULL ) + throw Error("NimbusEngine needs layer to be defined"); + + Box defBox = LefDefExtension::getRowsBox(_cell); + + if ( not _nimbus->getWorkZone().isEmpty() ) { + _rootGCell = GCell::create(_nimbus, 0, _nimbus->getWorkZone()); + } else if ( not defBox.isEmpty() ) { + UpdateSession::open(); + + if ( _cell->getAbutmentBox().isEmpty() ) + _cell->setAbutmentBox ( defBox ); + + cmess1 << " - DEF abutment box found: " << defBox << endl; + _rootGCell = GCell::create(_nimbus, 0, defBox); + + UpdateSession::close(); + } else if ( _cell->getAbutmentBox().isEmpty() ) { + if ( isNoInstancePlacedOrFixed(_cell) ) { + DbU::Unit minWidth = DbU::Max; + DbU::Unit sumWidth = 0; + forEach ( Instance*, iinstance, _cell->getInstances() ) { + Cell* model = iinstance->getMasterCell(); + DbU::Unit width = model->getAbutmentBox().getWidth(); + + if ( width < minWidth ) minWidth = width; + sumWidth += width; + } + //rectangularShape(_margin, sumWidth, minWidth, nrows); + rectangularShape(_nimbus->getMargin(), nimbus->getAspectRatio(), sumWidth, minWidth ); + + UpdateSession::open(); + + _cell->setAbutmentBox( Box ( _rootGCell->getXMin(), _rootGCell->getYMin() + , _rootGCell->getXMax(), _rootGCell->getYMax()) ); +#if 0 + Point center = box.getCenter(); + forEach ( Instance*, iinstance, cell->getInstances() ) { + iinstance->setPlacementStatus ( Instance::PlacementStatus::PLACED ); + setStep(**iinstance, 0); + + Box insABox = iinstance->getAbutmentBox(); + Box masterABox = iinstance->getMasterCell()->getAbutmentBox(); + DbU::Unit xPos = center.getX(); + DbU::Unit yPos = center.getY(); + + instance->setTransformation + ( getTransformation ( masterABox + , xPos - insABox.getHalfWidth() + , yPos - insABox.getHalfHeight() + , Transformation::Orientation::ID + ) ); + } +#endif + UpdateSession::close(); + } else { + Box box = _cell->getBoundingBox(); + + UpdateSession::open(); + _cell->setAbutmentBox ( box ); + _rootGCell = GCell::create(_nimbus, 0, box); + UpdateSession::close(); + } + } else { + cmess1 << " - Design abutment box found: " << _cell->getAbutmentBox() << endl; + _rootGCell = GCell::create(_nimbus, 0, _cell->getAbutmentBox()); + } + _rootGCell->setAsPlacementLeaf(); + _rootGCell->setAsRoutingLeaf(); +} + +Grid::~Grid () +//************ +{ + _rootGCell->destroy(); +} + +#if 0 +void Grid::Clear() +// ************** +{ + _oldBoxes.clear(); + _newBoxes.clear(); + + return; +} +#endif + + void Grid::rectangularShape(double margin, double aspectRatio, DbU::Unit sumWidth, DbU::Unit minWidth) + // *************************************************************************************************** + { + cmess1 << " o Creating abutment box: (margin: " << margin + << ", aspect ratio:" << aspectRatio << ")" << endl; + + CellGauge* cg = AllianceFramework::get()->getCellGauge(); + DbU::Unit rowHeight = cg->getSliceHeight(); + DbU::Unit pitch = cg->getPitch(); + DbU::Unit marginWidth = (DbU::Unit)( (1.0+margin) * (double)sumWidth ); + + // AR = x/y S = x*y = marginWidth*SH x=S/y AR = S/y^2 + // y = sqrt(S/AR) + + DbU::Unit y = (DbU::Unit)sqrt ( ((double)marginWidth*(double)rowHeight) / aspectRatio ); + unsigned int rows = y / rowHeight; + + if ( (rows == 0) or (rows % rowHeight) ) ++rows; + DbU::Unit rowWidth = marginWidth / rows; + + if ( rowWidth < minWidth ) { + rowWidth = minWidth; + rows = marginWidth / rowWidth; + + if ( rows == 0 ) ++rows; + } + + DbU::Unit adjustWidth = rowWidth % pitch; + if ( adjustWidth != 0 ) + rowWidth += pitch - adjustWidth; + + Box ab = Box ( 0, 0, rowWidth, rows * rowHeight ); + +#if DEPRECATED + if ( nrows == 0 ) { + nrows = (int)(sqrt((1.0 + margin) * sumwidth / rowHeight) + 0.5); + } + + DbU::Unit rowWidth + = DbU::lambda + ( (int)((double)((int)((1.0 + margin) * DbU::getLambda(sumwidth) + / ((double)nrows * DbU::getLambda(pitch)) )) + * DbU::getLambda(pitch) + 0.5) + ); + + Box ab = Box(0, 0, rowWidth, nrows * rowHeight); +#endif + + cmess1 << " - Abutment box: " << ab << endl; + + _rootGCell = GCell::create(_nimbus, (unsigned) 0, ab); + } + +void Grid::horizontalLongSplit (unsigned step, DbU::Unit& Y) const +//*************************************************************** +{ + //Clear(); + + recLS (step, Y, RG_HORIZONTAL, _rootGCell); + return; +} + +void Grid::verticalLongSplit (unsigned step, DbU::Unit& X) const +//************************************************************* +{ + //Clear(); + + recLS (step, X, RG_VERTICAL, _rootGCell); + return; +} + + +void Grid::recLS (unsigned step, DbU::Unit& coord, unsigned direction, GCell* gcell) const +//************************************************************************************* +{ + //cout << " recLS : " << step << "-" << gcell->getStep() << endl; + + if (gcell->getStep() >= step) { + + return; + } + + if (gcell->getStep() == step - 1) { + + if (!(gcell->hasSubGCells())) { + gcell->makeSub(); + } + + if (direction == RG_HORIZONTAL) { + //cout << "subHSplit" << endl; + gcell->subHSplit (coord); + //cout << "subHSplitted" << endl; + } else if (direction == RG_VERTICAL) { + //cout << "subVSplit" << endl; + gcell->subVSplit (coord); + //cout << "subVSplitted" << endl; + } else { + cerr << "Nothing to do here" << endl; + abort(); + } + + return; + + } else { // exploration récursive + + if (!(gcell->hasSubGCells())) { + gcell->makeSub(); + } + + for_each_gcell (nb, gcell->getSubGCells()) { + if (direction == RG_HORIZONTAL) { + if ( + nb->horizontalIsCrossed (coord) + ) + { + recLS (step, coord, direction, nb); + } + } else if (direction == RG_VERTICAL) { + if ( + nb->verticalIsCrossed (coord) + ) + { + recLS (step, coord, direction, nb); + } + } else { + cerr << "Nothing to do here" << endl; + abort(); + } + + end_for; + } + } + + return; +} + +Layer* Grid::getLayer () const { + + return _layer; +} + +GCell* Grid::recGetGCell (unsigned step, Point& p, GCell* gcell) const { + GCell* res = NULL; + + if (! (gcell->contains(p))) { + return NULL; + } + + if (gcell->getStep() == step) { + return gcell; + + } else { + for_each_gcell (subBox, gcell->getSubGCells()) { + + res = recGetGCell (step, p, subBox); + + if (res) + break; + //return res; + end_for; + } + } + + assert (res); + + return res; +} // recGetGCell + +GCell* Grid::getGCell (unsigned step, Point& p) const +{ + + return recGetGCell (step, p, _rootGCell); +} + +const Box Grid::getBox (unsigned step, Point& p) const +{ + + GCell* gcell = getGCell (step, p); + return Box (gcell->getXMin(), gcell->getYMin(), gcell->getXMax(), gcell->getYMax()); +} + +Point Grid::getPosition (unsigned step, Point& pos) const +{ + + return (getGCell(step,pos)->getCenter()); +} + +DbU::Unit Grid::getX (unsigned step, DbU::Unit& X) const +{ + Point p = Point (X, DbU::lambda (0)); + return getGCell (step, p)->getXCenter(); +} + +DbU::Unit Grid::getY (unsigned step, DbU::Unit& Y) const +{ + Point p = Point (DbU::lambda (0), Y); + return getGCell (step, p)->getYCenter(); +} + + +void Grid::recDumpGrid (GCell* gcell) const{ + + cout << " Step : " << gcell->getStep() << endl; + gcell->dumpPavement(); + + for_each_gcell (subBox, gcell->getSubGCells()) { + recDumpGrid(subBox); + end_for; + } + + return; +} + +void Grid::dumpGrid () const{ + + cout << " o dumping grid..." << endl; + recDumpGrid (_rootGCell); + cout << " - grid dumped." << endl; + + return; +} + +/* + * ******************************************************************** + * Collection des boites du niveau step + */ +GCells Grid::getGCells (unsigned step) const +{ + return Grid_GCells(this, step); +} +GCells Grid::getFastGCells (unsigned step) const +{ + return Grid_FastGCells(this, step); +} + +/* + * ******************************************************************** + * + * Création des Frontières + */ +void Grid::createFences (unsigned step) +{ + _fences[step] = new FenceSet(); + + for_each_gcell (gcell, getGCells(step)) { + + //cmess1 << gcell << endl; + + if (!gcell->getLeftFence()) { + GCell* nbleft = gcell->computeLeftOfMe(); + if (nbleft) { + Fence* fence = static_cast (VFence::create (this, nbleft, gcell)); + gcell->getContainer()->addInnerFence(fence); + fence->setStep(step); + _fences[step]->_insert(fence); + } + + } + if (!gcell->getRightFence()) { + GCell* nbright = gcell->computeRightOfMe(); + if (nbright) { + Fence* fence = static_cast (VFence::create (this, gcell, nbright)); + gcell->getContainer()->addInnerFence(fence); + fence->setStep(step); + _fences[step]->_insert(fence); + } + } + if (!gcell->getUpFence()) { + GCell* nbup = gcell->computeUpOfMe(); + if (nbup) { + Fence* fence = static_cast (HFence::create (this, nbup, gcell)); + gcell->getContainer()->addInnerFence(fence); + fence->setStep(step); + _fences[step]->_insert(fence); + } + } + if (!gcell->getDownFence()) { + GCell* nbdown = gcell->computeDownOfMe(); + if (nbdown) { + Fence* fence = static_cast (HFence::create (this, gcell, nbdown)); + gcell->getContainer()->addInnerFence(fence); + fence->setStep(step); + _fences[step]->_insert(fence); + } + } + end_for; + } + return; +} + +/* + * ******************************************************************** + * + * Collection des frontieres pour un niveau + */ +Fences Grid::getFences (unsigned step) +{ + return _fences[step]->getElements(); +} + +Fence* Grid::getFenceBetween (GCell* nb1, GCell* nb2) const +{ + Fence* fence = testFenceBetween (nb1, nb2); + if (!fence) + { + cerr << "no fence between " << nb1 << " and " << nb2 << "." << endl; + abort(); + throw Error ("getFenceBetween : gcelles are not linked together"); + } + + return fence; +} + +Fence* Grid::testFenceBetween (GCell* nb1, GCell* nb2) const +{ + if (nb1 == nb2) + { + return NULL; +#if 0 + abort(); + throw Error ("getFenceBetween : same gcelles"); +#endif + } + if (nb1->getStep() != nb2->getStep()) + { + return NULL; +#if 0 + abort(); + throw Error ("getFenceBetween : gcelles from different grid levels"); +#endif + } + for_each_fence (fence, nb1->getSurroundingFences()) + { + if (fence->getOppositeGCell (nb1) == nb2) + return fence; + + end_for; + } + + return NULL; +} + + +// Compat + +Grid* Grid::create (unsigned n, DbU::Unit& width, DbU::Unit& height) { + + throw Error ("Nimbus: Grid: entering an outdated and deactivated function"); + return NULL; +} + + +Box Grid::getGRBox (unsigned step, Point& p) { + + return (getBox (step, p)); +} + +Contact* Grid::getContact (Net& net, Point& position) { + + for_each_contact (contact, net.getContacts()) { + + if (contact->getPosition() == position) { + return contact; + } else { + // vide + } + + end_for; + } + + return NULL; +} + +Contact* Grid::getOrCreateContact (Net& net, Point& position, DbU::Unit width, DbU::Unit height) { + + Contact* c = NULL; + + c = getContact (net, position); + + if (!c) + c = Contact::create (&net, getLayer(), position.getX(), position.getY(), width, height); + + return c; +} +#if 0 +Contact* Grid::getOrCreateContact (Net& net, Point& position) { + + Contact* c = NULL; + + c = getContact (net, position); + + if (!c) + c = Contact::create (&net, getLayer(), position.getX(), position.getY(), DbU::lambda(5), DbU::lambda(5)); + + return c; +} +#endif + +DbU::Unit Grid::getVSplitterHalfLength (unsigned step) { + + return DbU::lambda (2); +} + +DbU::Unit Grid::getHSplitterHalfLength (unsigned step) { + + return DbU::lambda (2); +} + +Point Grid::getSubUpLeft (unsigned step, Point& pos) { + + GCell* gcell = getGCell (step, pos); + return gcell->getSubUpperLeft()->getCenter(); +} +Point Grid::getSubUpRight (unsigned step, Point& pos) { + + GCell* gcell = getGCell (step, pos); + assert (gcell); + assert (gcell->getSubUpperRight()); + return gcell->getSubUpperRight()->getCenter(); +} +Point Grid::getSubDownLeft (unsigned step, Point& pos) { + + GCell* gcell = getGCell (step, pos); + return gcell->getSubBottomLeft()->getCenter(); +} +Point Grid::getSubDownRight (unsigned step, Point& pos) { + + GCell* gcell = getGCell (step, pos); + return gcell->getSubBottomRight()->getCenter(); +} + +GCell* Grid::getLeftOf (const GCell* gcell) const +{ + GCell* nbl = gcell->getLeftOfMe(); + if (!nbl) nbl = gcell->computeLeftOfMe(); + + return nbl; +} +GCell* Grid::getRightOf (const GCell* gcell) const +{ + GCell* nbr = gcell->getRightOfMe(); + if (!nbr) nbr = gcell->computeRightOfMe(); + + return nbr; +} +GCell* Grid::getUpOf (const GCell* gcell) const +{ + GCell* nbu = gcell->getUpOfMe(); + if (!nbu) nbu = gcell->computeUpOfMe(); + + return nbu; +} +GCell* Grid::getDownOf (const GCell* gcell) const +{ + GCell* nbd = gcell->getDownOfMe(); + if (!nbd) nbd = gcell->computeDownOfMe(); + + return nbd; +} + +GCell* Grid::getUpperLeftCorner (unsigned step) const +{ + GCell* gcell = getRoot(); + + for (unsigned level = 0 ; level < step ; level++) { + gcell = gcell->getSubUpperLeft(); + if (!gcell) throw Error ("Nimbus crushed when diving too deep."); + } + return gcell; +} +GCell* Grid::getUpperRightCorner (unsigned step) const +{ + GCell* gcell = getRoot(); + + for (unsigned level = 0 ; level < step ; level++) { + gcell = gcell->getSubUpperRight(); + if (!gcell) throw Error ("Nimbus crushed when diving too deep."); + } + return gcell; +} +GCell* Grid::getLowerLeftCorner (unsigned step) const +{ + GCell* gcell = getRoot(); + + for (unsigned level = 0 ; level < step ; level++) { + gcell = gcell->getSubLowerLeft(); + if (!gcell) throw Error ("Nimbus crushed when diving too deep."); + } + return gcell; +} +GCell* Grid::getLowerRightCorner (unsigned step) const +{ + GCell* gcell = getRoot(); + + for (unsigned level = 0 ; level < step ; level++) { + gcell = gcell->getSubLowerRight(); + if (!gcell) throw Error ("Nimbus crushed when diving too deep."); + } + return gcell; +} + + + + + + + +/* + * ******************************************************************** + * + * Grid_GCells implementation + */ + +Grid_GCells::Grid_GCells(const Grid* grid, unsigned step) +// ************************************************************************ +: Inherit() + , _nb(NULL) + , _step(step) +{ + _nb = grid->getRoot(); + + for (unsigned level = 0 ; level < step ; level++) { + _nb = _nb->getSubUpperLeft(); + if (!_nb) throw Error ("Nimbus crushed when diving too deep."); + } +} + +Grid_GCells::Grid_GCells(const Grid_GCells& gcelles) +// ************************************************************************ +: Inherit() + , _nb(gcelles._nb) + , _step(gcelles._step) +{ +} + +Grid_GCells& Grid_GCells::operator=(const Grid_GCells& gcelles) +// *********************************************************************************** +{ + _nb = gcelles._nb; + _step = gcelles._step; + return *this; +} + +Collection* Grid_GCells::getClone() const +// *********************************************** +{ + return new Grid_GCells(*this); +} + +Locator* Grid_GCells::getLocator() const +// ****************************************************** +{ + return new Locator(_nb); +} + +string Grid_GCells::_getString() const +// ************************************* +{ + string s = "<" + _TName("GCell::GCells"); + if (_nb) s += " " + getString(_nb); + s += ">"; + return s; +} + +/* + * ******************************************************************** + * Grid_GCells::Locator implementation + */ +Grid_GCells::Locator::Locator(GCell* gcell) +// ******************************************************** +: Inherit(), + _nb(gcell), + _direction(0) +{ +} + +Grid_GCells::Locator::Locator(const Locator& locator) +// **************************************************** +: Inherit(), + _nb(locator._nb), + _direction(locator._direction) +{ +} + +Grid_GCells::Locator& Grid_GCells::Locator::operator=(const Locator& locator) +// ****************************************************************************** +{ + _nb = locator._nb; + _direction = locator._direction; + return *this; +} + +GCell* Grid_GCells::Locator::getElement() const +// ********************************************* +{ + return _nb; +} + +Locator* Grid_GCells::Locator::getClone() const +// ***************************************************** +{ + return new Locator(*this); +} + +bool Grid_GCells::Locator::isValid() const +// ***************************************** +{ + return (_nb != NULL); +} + +void Grid_GCells::Locator::progress() +// ************************************ +{ + GCell* gcell = NULL; + + switch (_direction) { + + case 0: + gcell = _nb->computeRightOfMe(); + if (!gcell) { + gcell = _nb->computeDownOfMe(); + _direction = 1; + } + break; + case 1: + gcell = _nb->computeLeftOfMe(); + if (!gcell) { + gcell = _nb->computeDownOfMe(); + _direction = 0; + } + break; + default: + gcell = NULL; + break; + } + + _nb = gcell; +} + +string Grid_GCells::Locator::_getString() const +// ********************************************** +{ + string s = "<" + _TName("GCells::GCells::Locator"); + if (_nb) s += " " + getString(_nb); + s += ">"; + return s; +} + + + +/* + * ******************************************************************** + * Grid_FastGCells implementation + */ +Grid_FastGCells::Grid_FastGCells(const Grid* grid, unsigned step) +// ************************************************************************************** +: Inherit() + , _nb(NULL) + , _step(step) +{ + _nb = grid->getRoot(); + + for (unsigned level = 0 ; level < step ; level++) { + _nb = _nb->getSubUpperLeft(); + if (!_nb) throw Error ("Nimbus crushed when diving too deep."); + } +} + +Grid_FastGCells::Grid_FastGCells(const Grid_FastGCells& gcelles) +// ************************************************************************************ +: Inherit() + , _nb(gcelles._nb) + , _step(gcelles._step) +{ +} + +Grid_FastGCells& Grid_FastGCells::operator=(const Grid_FastGCells& gcelles) +// **************************************************************** +{ + _nb = gcelles._nb; + _step = gcelles._step; + return *this; +} + +Collection* Grid_FastGCells::getClone() const +// *********************************************** +{ + return new Grid_FastGCells(*this); +} + +Locator* Grid_FastGCells::getLocator() const +// ********************************************** +{ + return new Locator(_nb); +} + +string Grid_FastGCells::_getString() const +// ************************************* +{ + string s = "<" + _TName("GCell::GCells"); + if (_nb) s += " " + getString(_nb); + s += ">"; + return s; +} + +/* + * ******************************************************************** + * Grid_FastGCells::Locator implementation + */ +Grid_FastGCells::Locator::Locator(GCell* gcell) +// ******************************************************** +: Inherit(), + _nb(gcell), + _direction(0) +{ +} + +Grid_FastGCells::Locator::Locator(const Locator& locator) +// **************************************************** +: Inherit(), + _nb(locator._nb), + _direction(locator._direction) +{ +} + +Grid_FastGCells::Locator& Grid_FastGCells::Locator::operator=(const Locator& locator) +// ****************************************************************************** +{ + _nb = locator._nb; + _direction = locator._direction; + return *this; +} + +GCell* Grid_FastGCells::Locator::getElement() const +// ********************************************************* +{ + return _nb; +} + +Locator* Grid_FastGCells::Locator::getClone() const +// ***************************************************************** +{ + return new Locator(*this); +} + +bool Grid_FastGCells::Locator::isValid() const +// ************************************************** +{ + return (_nb != NULL); +} + +void Grid_FastGCells::Locator::progress() +// ********************************************* +{ + GCell* gcell = NULL; + + switch (_direction) { + + case 0: + gcell = _nb->getRightOfMe(); + if (!gcell) { + gcell = _nb->getDownOfMe(); + _direction = 1; + } + break; + case 1: + gcell = _nb->getLeftOfMe(); + if (!gcell) { + gcell = _nb->getDownOfMe(); + _direction = 0; + } + break; + default: + gcell = NULL; + break; + } + + _nb = gcell; +} + +string Grid_FastGCells::Locator::_getString() const +// ******************************************************* +{ + string s = "<" + _TName("Grid::FastGCells::Locator"); + if (_nb) s += " " + getString(_nb); + s += ">"; + return s; +} + + +#if 0 + + + + +/* + * ******************************************************************** + * Grid_Fences implementation + */ +Grid_Fences::Grid_Fences(const Grid* grid, unsigned step) +// ************************************************************************************** +: Inherit() + , _nb(NULL) + , _fence(NULL) + , _step(step) +{ + _nb = grid->getRoot(); + + for (unsigned level = 0 ; level < step ; level++) { + _nb = _nb->getSubUpperLeft(); + if (!_nb) throw Error ("Nimbus crushed while diving too deep."); + } +} + +Grid_Fences::Grid_Fences(const Grid_Fences& fences) +// ************************************************************************************ +: Inherit() + , _nb(fences._nb) + , _fence(fences._nb) + , _step(fences._step) +{ +} + +Grid_Fences& Grid_Fences::operator=(const Grid_Fences& fences) +// **************************************************************** +{ + _nb = ._nb; + _step = ._step; + return *this; +} + +Collection* Grid_Fences::getClone() const +// *********************************************** +{ + return new Grid_Fences(*this); +} + +Locator* Grid_Fences::getLocator() const +// ********************************************** +{ + return new Locator(_nb); +} + +string Grid_Fences::_getString() const +// ************************************* +{ + string s = "<" + _TName("Fence::Fencees"); + if (_nb) s += " " + getString(_nb); + s += ">"; + return s; +} + +/* + * ******************************************************************** + * Grid_Fences::Locator implementation + */ +Grid_Fences::Locator::Locator(Fence* gcell) +// ******************************************************** +: Inherit(), + _nb(gcell), + _direction(0) +{ +} + +Grid_Fences::Locator::Locator(const Locator& locator) +// **************************************************** +: Inherit(), + _nb(locator._nb), + _direction(locator._direction) +{ +} + +Grid_Fences::Locator& Grid_Fences::Locator::operator=(const Locator& locator) +// ****************************************************************************** +{ + _nb = locator._nb; + _direction = locator._direction; + return *this; +} + +Fence* Grid_Fences::Locator::getElement() const +// ********************************************************* +{ + return _nb; +} + +Locator* Grid_Fences::Locator::getClone() const +// ***************************************************************** +{ + return new Locator(*this); +} + +bool Grid_Fences::Locator::isValid() const +// ************************************************** +{ + return (_nb != NULL); +} + +void Grid_Fences::Locator::progress() +// ********************************************* +{ + Fence* gcell = NULL; + + switch (_direction) { + + case 0: + gcell = _nb->getLeftOfMe(); + if (!gcell) { + gcell = _nb->getDownOfMe(); + _direction = 1; + } + break; + case 1: + gcell = _nb->getRightOfMe(); + if (!gcell) { + gcell = _nb->getDownOfMe(); + _direction = 0; + } + break; + default: + gcell = NULL; + break; + } + + _nb = gcell; +} + +string Grid_Fences::Locator::_getString() const +// ******************************************************* +{ + string s = "<" + _TName("Grid::FastFencees::Locator"); + if (_nb) s += " " + getString(_nb); + s += ">"; + return s; +} + +#endif + + + +/* + * FenceSet implementation + * + */ +Grid::FenceSet::FenceSet() +// ********************** + : Inherit() +{ +} + +unsigned Grid::FenceSet::_getHashValue(Fence* fence) const +{ + return ( (unsigned int)( (unsigned long)fence ) ) / 2; +} + +Fence* Grid::FenceSet::_getNextElement(Fence* fence) const +{ + return fence->_getNextOfGridFenceSet(); +} + +void Grid::FenceSet::_setNextElement(Fence* fence, Fence* nextFence) const +{ + fence->_setNextOfGridFenceSet(nextFence); + return; +} + + +} diff --git a/nimbus/src/HFence.cpp b/nimbus/src/HFence.cpp index ad9722e7..13c378ff 100644 --- a/nimbus/src/HFence.cpp +++ b/nimbus/src/HFence.cpp @@ -8,7 +8,7 @@ #include "crlcore/RoutingLayerGauge.h" -#include "nimbus/Nimbus.h" +#include "nimbus/NimbusEngine.h" #include "nimbus/RoutTools.h" #include "nimbus/HFence.h" diff --git a/nimbus/src/NimbusEngine.cpp b/nimbus/src/NimbusEngine.cpp new file mode 100644 index 00000000..23be9f70 --- /dev/null +++ b/nimbus/src/NimbusEngine.cpp @@ -0,0 +1,1872 @@ +// +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// 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 +// +// 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 "crlcore/AllianceFramework.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 { + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + + public: typedef Hurricane::Locator 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* 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* getClone() const; + public: virtual Hurricane::Locator* getLocator() const; + + public: virtual string _getString() const; +}; + + + +/* + * ******************************************************************** + * Nimbus_ColumnGCells declaration + * ******************************************************************** + */ +class Nimbus_ColumnGCells : public Collection { + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + + public: typedef Hurricane::Locator 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* 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* getClone() const; + public: virtual Hurricane::Locator* getLocator() const; + + public: virtual string _getString() const; +}; + + + +/* + * ******************************************************************** + * Nimbus_RowGCells declaration + * ******************************************************************** + */ +class Nimbus_RowGCells : public Collection { + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + + public: typedef Hurricane::Locator 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* 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* getClone() const; + public: virtual Hurricane::Locator* getLocator() const; + + public: virtual string _getString() const; +}; + + + +/* + * ******************************************************************** + * Nimbus_Fences declaration + * ******************************************************************** + */ +class Nimbus_Fences : public Collection { + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + + public: typedef Hurricane::Locator 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* 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* getClone() const; + public: virtual Hurricane::Locator* getLocator() const; + + public: virtual string _getString() const; +}; + + +/* + * ******************************************************************** + * Nimbus_Layers declaration + * ******************************************************************** + */ +class Nimbus_Layers : public Collection { + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + + public: typedef Hurricane::Locator Inherit; + + private: const set* _lset; + private: set::iterator _lit; + + public: Locator(const set* lset, set::iterator lit); + public: Locator(const Locator& locator); + + public: Locator& operator=(const Locator& locator); + + public: virtual Layer* getElement() const; + public: virtual Hurricane::Locator* getClone() const; + + public: virtual bool isValid() const; + public: virtual void progress(); + + public: virtual string _getString() const; + }; + + + private: const set* _lset; + private: set::iterator _lit; + + public: Nimbus_Layers(const set* lset); + public: Nimbus_Layers(const Nimbus_Layers& layers); + + public: Nimbus_Layers& operator=(const Nimbus_Layers& layers); + + public: virtual Collection* getClone() const; + public: virtual Hurricane::Locator* getLocator() const; + + public: virtual string _getString() const; +}; + +namespace { + +void PreCreate(Cell* cell, const Library* library) +{ + 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(routingGauge); + +} + +} + +const Name NimbusEngine::_toolName = "Nimbus"; + +NimbusEngine::NimbusEngine (Cell* cell, const Box& workZone) +// ********************************************************* + : Inherit (cell) + , _configuration (Configuration::getDefault()->clone()) + , _depth (0) + , _placementBoxSet() + , _routingBoxSet () + , _routingLayerSet() +{ + if ( not workZone.isEmpty() ) _configuration->setWorkZone(workZone); +} + +NimbusEngine* NimbusEngine::create (Cell* cell, const Library* library, const Box& workZone) +// ***************************************************************************************** +{ + PreCreate(cell, library); + + 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 numColsInf = (unsigned) rint((DbU::getLambda(width) / DbU::getLambda(AllianceFramework::get()->getCellGauge()->getPitch())) / nbSplits); + if (numColsInf == 0) throw Error ("no more split allowed", 1); + DbU::Unit splitWidth = DbU::lambda(numColsInf * DbU::getLambda(AllianceFramework::get()->getCellGauge()->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 numRowsInf = (unsigned) rint((DbU::getLambda(height) / DbU::getLambda(AllianceFramework::get()->getCellGauge()->getSliceHeight())) / nbSplits); + if (numRowsInf == 0) throw Error ("no more split allowed", 1); + DbU::Unit splitHeight = DbU::lambda(numRowsInf * DbU::getLambda(AllianceFramework::get()->getCellGauge()->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 = AllianceFramework::get()->getCellGauge()->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; + //throw Error ("no more split allowed"); +} + +#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 gcelles; + set newleaves; + getPlacementLeaves().fill(gcelles); + + for_each_gcell (gcell, getPlacementLeaves()) + { + GCell* container = gcell->getContainer(); + if (container) gcelles.insert (container); + end_for; + } + + for(set::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::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 gcelles; + getPlacementLeaves().fill(gcelles); + for(set::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 (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 (compo)) ) + continue; + SplitterContact* sc = dynamic_cast (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(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* Nimbus_GCells::getClone() const +// *********************************************** +{ + return new Nimbus_GCells(*this); +} + +Locator* 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* 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* Nimbus_ColumnGCells::getClone() const +// ********************************************************* +{ + return new Nimbus_ColumnGCells(*this); +} + +Locator* 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* 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* Nimbus_RowGCells::getClone() const +// ****************************************************** +{ + return new Nimbus_RowGCells(*this); +} + +Locator* 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* 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* Nimbus_Fences::getClone() const +// *********************************************** +{ + return new Nimbus_Fences(*this); +} + +Locator* 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* 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* 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* Nimbus_Layers::getClone() const +// *********************************************** +{ + return new Nimbus_Layers(*this); +} + +Locator* 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* lset, set::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* 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 diff --git a/nimbus/src/VFence.cpp b/nimbus/src/VFence.cpp index 94ceb448..66d551b0 100644 --- a/nimbus/src/VFence.cpp +++ b/nimbus/src/VFence.cpp @@ -7,7 +7,7 @@ // Author : Hugo Clément -#include "nimbus/Nimbus.h" +#include "nimbus/NimbusEngine.h" #include "nimbus/RoutTools.h" #include "nimbus/VFence.h" diff --git a/nimbus/src/nimbus/Grid.h b/nimbus/src/nimbus/Grid.h new file mode 100644 index 00000000..7245fb20 --- /dev/null +++ b/nimbus/src/nimbus/Grid.h @@ -0,0 +1,161 @@ + +// 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 + + +#ifndef __NIMBUS_GRID_H__ +#define __NIMBUS_GRID_H__ + +#include "hurricane/Contact.h" +#include "nimbus/GCells.h" +#include "nimbus/Fences.h" + +namespace Nimbus { + + + using namespace Hurricane; + + class NimbusEngine; + + +class Grid { + + + public: + class FenceSet : public IntrusiveSet { + public: + typedef IntrusiveSet Inherit; + FenceSet(); + virtual unsigned _getHashValue(Fence* fence) const; + virtual Fence* _getNextElement(Fence* fence) const; + virtual void _setNextElement(Fence* fence, Fence* nextFence) const; + }; + + private: NimbusEngine* _nimbus; + private: Cell* _cell; + private: GCell* _rootGCell; + private: Layer* _layer; + private: map _fences; + + /*! + * \fn Grid::Grid ( NimbusEngine* nimbus ) + * \param nimbus The engine owning the grid. + */ + public: Grid (NimbusEngine* nimbus); + public: ~Grid (); + + public: Cell* getCell() const { return _cell; }; + public: NimbusEngine* getNimbus() const { return _nimbus; }; + /*! + * \fn void Grid::rectangularShape ( double margin, double aspectRatio, DbU::Unit sumWidth, DbU::Unit minWidth ) + * \param margin Additionnal free space in the abutment box + * \param aspectRatio + * \param sumWidth + */ + public: void rectangularShape(double margin, double aspectRatio, DbU::Unit sumWidth, DbU::Unit minWidth); + + /*! + * \fn void Grid::horizontalLongSplit (unsigned step, DbU::Unit& Y) + * \param step the hierarchy level to be splitted + * \param Y ordinate of the cut-line + * Makes a full horizontal split of the abutment box apart from a cut line + */ + public: void horizontalLongSplit (unsigned step, DbU::Unit& Y) const; + /*! + * \fn void Grid::verticalLongSplit (unsigned step, DbU::Unit& X) + * \param step the hierarchy level to be splitted + * \param X abscisse of the cut-line + * Makes a full vertical split of the abutment box apart from a cut line + */ + public: void verticalLongSplit (unsigned step, DbU::Unit& X) const; + + public: static Grid* create (unsigned n, DbU::Unit& width, DbU::Unit& height); + + // Layer du routage global + /*! + * \fn Layer* Grid::getLayer () + * Returns the hurricane layer for the global route elements (splitters) + */ + public: Layer* getLayer () const; + + // Fenetre racine (boite d'aboutement) + /*! + * \fn GCell* Grid::getRoot () + * Returns the root of the partitionning box tree + */ + public: GCell* getRoot () const { return _rootGCell; }; + + // Retourne la boite englobante pour p + /*! + * \fn GCell* Grid::getGCell (unsigned step, Point& p) + * \param step the level to be searched + * \param p the point + * Returns the hierarchy level "step" GCell containing p + */ + public: GCell* getGCell (unsigned step, Point& p) const; + /*! + * \fn Box* Grid::getBox (unsigned step, Point& p) + * \param step the level to be searched + * \param p the point + * Returns the hierarchy level "step" hurricane Box containing p + */ + public: const Box getBox (unsigned step, Point& p) const; + + // Centre de fenetre correspondant à X, Y, pos pour l'étape step. + public: DbU::Unit getX (unsigned step, DbU::Unit& X) const; + public: DbU::Unit getY (unsigned step, DbU::Unit& Y) const; + public: Point getPosition (unsigned step, Point& pos) const; + + public: GCells getGCells (unsigned step) const; + public: GCells getFastGCells (unsigned step) const; + + public: void createFences (unsigned step); + public: Fences getFences (unsigned step); + public: Fence* getFenceBetween (GCell* gc1, GCell* gc2) const; + public: Fence* testFenceBetween (GCell* gc1, GCell* gc2) const; + + public: GCell* getLeftOf (const GCell* gcell) const; + public: GCell* getRightOf (const GCell* gcell) const; + public: GCell* getUpOf (const GCell* gcell) const; + public: GCell* getDownOf (const GCell* gcell) const; + + public: GCell* getUpperLeftCorner (unsigned step) const; + public: GCell* getUpperRightCorner (unsigned step) const; + public: GCell* getLowerLeftCorner (unsigned step) const; + public: GCell* getLowerRightCorner (unsigned step) const; + + // affichage, pour le debug + public: void dumpGrid() const; + private: void recDumpGrid (GCell* gcell) const; + + // utilisation interne uniquement + private: void recLS (unsigned step, DbU::Unit& coord, unsigned direction, GCell* gcell) const; + private: GCell* recGetGCell (unsigned step, Point& p, GCell* gcell) const; + + + + + // compat + public: Box getGRBox (unsigned step, Point &p); + + public: Contact* getContact (Net& net, Point& position); + public: Contact* getOrCreateContact (Net& net, Point& position, DbU::Unit width = DbU::lambda(5), DbU::Unit height = DbU::lambda(5)); + //public: Contact* getOrCreateContact (Net& net, Point& position); + + public: DbU::Unit getHSplitterHalfLength (unsigned _step); + public: DbU::Unit getVSplitterHalfLength (unsigned _step); + + public: Point getSubUpRight (unsigned step, Point &pos); + public: Point getSubUpLeft (unsigned step, Point &pos); + public: Point getSubDownRight (unsigned step, Point &pos); + public: Point getSubDownLeft (unsigned step, Point &pos); +}; + +Grid* getGrid (); + +} +#endif diff --git a/nimbus/src/nimbus/NimbusEngine.h b/nimbus/src/nimbus/NimbusEngine.h new file mode 100644 index 00000000..ca649110 --- /dev/null +++ b/nimbus/src/nimbus/NimbusEngine.h @@ -0,0 +1,169 @@ +// +// 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 +// +// Authors-Tag + + +#ifndef __NIMBUS_NIMBUS_H__ +#define __NIMBUS_NIMBUS_H__ + +#include "hurricane/Layers.h" +#include "crlcore/ToolEngine.h" +#include "nimbus/Configuration.h" +#include "nimbus/GCell.h" +#include "nimbus/GCells.h" +#include "nimbus/Grid.h" +#include "nimbus/Fence.h" +#include "nimbus/HFence.h" +#include "nimbus/VFence.h" +#include "nimbus/FrontLine.h" +#include "nimbus/Splitter.h" +#include "nimbus/SplitterContact.h" +#include "nimbus/StepProperty.h" +#include "nimbus/FenceProperty.h" + +namespace Hurricane { + class Library; +} + +namespace Nimbus { + +using namespace Hurricane; + +class NimbusEngine : public ToolEngine { + + typedef ToolEngine Inherit; + +// Attributes +// ********** + private: + static const Name _toolName; + Configuration* _configuration; + unsigned int _depth; + unsigned int _step; + Grid* _grid; + + GCellSet _placementBoxSet; + GCellSet _routingBoxSet; + FenceSet _routingFenceSet; + + set _routingLayerSet; + + +// Constructors +// ************ + private: NimbusEngine (Cell* cell, const Box& workzone); + + public: static NimbusEngine* create (Cell* cell, const Library* library, const Box& workZone=Box()); + + // Accessors + // ********* + public: + virtual const Name& getName () const; + static const Name& staticGetName (); + static NimbusEngine* get ( Cell* ); + inline bool doPinsPlacement () const; + inline double getAspectRatio () const; + inline double getMargin () const; + inline const Box& getWorkZone () const; + + public: Grid* getGrid() { return _grid; }; + public: unsigned getDepth() { return _depth; }; + public: unsigned getSteps() { cerr<<"getSteps is deprecated"<doPinsPlacement(); } + inline double NimbusEngine::getAspectRatio () const { return _configuration->getAspectRatio(); } + inline double NimbusEngine::getMargin () const { return _configuration->getMargin(); } + inline const Box& NimbusEngine::getWorkZone () const { return _configuration->getWorkZone(); } + + +} // namespace Nimbus + + +#endif // __NIMBUS_NIMBUS_H__