From a1726771b6c1a33332f2a66cc6c9868f26877b28 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Tue, 9 Mar 2010 15:25:20 +0000 Subject: [PATCH] * ./hurricane/src/hviewer, ./coriolis/src/crlcore, ./coriolis/src/knik, ./coriolis/src/katabatic, ./coriolis/src/kite, ./coriolis/src/equinox, ./coriolis/src/solstice, ./coriolis/src/ispd: - SVN MOVE: Source tree simplification & uniformisation. Now all tools are at the same level, directly under the root of the repository. No more "coriolis/src". --- equinox/CMakeLists.txt | 26 + equinox/cmake_modules/CMakeLists.txt | 1 + equinox/cmake_modules/FINDEquinox.cmake | 48 ++ equinox/cmake_modules/FindEQUINOX.cmake | 47 ++ equinox/src/CMakeLists.txt | 55 ++ equinox/src/Equi.cpp | 186 +++++ equinox/src/EquinoxCollections.cpp | 721 ++++++++++++++++++ equinox/src/EquinoxEngine.cpp | 576 ++++++++++++++ equinox/src/EquinoxFilters.cpp | 240 ++++++ equinox/src/GraphicEquinoxEngine.cpp | 228 ++++++ equinox/src/Strategy.cpp | 523 +++++++++++++ equinox/src/Tile.cpp | 90 +++ equinox/src/TileSweepLine.cpp | 47 ++ equinox/src/UnionFind.cpp | 91 +++ equinox/src/equinox/Equi.h | 165 ++++ equinox/src/equinox/EquinoxCollections.h | 269 +++++++ equinox/src/equinox/EquinoxEngine.h | 209 +++++ equinox/src/equinox/EquinoxFilters.h | 250 ++++++ equinox/src/equinox/Equis.h | 60 ++ equinox/src/equinox/GraphicEquinoxEngine.h | 98 +++ equinox/src/equinox/Interval.h.b | 54 ++ equinox/src/equinox/Strategy.h | 165 ++++ equinox/src/equinox/SweepLine.h | 411 ++++++++++ equinox/src/equinox/Tile.h | 156 ++++ equinox/src/equinox/TileSweepLine.h | 43 ++ equinox/src/equinox/Tiles.h | 128 ++++ equinox/src/equinox/UnionFind.h | 60 ++ equinox/src/equinox/intervaltree.h.b | 625 +++++++++++++++ equinox/src/equinox/misc.h.b | 166 ++++ equinox/src/intervalTree/src/IntervalTree.cpp | 410 ++++++++++ .../src/intervalTree/src/equinox/Interval.h | 54 ++ .../intervalTree/src/equinox/IntervalTree.h | 625 +++++++++++++++ 32 files changed, 6827 insertions(+) create mode 100644 equinox/CMakeLists.txt create mode 100644 equinox/cmake_modules/CMakeLists.txt create mode 100644 equinox/cmake_modules/FINDEquinox.cmake create mode 100644 equinox/cmake_modules/FindEQUINOX.cmake create mode 100644 equinox/src/CMakeLists.txt create mode 100644 equinox/src/Equi.cpp create mode 100644 equinox/src/EquinoxCollections.cpp create mode 100644 equinox/src/EquinoxEngine.cpp create mode 100644 equinox/src/EquinoxFilters.cpp create mode 100644 equinox/src/GraphicEquinoxEngine.cpp create mode 100644 equinox/src/Strategy.cpp create mode 100644 equinox/src/Tile.cpp create mode 100644 equinox/src/TileSweepLine.cpp create mode 100644 equinox/src/UnionFind.cpp create mode 100644 equinox/src/equinox/Equi.h create mode 100644 equinox/src/equinox/EquinoxCollections.h create mode 100644 equinox/src/equinox/EquinoxEngine.h create mode 100644 equinox/src/equinox/EquinoxFilters.h create mode 100644 equinox/src/equinox/Equis.h create mode 100644 equinox/src/equinox/GraphicEquinoxEngine.h create mode 100644 equinox/src/equinox/Interval.h.b create mode 100644 equinox/src/equinox/Strategy.h create mode 100644 equinox/src/equinox/SweepLine.h create mode 100644 equinox/src/equinox/Tile.h create mode 100644 equinox/src/equinox/TileSweepLine.h create mode 100644 equinox/src/equinox/Tiles.h create mode 100644 equinox/src/equinox/UnionFind.h create mode 100644 equinox/src/equinox/intervaltree.h.b create mode 100644 equinox/src/equinox/misc.h.b create mode 100644 equinox/src/intervalTree/src/IntervalTree.cpp create mode 100644 equinox/src/intervalTree/src/equinox/Interval.h create mode 100644 equinox/src/intervalTree/src/equinox/IntervalTree.h diff --git a/equinox/CMakeLists.txt b/equinox/CMakeLists.txt new file mode 100644 index 00000000..ab24ad7e --- /dev/null +++ b/equinox/CMakeLists.txt @@ -0,0 +1,26 @@ +PROJECT(EQUINOX) + +CMAKE_MINIMUM_REQUIRED(VERSION 2.4.0) +IF(COMMAND CMAKE_POLICY) + CMAKE_POLICY(SET CMP0003 NEW) +ENDIF(COMMAND CMAKE_POLICY) + +SET(CMAKE_C_FLAGS_DEBUG "-g -Wall" CACHE STRING "Debug options." FORCE) +SET(CMAKE_CXX_FLAGS_DEBUG "-Winline -g -Wall" CACHE STRING "Debug options." FORCE) +SET(CMAKE_LINKER_FLAGS_DEBUG "-Winline -pg" CACHE STRING "Debug options." FORCE) +SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "-Winline -pg" CACHE STRING "Debug options." FORCE) +SET(CMAKE_MODULE_LINKER_FLAGS_DEBUG "-Winline -pg" CACHE STRING "Debug options." FORCE) +SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "-Winline -pg" CACHE STRING "Debug options." FORCE) + +SET(CMAKE_MODULE_PATH "$ENV{HURRICANE_TOP}/share/cmake_modules/") + +SET(QT_USE_QTXML "true") + +FIND_PACKAGE(Qt4 REQUIRED) # find and setup Qt4 for this project +FIND_PACKAGE(HURRICANE REQUIRED) +FIND_PACKAGE(CORIOLIS REQUIRED) + +SET_LIB_LINK_MODE() + +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(cmake_modules) diff --git a/equinox/cmake_modules/CMakeLists.txt b/equinox/cmake_modules/CMakeLists.txt new file mode 100644 index 00000000..3bd7a7ec --- /dev/null +++ b/equinox/cmake_modules/CMakeLists.txt @@ -0,0 +1 @@ +install ( FILES FindEQUINOX.cmake DESTINATION /share/cmake_modules ) diff --git a/equinox/cmake_modules/FINDEquinox.cmake b/equinox/cmake_modules/FINDEquinox.cmake new file mode 100644 index 00000000..33d78484 --- /dev/null +++ b/equinox/cmake_modules/FINDEquinox.cmake @@ -0,0 +1,48 @@ +# - Find the Equinox includes and libraries. +# The following variables are set if Coriolis is found. If EQUINOX is not +# found, EQUINOX_FOUND is set to false. +# EQUINOX_FOUND - True when the Coriolis include directory is found. +# EQUINOX_INCLUDE_DIR - the path to where the Coriolis include files are. +# EQUINOX_LIBRARIES - The path to where the Coriolis library files are. + + +SET(EQUINOX_INCLUDE_PATH_DESCRIPTION "directory containing the Equinox include files. E.g /usr/local/include/coriolis or /asim/coriolis/include/coriolis") + +SET(EQUINOX_DIR_MESSAGE "Set the EQUINOX_INCLUDE_DIR cmake cache entry to the ${EQUINOX_INCLUDE_PATH_DESCRIPTION}") + +# don't even bother under WIN32 +IF(UNIX) + + SET(EQUINOX_DIR_SEARCH $ENV{CORIOLIS_TOP} $ENV{HURRICANE_TOP}) + # + # Look for an installation. + # + FIND_PATH(EQUINOX_INCLUDE_PATH NAMES equinox/Equi.h PATHS + # Look in other places. + ${EQUINOX_DIR_SEARCH} + PATH_SUFFIXES include/coriolis + # Help the user find it if we cannot. + DOC "The ${EQUINOX_INCLUDE_PATH_DESCRIPTION}" + ) + + FIND_LIBRARY(EQUINOX_LIBRARY_PATH + NAMES equinox + PATHS ${EQUINOX_DIR_SEARCH} + PATH_SUFFIXES lib + # Help the user find it if we cannot. + DOC "The ${EQUINOX_INCLUDE_PATH_DESCRIPTION}" + ) + + FIND_LIBRARY(EQUINOX_STATIC_LIBRARY_PATH + NAMES equinox-static + PATHS ${EQUINOX_DIR_SEARCH} + PATH_SUFFIXES lib + # Help the user find it if we cannot. + DOC "The ${EQUINOX_INCLUDE_PATH_DESCRIPTION}" + ) + + SET_LIBRARIES_PATH(EQUINOX EQUINOX) + HURRICANE_CHECK_LIBRARIES(EQUINOX) + +ENDIF(UNIX) + diff --git a/equinox/cmake_modules/FindEQUINOX.cmake b/equinox/cmake_modules/FindEQUINOX.cmake new file mode 100644 index 00000000..f02ead4e --- /dev/null +++ b/equinox/cmake_modules/FindEQUINOX.cmake @@ -0,0 +1,47 @@ +# - Find the Equinox includes and libraries. +# The following variables are set if Coriolis is found. If EQUINOX is not +# found, EQUINOX_FOUND is set to false. +# EQUINOX_FOUND - True when the Coriolis include directory is found. +# EQUINOX_INCLUDE_DIR - the path to where the Coriolis include files are. +# EQUINOX_LIBRARIES - The path to where the Coriolis library files are. + + +SET(EQUINOX_INCLUDE_PATH_DESCRIPTION "directory containing the Equinox include files. E.g /usr/local/include/coriolis or /asim/coriolis/include/coriolis") + +SET(EQUINOX_DIR_MESSAGE "Set the EQUINOX_INCLUDE_DIR cmake cache entry to the ${EQUINOX_INCLUDE_PATH_DESCRIPTION}") + +# don't even bother under WIN32 +IF(UNIX) + + SET(EQUINOX_DIR_SEARCH $ENV{CORIOLIS_TOP} $ENV{HURRICANE_TOP}) + # + # Look for an installation. + # + FIND_PATH(EQUINOX_INCLUDE_PATH NAMES equinox/Equi.h PATHS + # Look in other places. + ${EQUINOX_DIR_SEARCH} + PATH_SUFFIXES include/coriolis + # Help the user find it if we cannot. + DOC "The ${EQUINOX_INCLUDE_PATH_DESCRIPTION}" + ) + + FIND_LIBRARY(EQUINOX_LIBRARY_PATH + NAMES equinox + PATHS ${EQUINOX_DIR_SEARCH} + PATH_SUFFIXES lib + # Help the user find it if we cannot. + DOC "The ${EQUINOX_INCLUDE_PATH_DESCRIPTION}" + ) + + FIND_LIBRARY(EQUINOX_STATIC_LIBRARY_PATH + NAMES equinox-static + PATHS ${EQUINOX_DIR_SEARCH} + PATH_SUFFIXES lib + # Help the user find it if we cannot. + DOC "The ${EQUINOX_INCLUDE_PATH_DESCRIPTION}" + ) + + SET_LIBRARIES_PATH(EQUINOX EQUINOX) + HURRICANE_CHECK_LIBRARIES(EQUINOX) + +ENDIF(UNIX) diff --git a/equinox/src/CMakeLists.txt b/equinox/src/CMakeLists.txt new file mode 100644 index 00000000..fb4aac51 --- /dev/null +++ b/equinox/src/CMakeLists.txt @@ -0,0 +1,55 @@ + + include ( ${QT_USE_FILE} ) + + include_directories ( ${EQUINOX_SOURCE_DIR}/src + ${EQUINOX_SOURCE_DIR}/src/intervalTree/src + ${HURRICANE_INCLUDE_DIR} + ${CORIOLIS_INCLUDE_DIR} + ) + + + set ( includes equinox/EquinoxFilters.h + equinox/EquinoxCollections.h + equinox/Equi.h equinox/Equis.h + equinox/EquinoxEngine.h + equinox/Strategy.h + equinox/Tile.h equinox/Tiles.h + equinox/UnionFind.h + equinox/SweepLine.h equinox/TileSweepLine.h + ) + set ( mocIncludes equinox/GraphicEquinoxEngine.h ) + + set ( cpps EquinoxFilters.cpp + EquinoxCollections.cpp + Equi.cpp + TileSweepLine.cpp + Tile.cpp + Strategy.cpp + EquinoxEngine.cpp + UnionFind.cpp + GraphicEquinoxEngine.cpp + ) + + set ( intervalTreeIncludes intervalTree/src/equinox/Interval.h + intervalTree/src/equinox/IntervalTree.h ) + set ( intervalTreeCpps intervalTree/src/IntervalTree.cpp ) + qt4_wrap_cpp ( mocCpps ${mocIncludes} ) + + add_library ( equinox ${cpps} ${mocCpps} ) + target_link_libraries ( equinox intervalTree + ${CORIOLIS_LIBRARIES} + ${HURRICANE_LIBRARIES} + ${HURRICANE_GRAPHICAL_LIBRARIES} + ${QT_LIBRARIES} + ${LEFDEF_LIBRARIES} + ${OA_LIBRARIES} + ) + add_library (intervalTree ${intervalTreeCpps} ) + target_link_libraries (intervalTree ${CORIOLIS_LIBRARIES} + ${HURRICANE_LIBRARIES} ) + install ( TARGETS equinox intervalTree DESTINATION /lib) + install ( FILES ${includes} + ${mocIncludes} + ${intervalTreeIncludes} DESTINATION /include/coriolis/equinox ) + + diff --git a/equinox/src/Equi.cpp b/equinox/src/Equi.cpp new file mode 100644 index 00000000..eb5d594d --- /dev/null +++ b/equinox/src/Equi.cpp @@ -0,0 +1,186 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./Equi.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include + +using namespace std; + + +#include "hurricane/Box.h" +#include "hurricane/Cell.h" +#include "hurricane/Component.h" +#include "hurricane/Occurrence.h" +#include "hurricane/Collection.h" +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Entity.h" +#include "hurricane/Filter.h" +#include "hurricane/Net.h" +#include "hurricane/Commons.h" +#include "hurricane/Error.h" +#include "hurricane/Relation.h" +#include "hurricane/Locator.h" + +#include "crlcore/Utilities.h" +#include "crlcore/ToolEngine.h" + +#include "equinox/Tile.h" +#include "equinox/Equi.h" +#include "equinox/Strategy.h" +#include "equinox/EquinoxEngine.h" +#include "equinox/EquinoxFilters.h" +#include "equinox/EquinoxCollections.h" + + +namespace Equinox { + + using namespace Hurricane; + + +// ------------------------------------------------------------------- +// Class : "Equinox::Equi". + + map Equi::_map_net2nb_usefulcomponent; + + + + void Equi::_preDestroy() + { + if(_nextequi) _nextequi->decrementCount(); + _equinox->removeEqui(this); + Entity::_preDestroy(); + } + + void Equi::factorizeComponents() + { + + // get all components to netmap (net2Component) + map > netmap; + forEach(Occurrence,occurrence,getComponentOccurrences()) { + netmap[( dynamic_cast((*occurrence).getEntity()))->getNet()].insert((*occurrence)); + } + + for ( map >::iterator i = netmap.begin(); + i != netmap.end(); + i++ ) + { + Net * net = (*i).first; + + + //process nb_component and map_net2nb_usefulcomponent[net] + unsigned long nb_component = 0; + map::iterator end = _map_net2nb_usefulcomponent.end(); + if(_map_net2nb_usefulcomponent.find(net)==end) { /* haven't been calculed */ + nb_component = net->getComponents().getSubSet(IsUsedByExtractFilter()).getSize(); + _map_net2nb_usefulcomponent[net] = nb_component; + } + else { + nb_component = _map_net2nb_usefulcomponent[net] ; + } + + if( (*i).second.size() == nb_component ){ + forEach (Occurrence,occurrence,getCollection((*i).second)) _occurrences.erase((*occurrence)); + _occurrences.insert(Occurrence(net)); + } + } + } + + + void Equi::_postCreate() + { + Entity::_postCreate(); + _equinox->addEqui(this); + } + + + string Equi::_getString() const + { + return ""; + } + + + Equi::Equi(EquinoxEngine* equinox, Equi* nextequi, const unsigned long& number) + : Entity() + , _equinox(equinox) + , _occurrences() + , _nextequi(nextequi) + , _count(0) + , _number(number) + { + if(!equinox){ + throw Error("Can't create Equi: equinox is null"); + } + } + + + + + Equi * Equi::create(EquinoxEngine* equinox, Equi* nextequi, const unsigned long& number) + { + Equi * equi = new Equi(equinox, nextequi, number); + if(!equi) { + throw Error("can't create Equi : allocation error"); + } + equi->_postCreate(); + return equi; + } + + + + Cell* Equi::getCell() const + { + return _equinox->getCell(); + } + + + + // filters + + GenericFilter Equi::getIsEquiFilter (){ return IsEquiFilter();} + GenericFilter Equi::getIsComponentFilter (){ return IsComponentFilter();} + GenericFilter Equi::getIsNetFilter (){ return IsNetFilter();} + GenericFilter Equi::getIsLeafEquiFilter (){ return IsLeafEquiFilter(); } + GenericFilter Equi::getIsNotLeafEquiFilter (){ return !IsLeafEquiFilter(); } + // GenericFilter Equi::getIsUsedByExtractFilter (){ return IsUsedByExtractFilter();} + GenericFilter Equi::getIsNetOrComponentFilter (){ return IsNetOrComponentFilter();} + + Occurrences Equi::getAllOccurrences () const { return AllOccurrencesCollection(this);} + + Occurrences Equi::getEquiOccurrences () const { return getOccurrences().getSubSet(IsEquiFilter());}; + Occurrences Equi::getComponentOccurrences () const { return getOccurrences().getSubSet(IsComponentFilter());}; + Occurrences Equi::getNetOccurrences () const { return getOccurrences().getSubSet(IsNetFilter());}; + Occurrences Equi::getNetAndComponentOccurrences () const { return getOccurrences().getSubSet(IsNetOrComponentFilter());}; + + Occurrences Equi::getEquiComponentOccurrences () const { return EquiComponentOccurrencesCollection(this);}; + Occurrences Equi::getCurrentComponentOccurrences () const { return CurrentComponentOccurrencesCollection(this); }; + + bool Equi::isLeafEqui () const { GenericLocator l = getEquiOccurrences().getLocator(); return !(l.isValid());}; + bool Equi::hasNetOccurrence () const { GenericLocator l = getNetOccurrences().getLocator(); return (l.isValid());}; + bool Equi::hasComponentOccurrence () const { GenericLocator l = getComponentOccurrences().getLocator(); return (l.isValid());}; + +}// End of namespace Equinox diff --git a/equinox/src/EquinoxCollections.cpp b/equinox/src/EquinoxCollections.cpp new file mode 100644 index 00000000..7127b9ef --- /dev/null +++ b/equinox/src/EquinoxCollections.cpp @@ -0,0 +1,721 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./EquinoxCollections.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + +/******************************************************************** +* This file contains : * +* - See "./equinox/EquinoxCollections.h" * +********************************************************************/ + + +#include +#include +#include +#include + +#include +#include +#include + + + +namespace Equinox { + + + AllOccurrencesCollection::AllOccurrencesCollection() + // *************************************************** + : Inherit() + , _equi(NULL) + { + } + + + AllOccurrencesCollection::AllOccurrencesCollection(const Equi* equi) + // ****************************************************************** + : Inherit() + , _equi(equi) + { + } + + + AllOccurrencesCollection::AllOccurrencesCollection(const AllOccurrencesCollection& occurrences) + // *********************************************************************************************** + : Inherit() + , _equi(occurrences._equi) + { + } + + + AllOccurrencesCollection& AllOccurrencesCollection::operator=(const AllOccurrencesCollection& occurrences) + // ********************************************************************************************************** + { + _equi = occurrences._equi; + return *this; + } + + + Collection * AllOccurrencesCollection::getClone() const + // ***************************************************************** + { + return new AllOccurrencesCollection(*this); + } + + + Locator* AllOccurrencesCollection::getLocator() const + // *************************************************************** + { + return new Locator(_equi); + } + + + string AllOccurrencesCollection::_getString() const + // ************************************************* + { + string s = "getNetAndComponentOccurrences().getLocator(); + + if(_componentLocator.isValid()) + _state = 1; + else { + _equioccurrenceLocator = _equi->getEquiOccurrences().getLocator(); + + while(!_state && _equioccurrenceLocator.isValid()) { + Equi * equi = dynamic_cast(_equioccurrenceLocator.getElement().getEntity()); + _occurrenceLocator = equi->getAllOccurrences().getLocator(); + if(_occurrenceLocator.isValid()) + _state = 2; + else + _equioccurrenceLocator.progress(); + } + } + } + } + + + AllOccurrencesCollection::Locator::Locator(const Locator& locator) + // **************************************************************** + : Inherit() + ,_equi(locator._equi) + ,_state(locator._state) + ,_componentLocator(locator._componentLocator) + ,_equioccurrenceLocator(locator._equioccurrenceLocator) + ,_occurrenceLocator(locator._occurrenceLocator) + { + } + + + AllOccurrencesCollection::Locator& AllOccurrencesCollection::Locator::operator=(const Locator& locator) + // ***************************************************************************************************** + { + _equi = locator._equi; + _state = locator._state; + _componentLocator = locator._componentLocator; + _equioccurrenceLocator = locator._equioccurrenceLocator; + _occurrenceLocator = locator._occurrenceLocator; + return *this; + } + + + Occurrence AllOccurrencesCollection::Locator::getElement() const + // ************************************************************** + { + if(_state) { // If locator is valid + switch(_state) { + case 1 : return Occurrence(_componentLocator.getElement()); + + case 2 : { + Occurrence occurrence = _occurrenceLocator.getElement(); + + Entity* entity = occurrence.getEntity(); + Path path = Path(_equioccurrenceLocator.getElement().getPath().getHeadInstance() , occurrence.getPath()); + + return Occurrence(entity, path); + } + } + } + return Occurrence(); + } + + + Locator * AllOccurrencesCollection::Locator::getClone() const + // *********************************************************************** + { + return new Locator(*this); + } + + + bool AllOccurrencesCollection::Locator::isValid() const + // ***************************************************** + { + return (_state!=0); + } + + void AllOccurrencesCollection::Locator::progress() + // ************************************************* + { + if(_state) { + switch(_state) { + case 1 : + _componentLocator.progress(); + if(!_componentLocator.isValid()) { + _state = 0; + _equioccurrenceLocator = _equi-> getEquiOccurrences().getLocator(); + + while(!_state && _equioccurrenceLocator.isValid()) { + Equi* equi = dynamic_cast(_equioccurrenceLocator.getElement().getEntity()); + _occurrenceLocator = equi->getAllOccurrences().getLocator(); + if(_occurrenceLocator.isValid()) + _state = 2; + else + _equioccurrenceLocator.progress(); + } + } + break; + + case 2 : + _occurrenceLocator.progress(); + if(!_occurrenceLocator.isValid()) { + _state = 0; + if(_equioccurrenceLocator.isValid()) { + _equioccurrenceLocator.progress(); + + while(!_state && _equioccurrenceLocator.isValid()) { + Equi* equi = dynamic_cast(_equioccurrenceLocator.getElement().getEntity()); + _occurrenceLocator = equi->getAllOccurrences().getLocator(); + if(_occurrenceLocator.isValid()) + _state = 2; + else + _equioccurrenceLocator.progress(); + + } + } + } + break; + } + } + } + + + string AllOccurrencesCollection::Locator::_getString() const + // ********************************************************** + { + string s =" * EquiComponentOccurrencesCollection::getClone() const + // ***************************************************************** + { + return new EquiComponentOccurrencesCollection(*this); + } + + + Locator* EquiComponentOccurrencesCollection::getLocator() const + // *************************************************************** + { + return new Locator(_equi); + } + + + string EquiComponentOccurrencesCollection::_getString() const + // ************************************************* + { + string s = "getCurrentComponentOccurrences().getLocator(); + + if(_componentLocator.isValid()) + _state = 1; + else { + _equioccurrenceLocator = _equi->getEquiOccurrences().getLocator(); + + while(!_state && _equioccurrenceLocator.isValid()) { + Equi * equi = dynamic_cast(_equioccurrenceLocator.getElement().getEntity()); + _occurrenceLocator = equi->getEquiComponentOccurrences().getLocator(); + if(_occurrenceLocator.isValid()) + _state = 2; + else + _equioccurrenceLocator.progress(); + } + } + } + } + + + EquiComponentOccurrencesCollection::Locator::Locator(const Locator& locator) + // **************************************************************** + : Inherit() + ,_equi(locator._equi) + ,_state(locator._state) + ,_componentLocator(locator._componentLocator) + ,_equioccurrenceLocator(locator._equioccurrenceLocator) + ,_occurrenceLocator(locator._occurrenceLocator) + { + } + + + EquiComponentOccurrencesCollection::Locator& EquiComponentOccurrencesCollection::Locator::operator=(const Locator& locator) + // ***************************************************************************************************** + { + _equi = locator._equi; + _state = locator._state; + _componentLocator = locator._componentLocator; + _equioccurrenceLocator = locator._equioccurrenceLocator; + _occurrenceLocator = locator._occurrenceLocator; + return *this; + } + + + Occurrence EquiComponentOccurrencesCollection::Locator::getElement() const + // ************************************************************** + { + if(_state) { // If locator is valid + switch(_state) { + case 1 : return Occurrence(_componentLocator.getElement()); + + case 2 : { + Occurrence occurrence = _occurrenceLocator.getElement(); + + Entity* entity = occurrence.getEntity(); + Path path = Path(_equioccurrenceLocator.getElement().getPath().getHeadInstance() , occurrence.getPath()); + + return Occurrence(entity, path); + } + } + } + return Occurrence(); + } + + + Locator * EquiComponentOccurrencesCollection::Locator::getClone() const + // *********************************************************************** + { + return new Locator(*this); + } + + + bool EquiComponentOccurrencesCollection::Locator::isValid() const + // ***************************************************** + { + return (_state!=0); + } + + void EquiComponentOccurrencesCollection::Locator::progress() + // ************************************************* + { + if(_state) { + switch(_state) { + case 1 : + _componentLocator.progress(); + if(!_componentLocator.isValid()) { + _state = 0; + _equioccurrenceLocator = _equi-> getEquiOccurrences().getLocator(); + + while(!_state && _equioccurrenceLocator.isValid()) { + Equi* equi = dynamic_cast(_equioccurrenceLocator.getElement().getEntity()); + _occurrenceLocator = equi->getEquiComponentOccurrences().getLocator(); + if(_occurrenceLocator.isValid()) + _state = 2; + else + _equioccurrenceLocator.progress(); + } + } + break; + + case 2 : + _occurrenceLocator.progress(); + if(!_occurrenceLocator.isValid()) { + _state = 0; + if(_equioccurrenceLocator.isValid()) { + _equioccurrenceLocator.progress(); + + while(!_state && _equioccurrenceLocator.isValid()) { + Equi* equi = dynamic_cast(_equioccurrenceLocator.getElement().getEntity()); + _occurrenceLocator = equi->getEquiComponentOccurrences().getLocator(); + if(_occurrenceLocator.isValid()) + _state = 2; + else + _equioccurrenceLocator.progress(); + + } + } + } + break; + } + } + } + + + string EquiComponentOccurrencesCollection::Locator::_getString() const + // ********************************************************** + { + string s =" * CurrentComponentOccurrencesCollection::getClone() const + // ***************************************************************** + { + return new CurrentComponentOccurrencesCollection(*this); + } + + + Locator* CurrentComponentOccurrencesCollection::getLocator() const + // *************************************************************** + { + return new Locator(_equi); + } + + + string CurrentComponentOccurrencesCollection::_getString() const + // ************************************************* + { + string s = "getComponentOccurrences().getLocator(); + if( _componentLocator.isValid() ) { + _state = 1; + } + else + { + _netoccurrenceLocator = _equi->getNetOccurrences().getLocator(); + while(!_state && _netoccurrenceLocator.isValid()) { + Net * net = dynamic_cast(_netoccurrenceLocator.getElement().getEntity()); + _occurrenceLocator = net->getComponents().getSubSet(NetIsUsedByExtractorFilter()).getLocator(); + + if(_occurrenceLocator.isValid()) + _state = 2; + else + _netoccurrenceLocator.progress(); + } + } + } + } + + + + CurrentComponentOccurrencesCollection::Locator::Locator(const Locator& locator) + // **************************************************************** + : Inherit() + ,_equi(locator._equi) + ,_state(locator._state) + ,_componentLocator(locator._componentLocator) + ,_netoccurrenceLocator(locator._netoccurrenceLocator) + ,_occurrenceLocator(locator._occurrenceLocator) + { + } + + + CurrentComponentOccurrencesCollection::Locator& CurrentComponentOccurrencesCollection::Locator::operator=(const Locator& locator) + // ***************************************************************************************************** + { + _equi = locator._equi; + _state = locator._state; + _componentLocator = locator._componentLocator; + _netoccurrenceLocator = locator._netoccurrenceLocator; + _occurrenceLocator = locator._occurrenceLocator; + return *this; + } + + + Occurrence CurrentComponentOccurrencesCollection::Locator::getElement() const + // ************************************************************** + { + if(_state){ // If Locator is Valid + switch(_state) { + case 1 : return _componentLocator.getElement(); + + case 2 : { + return Occurrence( _occurrenceLocator.getElement(), Path() ); + } + } + } + return Occurrence(); + } + + + Locator * CurrentComponentOccurrencesCollection::Locator::getClone() const + // *********************************************************************** + { + return new Locator(*this); + } + + + bool CurrentComponentOccurrencesCollection::Locator::isValid() const + // ***************************************************** + { + return (_state!=0); + } + + void CurrentComponentOccurrencesCollection::Locator::progress() + // ************************************************* + { + + if(_state) { // If locator is Valid + switch(_state) { + case 1 : { + _componentLocator.progress(); + if(!_componentLocator.isValid()) { + _state = 0; + _netoccurrenceLocator = _equi->getNetOccurrences().getLocator(); + while(!_state && _netoccurrenceLocator.isValid()) { + Net * net = dynamic_cast(_netoccurrenceLocator.getElement().getEntity()); + + //_occurrenceLocator = net->GetComponents().GetLocator(); + _occurrenceLocator = net->getComponents().getSubSet(NetIsUsedByExtractorFilter()).getLocator(); + if(_occurrenceLocator.isValid()) + _state = 2; + else + _netoccurrenceLocator.progress(); + } + } + break; + } + + case 2 : { + _occurrenceLocator.progress(); + if(!_occurrenceLocator.isValid()) { + _state = 0; + if (_netoccurrenceLocator.isValid()) { + _netoccurrenceLocator.progress(); + + while(!_state && _netoccurrenceLocator.isValid()) { + Net * net = dynamic_cast(_netoccurrenceLocator.getElement().getEntity()); + //_occurrenceLocator = net->GetComponents().GetLocator(); + _occurrenceLocator = net->getComponents().getSubSet(NetIsUsedByExtractorFilter()).getLocator(); + + if(_occurrenceLocator.isValid()) + _state = 2; + else + _netoccurrenceLocator.progress(); + } + } + } + break; + } + } + } + } + + + string CurrentComponentOccurrencesCollection::Locator::_getString() const + // ********************************************************** + { + string s =" +#include + + +#include "hurricane/Path.h" +#include "hurricane/Net.h" +#include "hurricane/Name.h" +#include "hurricane/Entity.h" +#include "hurricane/Error.h" +#include "hurricane/Collection.h" +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Cell.h" +#include "hurricane/Occurrences.h" +#include "hurricane/Box.h" +#include "hurricane/Instance.h" +#include "hurricane/Components.h" + +#include "crlcore/ToolEngine.h" +#include "crlcore/Utilities.h" + +#include "equinox/EquinoxFilters.h" +#include "equinox/Equis.h" +#include "equinox/Equi.h" +#include "equinox/Tile.h" +#include "equinox/Tiles.h" +#include "equinox/Strategy.h" +#include "equinox/UnionFind.h" +#include "equinox/EquinoxEngine.h" +#include "equinox/TileSweepLine.h" + + +namespace Equinox { + + + using namespace std; + using namespace Hurricane; + + + + + // ------------------------------------------------------------------- + // Class : "Equinox::EquinoxEngine". + + /**/ Name EquinoxEngine::_toolName = "Equinox"; + /**/ Strategy * EquinoxEngine::_strategy = NULL; + + + + + EquinoxEngine* EquinoxEngine::create (Cell* cell) + { + EquinoxEngine* equinox = new EquinoxEngine ( cell ); + + if(!equinox){ + throw Error("can't create Equinox : allocation failed"); + } + + equinox->_postCreate (); + return equinox; + } + + + + /**/ void EquinoxEngine::removeEquis () + { + set::iterator i; + + while(!_equis.empty()) { + i = _equis.begin(); + (*i)->destroy(); // Delete also addresse of objet Equi from current Equinox + } + _occurrences.clear(); // Clear also map + } + + + Strategy* EquinoxEngine::getStrategy () + { + if (!_strategy) { + _strategy = new DefaultStrategy(); + } + + return _strategy; + } + + +void EquinoxEngine::withAlimExtract(unsigned int nbwindows) +// ************************************************** +{ + setStrategy(new WithAlimStrategy()); + /*DEBUG*/ cmess1 << " o extract " << endl; + extract(nbwindows); + /*DEBUG*/ cmess1 << " o printEqui " << endl; + printEquis(); + /*DEBUG*/ cmess1 << " o Fin " << endl; +} + + + +void EquinoxEngine::withoutAlimExtract(unsigned int nbwindows) +// ************************************************** +{ + setStrategy(new WithoutAlimStrategy()); + /*DEBUG*/ cmess1 << " o extract " << endl; + extract(nbwindows); + /*DEBUG*/ cmess1 << " o printEqui " << endl; + printEquis(); + /*DEBUG*/ cmess1 << " o Fin " << endl; +} + + void EquinoxEngine::extract(unsigned int nbwindows) + { + + // Test for parameter + // ****************** + if(!getStrategy()) + throw Error("Can't start extraction without mode, the current mode is null"); + + if( nbwindows >256 || nbwindows < 1 ) { + throw Error("Can't start extraction : the nbwindows " + getString(nbwindows) + " is not valid"); + } + + // Clean Equis + // *********** + if(isExtracted()) { + flushEquis(_cell); + } + + // Start extraction. + // ***************** + getStrategy()->run(this, nbwindows); + + } + + + Record* EquinoxEngine::_getRecord () const + { + Record* record = ToolEngine::_getRecord (); + record->add ( getSlot ( "_isExtracted" , _isExtracted ) ); + record->add ( getSlot ( "_equis" , _equis ) ); + record->add ( getSlot ( "_occurrences" , _occurrences ) ); + return ( record ); + } + + + string EquinoxEngine::_getString () const + { + ostringstream os; + + os << "<" << "Equinox " << _cell->getName () << ">"; + + return ( os.str() ); + } + + string EquinoxEngine::_getTypeName () const { return "Equinox"; } + + + + + Equi* EquinoxEngine::getEquiByOccurrence(Occurrence occurrence) + // ********************************************* + { + map::iterator i = _occurrences.end(); + if( _occurrences.find(occurrence) == i) { + Component * component = dynamic_cast(occurrence.getEntity()); + + if( component && occurrence.getPath().isEmpty() ) + { + // If this is a component , maybe it has been factorized, after extraction. + // ************************************************************************* + if( _occurrences.find( Occurrence(component->getNet()) ) != i ) + return _occurrences[Occurrence(component->getNet())]; + } + return NULL; + } + else + return _occurrences[occurrence]; + }; + + + +Occurrence EquinoxEngine::getEquiOccurrence(Occurrence occurrence) + // *********************************************** + { + map::iterator i = _occurrences.end(); + if( _occurrences.find(occurrence) == i ) { + Component* component = dynamic_cast(occurrence.getEntity()); + if( component && occurrence.getPath().isEmpty() ) { // If this is a component, maybe it has been factorized. + if( _occurrences.find( Occurrence(component->getNet()) ) != i ) + return Occurrence(static_cast(_occurrences[Occurrence(component->getNet())])); + } + return Occurrence(); + } + else + return Occurrence(static_cast(_occurrences[occurrence])); + }; + Occurrence EquinoxEngine::getUpperEquiOccurrence(Occurrence occurrence) + // ***************************************************** + { + Path path = occurrence.getPath(); + Equi * equi = NULL; + occurrence = Occurrence(occurrence.getEntity()); + while(1) { + if(!path.isEmpty()) + equi = get(path.getMasterCell())->getEquiByOccurrence(occurrence); + else + equi = this->getEquiByOccurrence(occurrence); + + if(!equi) return occurrence; + occurrence = Occurrence(equi, Path(path.getTailInstance())); + path=path.getHeadPath(); + } + return Occurrence(); + }; + + + + void EquinoxEngine::setIsExtracted (const bool flag) + { + _isExtracted= flag; + }; + + + + + + void EquinoxEngine::selectWindowsSize () + { + Box cellbox = _cell->getBoundingBox(); + long cellwidth = cellbox.getWidth(); + if ( cellwidth < 50000 ){ _nbWindows = 1; } + else if( cellwidth < 100000 ){ _nbWindows = 2; } + else { _nbWindows = cellwidth / 50000; } + if (_nbWindows > 256) _nbWindows = 256; + _nbWindows=20; + ///*DEBUG*/ cmess1 << " o selectWindowsSize : _nbWindows = " << _nbWindows << endl ; + + } + + void EquinoxEngine::initTiles () + { + + getStrategy()->getTilesFor(this); + + } + + void EquinoxEngine::postSweepLine () + { + getStrategy()->operationAfterScanLine(this); + } + + + + void EquinoxEngine::scan (unsigned int nbwindows) + { + /*DEBUG*/ cmess1 << " o EquinoxEngine::scan " << getString(_cell) << endl; + + TileSweepLine* sweepLine = TileSweepLine::create(this,getStrategy()); + + // Step 2 - Select Windows Size + // **************************** + /*DEBUG*/ cmess1 << " - Step 2 - Select Windows Size" << endl; + selectWindowsSize(); + + // Main algorithme + // *************** + for(_cWindows=0; _cWindows<_nbWindows; _cWindows++) { + + // Step 3 - Init tiles vector + // ************************** + /*DEBUG*/ cmess1 << " - Step 3 - Init tiles vector " << flush; + initTiles(); + + // Step 4 - Run Sweep Line + // *********************** + /*DEBUG*/ cmess1 << _tilesByXmin->size() <<" Tiles and SweepLine " << _cWindows << " sur " << _nbWindows << endl; + sweepLine->run( + _tilesByXmin, + _tilesByXmax, + _cWindows < _nbWindows-1, + ((_cell->getBoundingBox().getXMin ()+(_cWindows+1)*_cell->getBoundingBox().getWidth()/_nbWindows)) ); + + } // end for + + // Step 5 - Post Sweep Line + // *********************** + /*DEBUG*/ cmess1 << " - Step 4 - PostSweepLine" << endl; + postSweepLine(); + + // Step 6 - Clean SweepLine + // ************************* + sweepLine->destroy(); + } + + +void EquinoxEngine::getOccurrencesOfEquis() +// ******************************************* +{ + unsigned long count = 0; + forEach (Equi*,equi,getCollection(_equis)) + { + // Factoriser occurrences of equi + (*equi)->factorizeComponents(); + + forEach(Occurrence,occurrence,((*equi)->getOccurrences())) + _occurrences[(*occurrence)] = *equi; + (*equi)->setNumber(++count); + } +} + + +void EquinoxEngine::cleanUpLeafCell() +// ************************************* +{ + + ///*DEBUG*/ cmess1 << " - cleanUpLeafCell() " << endl; + set set_nets; + Net * externalnet = NULL; + unsigned long count = 1; + Occurrence o; + + forEach(Equi*,equi,getCollection(_equis)) + { + + externalnet = NULL; + forEach( Occurrence,occurrence, (*equi)->getComponentOccurrences()) + { + Net * net = dynamic_cast((*occurrence).getEntity())->getNet(); + + + // check for 2 externals nets on the same Equi + if(net->isExternal()) { + if(externalnet && (externalnet != net) ) + throw Error("There is two external net in leaf cell : Library Error " + getString(externalnet) + + " " + getString(net) + " with component " + + getString((*occurrence)) + " " + getString(o)); + + if(!externalnet) { + o = (*occurrence); + externalnet = net; + } + } + + set_nets.insert(net); + } + + // If there is no externalNet, choice the first + if(!externalnet) externalnet = (*set_nets.begin()); + + + + forEach(Net*,net, getCollection(set_nets)) + { + if( (*net)!= externalnet) { + externalnet->merge(*net); + } + } + + _occurrences[Occurrence(externalnet)] = *equi; // Add to map _occurrences. + (*equi)->erase(); // Clean all component occurrences + (*equi)->addOccurrence(Occurrence(externalnet));// Add net occurrence + + + + set_nets.clear(); + (*equi)->setNumber(count++); + + } + +} + + + + EquinoxEngine::EquinoxEngine ( Cell* cell ) + : ToolEngine (cell) + , _cWindows(0) + , _nbWindows(0) + , _isExtracted(false) + , _tilesByXmin() + , _tilesByXmax() + { } + + + + + void EquinoxEngine::flushEquis (Cell*cell) { + if(!_isExtracted) // If the top cell hasn't been extracted. + return ; + + InstanceLocator instancelocator = cell->getInstances().getLocator(); + + if(instancelocator.isValid()){ // If the cell isn't a leaf cell. + EquinoxEngine * equinox = NULL; + Cell * mastercell = NULL; + + while(instancelocator.isValid()) { + mastercell = instancelocator.getElement()->getMasterCell(); + equinox = get(mastercell); + + if(equinox && (equinox->isExtracted())) // If the sous-cell has been extracted. + flushEquis(mastercell); + + instancelocator.progress(); + } + } + + EquinoxEngine * equinox = get(cell); + equinox->removeEquis(); + equinox->setIsExtracted(false); + } + + + EquinoxEngine::~EquinoxEngine () + { + } + + + + + + void EquinoxEngine::_postCreate () + { + ToolEngine::_postCreate (); + _tilesByXmin = new TileVector(); + _tilesByXmax = new TileVector(); + } + + + + + + void EquinoxEngine::_preDestroy () + { + ToolEngine::_preDestroy (); + removeEquis(); + } + + + void EquinoxEngine::_destroy () + { + _preDestroy(); + _depthDestroy(); + delete this; + } + + +void EquinoxEngine::_depthDestroy() +// ************************** +{ + GenericLocator locator = _cell->getInstances().getLocator(); + EquinoxEngine * equinox = NULL; + + if( !(locator.isValid()) ) { + this->destroy(); + } + else { + while(locator.isValid()) { + Cell * cell = locator.getElement()->getMasterCell(); + equinox = get(cell); + + if(equinox) + equinox->_depthDestroy(); + + locator.progress(); + } + this->destroy(); + } +} + + + + void EquinoxEngine::printEquis() + { + cmess1 << "Nombre d'equis"<< _equis.size() <_getString() << endl; +/*DEBUG*/// forEach(Occurrence,occurrence,((*equi)->getOccurrences())) +/*DEBUG*/// { +/*DEBUG*/// +/*DEBUG*/// //NET Occurrence +/*DEBUG*/// if (dynamic_cast((*occurrence).getEntity())) +/*DEBUG*/// { +/*DEBUG*/// cmess1 << " - [NET]" << (*occurrence).getEntity() << " \t===>\t " << getHyperNetRootNetOccurrence((*occurrence).getEntity())._getString() << endl; +/*DEBUG*/// } +/*DEBUG*/// +/*DEBUG*/// //COMPONENT Occurrence +/*DEBUG*/// if (dynamic_cast((*occurrence).getEntity())) { +/*DEBUG*/// Component* composant = dynamic_cast((*occurrence).getEntity()); +/*DEBUG*/// cmess1 << " - [COM]" << composant << " \t===>\t " << getHyperNetRootNetOccurrence(composant->getNet())._getString() << endl; +/*DEBUG*/// } +/*DEBUG*/// +/*DEBUG*/// //EQUI Occurrence +/*DEBUG*/// if (dynamic_cast((*occurrence).getEntity())) { +/*DEBUG*/// Equi* equi = dynamic_cast((*occurrence).getEntity()); +/*DEBUG*/// cmess1 << " - [EQU]" << equi << endl; +/*DEBUG*/// } +/*DEBUG*/// } +/*DEBUG*/// } + } + + void EquinoxEngine::removeInterval(Tile* item) + { + + // on diminue le compteur de reference de l'Equi + item->getEqui()->decrementCount(); + + + + // on detruit le tile + item->destroy(); + + } + + void EquinoxEngine::insertInterval(Tile* newtile,stack *enumResultStack) + { + //Application des contacts + Equi * newroot = NULL; + if( !(enumResultStack->empty()) ) { // contact > 0 + if( newtile->getEqui() ) enumResultStack->push(newtile); + newroot = UnionFind::getRootEquiWithCompression(dynamic_cast(enumResultStack->top()) ); + enumResultStack->pop(); + while (!enumResultStack->empty()) {//while contact > 0 + Equi * root = UnionFind::getRootEquiWithCompression(dynamic_cast(enumResultStack->top()) ); + enumResultStack->pop(); + if( root != newroot ) { + root->setNextEqui(newroot); + newroot->merge(root); + newroot->incrementCount(); + } + } + if(newtile->getEqui() == NULL){ + newtile->setEqui(newroot); + newroot->incrementCount(); + newroot->addOccurrence(newtile->getOccurrence()); + } + } + else { // contact == 0 + if( newtile->getEqui() == NULL) { + newroot = Equi::create(this); + newroot->incrementCount(); + newtile->setEqui(newroot); + newroot->addOccurrence(newtile->getOccurrence()); + } + } + + } + + + +}// End of namespace Equinox diff --git a/equinox/src/EquinoxFilters.cpp b/equinox/src/EquinoxFilters.cpp new file mode 100644 index 00000000..fae00527 --- /dev/null +++ b/equinox/src/EquinoxFilters.cpp @@ -0,0 +1,240 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | =============================================================== | +// | C++ Header : "./EquinoxFilters.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include "hurricane/Components.h" + +#include "hurricane/Component.h" +#include "hurricane/Filter.h" +#include "hurricane/Collection.h" +#include "hurricane/Occurrence.h" +#include "hurricane/BasicLayer.h" +#include "hurricane/Net.h" +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Cell.h" +#include "equinox/EquinoxFilters.h" +#include "equinox/Equi.h" +#include "equinox/Strategy.h" + + +namespace Equinox { + + using Hurricane::GenericCollection; + using Hurricane::GenericLocator; + using Hurricane::GenericFilter; + using Hurricane::Filter; + using Hurricane::Occurrence; + using Hurricane::Component; + using Hurricane::Net; + + + using namespace Hurricane; + + + + + + + + // ------------------------------------------------------------------- + // Class : "Equinox::IsRoutingEquiFilter". + + /**/ IsRoutingFilter::IsRoutingFilter () {}; + /**/ IsRoutingFilter::IsRoutingFilter (const IsRoutingFilter&) {}; + IsRoutingFilter& IsRoutingFilter::operator= (const IsRoutingFilter&) {return *this; }; + Filter* IsRoutingFilter::getClone () const {return new IsRoutingFilter(*this); }; + string IsRoutingFilter::_getString () const {return ""; }; + bool IsRoutingFilter::accept (Equi* item) const + { + if(item->isLeafEqui()) { + if( item->getCell()->isLeaf() ) { + OccurrenceLocator locator = item->getNetOccurrences().getLocator(); + Net * net = dynamic_cast(locator.getElement().getEntity()); + if(!(net->isExternal())) + return false; + } + } + else + { + if( !(item->hasNetOccurrence() || item->hasComponentOccurrence()) ) + if( item->getEquiOccurrences().getSize() == 1 ) { + OccurrenceLocator locator = item->getEquiOccurrences().getLocator(); + Equi * subequi = dynamic_cast(locator.getElement().getEntity()); + return accept(subequi); + } + } + + return true; + }; + + + // ------------------------------------------------------------------- + // Class : "Equinox::IsUsedByExtractFilter". + + /**/ IsUsedByExtractFilter::IsUsedByExtractFilter () {}; + /**/ IsUsedByExtractFilter::IsUsedByExtractFilter (const IsUsedByExtractFilter&) {}; + IsUsedByExtractFilter& IsUsedByExtractFilter::operator= (const IsUsedByExtractFilter&) {return *this; }; + Filter* IsUsedByExtractFilter::getClone () const {return new IsUsedByExtractFilter(*this); }; + string IsUsedByExtractFilter::_getString () const {return ""; }; + + bool IsUsedByExtractFilter::accept (Component* item) const + { + + + Box box = item->getBoundingBox(); + + if( (box.getYMin() == box.getYMax()) || (box.getXMin() == box.getXMax()) ) + return false; + + forEach ( BasicLayer*, i, item->getLayer()->getBasicLayers() ) + { + if ( Strategy::isExtractableLayer(*i)) return true; + } + return false; + + }; + + + + + + + + + + + + + + /**/ IsEquiFilter::IsEquiFilter () {}; + /**/ IsEquiFilter::IsEquiFilter (const IsEquiFilter&) {}; + IsEquiFilter& IsEquiFilter::operator= (const IsEquiFilter&) {return *this; }; + Filter* IsEquiFilter::getClone () const {return new IsEquiFilter(*this); }; + string IsEquiFilter::_getString () const {return ""; }; + bool IsEquiFilter::accept (Occurrence item) const + { + return (dynamic_cast(item.getEntity())!=NULL); + } + + + + /**/ IsComponentFilter::IsComponentFilter () {}; + /**/ IsComponentFilter::IsComponentFilter (const IsComponentFilter&) {}; + IsComponentFilter& IsComponentFilter::operator= (const IsComponentFilter&) {return *this; }; + Filter* IsComponentFilter::getClone () const {return new IsComponentFilter(*this); }; + string IsComponentFilter::_getString () const {return ""; }; + + + bool IsComponentFilter::accept (Occurrence item) const { + + return (dynamic_cast(item.getEntity())!=NULL); + + } + + + /**/ IsNetFilter::IsNetFilter () {}; + /**/ IsNetFilter::IsNetFilter (const IsNetFilter&) {}; + IsNetFilter& IsNetFilter::operator= (const IsNetFilter&) {return *this; }; + Filter* IsNetFilter::getClone () const {return new IsNetFilter(*this); }; + string IsNetFilter::_getString () const {return ""; }; + bool IsNetFilter::accept (Occurrence item) const + { + return (dynamic_cast(item.getEntity())!= NULL); + } + + + + /**/ IsNetOrComponentFilter::IsNetOrComponentFilter () {}; + /**/ IsNetOrComponentFilter::IsNetOrComponentFilter (const IsNetOrComponentFilter&) {}; + IsNetOrComponentFilter& IsNetOrComponentFilter::operator= (const IsNetOrComponentFilter&) {return *this; }; + Filter* IsNetOrComponentFilter::getClone () const {return new IsNetOrComponentFilter(*this); }; + string IsNetOrComponentFilter::_getString () const {return ""; }; + bool IsNetOrComponentFilter::accept (Occurrence item) const +{ + if( dynamic_cast(item.getEntity()) ) + return true; + + if( dynamic_cast(item.getEntity()) ) + return true; + + return false; +} + + + + + /**/ IsLeafEquiFilter::IsLeafEquiFilter () {}; + /**/ IsLeafEquiFilter::IsLeafEquiFilter (const IsLeafEquiFilter&) {}; + IsLeafEquiFilter& IsLeafEquiFilter::operator= (const IsLeafEquiFilter&) {return *this; }; + Filter* IsLeafEquiFilter::getClone () const {return new IsLeafEquiFilter(*this); }; + string IsLeafEquiFilter::_getString () const {return ""; }; + bool IsLeafEquiFilter::accept (Occurrence item) const {assert(false); return false;} + + + + /**/ IsNotLeafEquiFilter::IsNotLeafEquiFilter () {}; + /**/ IsNotLeafEquiFilter::IsNotLeafEquiFilter (const IsNotLeafEquiFilter&) {}; + IsNotLeafEquiFilter& IsNotLeafEquiFilter::operator= (const IsNotLeafEquiFilter&) {return *this; }; + Filter* IsNotLeafEquiFilter::getClone () const {return new IsNotLeafEquiFilter(*this); }; + string IsNotLeafEquiFilter::_getString () const {return ""; }; + bool IsNotLeafEquiFilter::accept (Occurrence item) const {assert(false); return false;} + + + + // ------------------------------------------------------------------- + // Class : "Equinox::NetIsUsedByExtractorNetFilter". + + + + /**/ NetIsUsedByExtractorFilter::NetIsUsedByExtractorFilter () {}; + /**/ NetIsUsedByExtractorFilter::NetIsUsedByExtractorFilter (const NetIsUsedByExtractorFilter&) {}; + NetIsUsedByExtractorFilter& NetIsUsedByExtractorFilter::operator= (const NetIsUsedByExtractorFilter&) {return *this; }; + Filter* NetIsUsedByExtractorFilter::getClone () const {return new NetIsUsedByExtractorFilter(*this); }; + string NetIsUsedByExtractorFilter::_getString () const {return ""; }; + bool NetIsUsedByExtractorFilter::accept (Component* item) const { + + Box box = item->getBoundingBox(); + + if( (box.getYMin() == box.getYMax()) || (box.getXMin() == box.getXMax()) ) + return false; + + + forEach ( BasicLayer*, i, item->getLayer()->getBasicLayers() ) + { + if (WithAlimStrategy::isExtractableLayer(*i)) return true; + } + + + return false; + } + + + + + + +}// End of namespace Equinox + + diff --git a/equinox/src/GraphicEquinoxEngine.cpp b/equinox/src/GraphicEquinoxEngine.cpp new file mode 100644 index 00000000..fea427da --- /dev/null +++ b/equinox/src/GraphicEquinoxEngine.cpp @@ -0,0 +1,228 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./GraphicEquinoxEngine.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +namespace Equinox { + + + using namespace std; + using Hurricane::Error; + using Hurricane::Warning; + using Hurricane::Graphics; + using CRL::AllianceFramework; + + +// ------------------------------------------------------------------- +// Class : "Equinox::GraphicEquinoxEngine". + + + size_t GraphicEquinoxEngine::_references = 0; + GraphicEquinoxEngine* GraphicEquinoxEngine::_singleton = NULL; + + + EquinoxEngine* GraphicEquinoxEngine::createEngine ( ) + { + Cell* cell = getCell (); + + EquinoxEngine* equinox = EquinoxEngine::get ( cell ); + if ( !equinox ) { + equinox = EquinoxEngine::create ( cell ); + } + return equinox; + } + + + GraphicEquinoxEngine* GraphicEquinoxEngine::grab () + { + if ( !_references ) + _singleton = new GraphicEquinoxEngine (); + _references++; + + return _singleton; + } + + + const Name& GraphicEquinoxEngine::getName () const + { return EquinoxEngine::staticGetName (); } + + + + + + Cell* GraphicEquinoxEngine::getCell () + { + if ( !_viewer ) { + throw Error ( "Equinox: GraphicEquinoxEngine not bound to any Viewer." ); + return NULL; + } + + if ( !_viewer->getCell() ) { + throw Error ( "Equinox: No Cell is loaded into the Viewer." ); + return NULL; + } + + return _viewer->getCell(); + } + + + + size_t GraphicEquinoxEngine::release () + { + _references--; + if ( !_references ) { + delete _singleton; + _singleton = NULL; + } + return _references; + } + + + + + + + + void GraphicEquinoxEngine::addToMenu ( CellViewer* viewer ) + { + assert ( _viewer == NULL ); + _viewer = viewer; + + QMenu* prMenu = _viewer->findChild("viewer.menuBar.extract"); + if ( !prMenu ) { + QMenuBar* menuBar = _viewer->findChild("viewer.menuBar"); + if ( !menuBar ) { + cerr << Warning("GraphicEquinoxEngine::addToMenu() - No MenuBar in parent widget.") << endl; + return; + } + prMenu = menuBar->addMenu ( tr("Extract") ); + prMenu->setObjectName ( "viewer.menuBar.extract" ); + + + prMenu->addSeparator (); + } + + + QAction* gRunWAAction = _viewer->findChild("viewer.menuBar.extract.equinox.withalim"); + if ( gRunWAAction ) + cerr << Warning("GraphicEquinoxEngine::addToMenu() - Equinox withalim already hooked in.") << endl; + else { + gRunWAAction = new QAction ( tr("Equinox - With alim"), _viewer ); + gRunWAAction->setObjectName ( "viewer.menuBar.extract.equinox.withalim" ); + gRunWAAction->setStatusTip ( tr("Run the Equinox withAlim Stategy") ); + gRunWAAction->setVisible ( true ); + prMenu->addAction ( gRunWAAction ); + + connect ( gRunWAAction, SIGNAL(triggered()), this, SLOT(runWithAlim()) ); + } + + + QAction* gRunWoAAction = _viewer->findChild("viewer.menuBar.extract.equinox.withoutalim"); + if ( gRunWoAAction ) + cerr << Warning("GraphicEquinoxEngine::addToMenu() - Equinox withoutalim already hooked in.") << endl; + else { + gRunWoAAction = new QAction ( tr("Equinox - Without alim"), _viewer ); + gRunWoAAction->setObjectName ( "viewer.menuBar.extract.equinox.withoutalim" ); + gRunWoAAction->setStatusTip ( tr("Run the Equinox withoutAlim Stategy") ); + gRunWoAAction->setVisible ( true ); + prMenu->addAction ( gRunWoAAction ); + + connect ( gRunWoAAction, SIGNAL(triggered()), this, SLOT(runWithoutAlim()) ); + } + + + // fin du sous menu + + connect ( this, SIGNAL(cellPreModificated ()), _viewer->getCellWidget(), SLOT(cellPreModificate ()) ); + connect ( this, SIGNAL(cellPostModificated()), _viewer->getCellWidget(), SLOT(cellPostModificate()) ); + } + + + + void GraphicEquinoxEngine::runWithAlim () + { + EquinoxEngine* equinox = createEngine ( ); + if ( !equinox ) return; + + emit cellPreModificated (); + + equinox->withAlimExtract(1); + + emit cellPostModificated (); + } + + + void GraphicEquinoxEngine::runWithoutAlim () + { + EquinoxEngine* equinox = createEngine ( ); + if ( !equinox ) return; + + emit cellPreModificated (); + + equinox->withoutAlimExtract(1); + + emit cellPostModificated (); + } + + + + + GraphicEquinoxEngine::GraphicEquinoxEngine () + : GraphicTool () + , _viewer (NULL) + { + } + + + GraphicEquinoxEngine::~GraphicEquinoxEngine() + { + } + + +} // End of Equinox namespace. diff --git a/equinox/src/Strategy.cpp b/equinox/src/Strategy.cpp new file mode 100644 index 00000000..bd8bea4d --- /dev/null +++ b/equinox/src/Strategy.cpp @@ -0,0 +1,523 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./Strategy.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include +#include + + +#include "hurricane/Bug.h" +#include "hurricane/Net.h" +#include "hurricane/Name.h" +#include "hurricane/Error.h" +#include "hurricane/Warning.h" +#include "hurricane/BasicLayer.h" +#include "hurricane/Technology.h" +#include "hurricane/Collection.h" +#include "hurricane/Cell.h" +#include "hurricane/Box.h" +#include "hurricane/Locator.h" +#include "hurricane/Instance.h" +#include "hurricane/Occurrence.h" +#include "hurricane/Component.h" +#include "hurricane/DataBase.h" +#include "hurricane/DebugSession.h" + +#include "crlcore/Utilities.h" +#include + +#include "equinox/Strategy.h" +#include "equinox/Equi.h" +#include "equinox/Tile.h" +#include "equinox/Tiles.h" +#include "equinox/EquinoxFilters.h" +#include "equinox/EquinoxEngine.h" + +namespace { + + +} + +namespace Equinox { + + + using namespace std; + using namespace Hurricane; + + + + + Strategy::Strategy() {} + + + bool const Strategy::isExtractableLayer(BasicLayer * basicLayer) + { + static Layer * _gmetalh = DataBase::getDB()->getTechnology()->getLayer("gmetalh"); + static Layer * _gmetalv = DataBase::getDB()->getTechnology()->getLayer("gmetalv"); + static Layer * _gcontact = DataBase::getDB()->getTechnology()->getLayer("gcontact"); + + if ( DataBase::getDB()->getTechnology()->isMetal(dynamic_cast ( basicLayer )) ) + if (( ( (basicLayer) != _gmetalh ) && ( (basicLayer) != _gmetalv ) && ( (basicLayer) != _gcontact ) )) return true; + return false; + } + + + + + + + WithAlimStrategy::WithAlimStrategy() {} + WithAlimStrategy::~WithAlimStrategy() {} + + + + void WithAlimStrategy::run(EquinoxEngine* equinox, unsigned nbwindows) + { + + forEach(Instance*,instance, equinox->_cell->getInstances()) + { + Cell * cell = instance->getMasterCell(); + EquinoxEngine* subequinox = EquinoxEngine::get(cell); + + if(!subequinox) + subequinox = EquinoxEngine::create(cell); + if( !(subequinox->isExtracted()) ) + run(subequinox, nbwindows); + } + + + equinox->scan(nbwindows); + equinox->setIsExtracted(true); + } + + void WithAlimStrategy::getTilesFor(EquinoxEngine* equinox) + { + + + // Init + //****** + ///*DEBUG*/ cmess1 << " o getTilesFor : " << endl ; + Box cellbox = equinox->_cell->getBoundingBox(); + long cellwidth = cellbox.getWidth(); + long ymax = cellbox.getYMax(); + long ymin = cellbox.getYMin(); + long xmin = cellbox.getXMin(); + long xmax = cellbox.getXMax(); + long interval = cellwidth/equinox->_nbWindows; + + + // Cas de la premiere fenetre + //**************************** + if( equinox->_cWindows == 0 ) + if ((equinox->_tilesByXmin->size()) + (equinox->_tilesByXmax->size())) + throw "Listes non vides avant constitution des Tiles"; + + + // calcul de la UnderBox + //****************** + long underbox_xmax = 0; + if( equinox->_cWindows == equinox->_nbWindows-1 ) + underbox_xmax = xmax; + else + underbox_xmax = xmin + (equinox->_cWindows+1)*interval; + + Box underbox(xmin+equinox->_cWindows*interval, ymin, underbox_xmax, ymax); + + + //Component Occurrence with a basiclayer on Metal at least + Occurrences componentoccurrences = equinox->_cell->getComponentOccurrencesUnder(underbox, + DataBase::getDB()->getTechnology()->_getMetalMask()).getSubSet((WithAlimStrategyFilter())); + + + Component * component = NULL; + Box box; + Tile * tile = NULL; + Equi * equi = NULL; + bool equicreated = false; + Occurrence o = NULL; + + forEach(Occurrence,occurrence,componentoccurrences) + { + + + component = dynamic_cast((*occurrence).getEntity()); + box = (*occurrence).getBoundingBox(); + tile = NULL; + equi = NULL; + equicreated = false; + + // ignorer les occurrences inutiles + // ***************************** + if( box.getXMin() < xmin || box.getXMin() >= xmax ) + continue; + + if((*occurrence)._getSharedPath()) { + o = (equinox->getUpperEquiOccurrence((*occurrence))); + if(!(o.isValid())) + throw Error("Can't use Equinox::GetTilesFor() : GetUpperEquiOccurrence Return Invalid Occurrence"); + } else { + o = (*occurrence); + } + + if (dynamic_cast(component->getLayer())) { + + // BasicLayer + //************ + tile = Tile::create((o), box, const_cast(dynamic_cast(component->getLayer())), NULL); + equinox->_tilesByXmin->push_back(tile); + equinox->_tilesByXmax->push_back(tile); + + } else { + + + + // Not BasicLayer + //**************** + + forEach ( BasicLayer*, i, component->getLayer()->getBasicLayers() ) + { + + + if (isExtractableLayer(*i)) + { + if(!equicreated && tile){ + equi = Equi::create(equinox); + tile->setEqui(equi); + equi->incrementCount(); + equi->addOccurrence((o)); + equicreated = true; + } + tile = Tile::create((o), box, (*i), equi); + equinox->_tilesByXmin->push_back(tile); + equinox->_tilesByXmax->push_back(tile); + + + if(equi) + equi->incrementCount(); + } + } + } + } + + // Sort these two vectors + // *********************** + sort::iterator, CompByXmin >( equinox->_tilesByXmin->begin(), equinox->_tilesByXmin->end(), CompByXmin() ); + sort::iterator, CompByXmax >( equinox->_tilesByXmax->begin(), equinox->_tilesByXmax->end(), CompByXmax() ); + + } + + + + + + + + + void WithAlimStrategy::operationAfterScanLine(EquinoxEngine* equinox) + { + Cell * cell = equinox->_cell; + if( cell->isLeaf()) // If this is a leaf cell + equinox->cleanUpLeafCell(); + else + equinox->getOccurrencesOfEquis(); + } + + + + + + + + WithoutAlimStrategy::WithoutAlimStrategy() {} + WithoutAlimStrategy::~WithoutAlimStrategy() {} + + + + + void WithoutAlimStrategy::run(EquinoxEngine* equinox, unsigned nbwindows) + { + + forEach(Instance*,instance, equinox->_cell->getInstances()) + { + Cell * cell = instance->getMasterCell(); + EquinoxEngine* subequinox = EquinoxEngine::get(cell); + + if(!subequinox) + subequinox = EquinoxEngine::create(cell); + if( !(subequinox->isExtracted()) ) + run(subequinox, nbwindows); + } + + + equinox->scan(nbwindows); + equinox->setIsExtracted(true); + } + + + void WithoutAlimStrategy::getTilesFor(EquinoxEngine* equinox) + { + + + // Init + //****** + ///*DEBUG*/ cmess1 << " o getTilesFor : " << endl ; + Box cellbox = equinox->_cell->getBoundingBox(); + long cellwidth = cellbox.getWidth(); + long ymax = cellbox.getYMax(); + long ymin = cellbox.getYMin(); + long xmin = cellbox.getXMin(); + long xmax = cellbox.getXMax(); + long interval = cellwidth/equinox->_nbWindows; + + // Cas de la premiere fenetre + //**************************** + if( equinox->_cWindows == 0 ) + { + ///*DEBUG*/ cmess1 << " - vidage de tilesByXmin (" << equinox->_tilesByXmin->size() << ") et tilesByXmax (" << equinox->_tilesByXmax->size() << ")" << endl; + equinox->_tilesByXmin->clear(); + equinox->_tilesByXmax->clear(); + } + + // calcul de la box + //****************** + long underbox_xmax = 0; + if( equinox->_cWindows==equinox->_nbWindows-1 ) + underbox_xmax = xmax; + else + underbox_xmax = xmin + (equinox->_cWindows+1)*interval; + + Box underbox(xmin+equinox->_cWindows*interval, ymin, underbox_xmax, ymax); + ///*DEBUG*/ cmess1 << " - underbox = "<< underbox << endl ; + + + + Occurrences componentoccurrences ; + + if(equinox->_cell->isLeaf()) + componentoccurrences = equinox->_cell->getComponentOccurrencesUnder(underbox, + DataBase::getDB()->getTechnology()->_getMetalMask()).getSubSet((WithAlimStrategyFilter())); + else + componentoccurrences = equinox->_cell->getComponentOccurrencesUnder(underbox, + DataBase::getDB()->getTechnology()->_getMetalMask()).getSubSet((WithoutAlimStrategyFilter())); + + + + + + Component * component = NULL; + Box box; + Tile * tile = NULL; + Equi * equi = NULL; + bool equicreated = false; + Occurrence o = NULL; + + + forEach(Occurrence,occurrence,componentoccurrences) + { + + + component = dynamic_cast((*occurrence).getEntity()); + box = (*occurrence).getBoundingBox(); + tile = NULL; + equi = NULL; + equicreated = false; + + + + + // ignorer les occurrences inutiles + // ***************************** + if( box.getXMin() < xmin || box.getXMin() >= xmax ) + continue; + + if((*occurrence)._getSharedPath()){ + o = (equinox->getUpperEquiOccurrence((*occurrence))); + if(!(o.isValid())) + throw Error("Can't use Equinox::GetTilesFor() : GetUpperEquiOccurrence Return Invalid Occurrence"); + } else { + o = (*occurrence); + } + //o = (*occurrence); + + if (dynamic_cast(component->getLayer())) { + + + + // BasicLayer + //************ + + + tile = Tile::create((o), box, const_cast(dynamic_cast(component->getLayer())), NULL); + equinox->_tilesByXmin->push_back(tile); + equinox->_tilesByXmax->push_back(tile); + /////*DEBUG*/ bt++; + + + + } else { + + + + // Not BasicLayer + //**************** + + forEach ( BasicLayer*, i, component->getLayer()->getBasicLayers() ) + { + + + if ( isExtractableLayer(*i)) + { + if(!equicreated && tile){ + equi = Equi::create(equinox); + tile->setEqui(equi); + equi->incrementCount(); + equi->addOccurrence((o)); + equicreated = true; + } + tile = Tile::create((o), box, (*i), equi); + equinox->_tilesByXmin->push_back(tile); + equinox->_tilesByXmax->push_back(tile); + + + if(equi) + equi->incrementCount(); + } + + + } + } + } + + // Sort these two vectors + // *********************** + sort::iterator, CompByXmin >( equinox->_tilesByXmin->begin(), equinox->_tilesByXmin->end(), CompByXmin() ); + sort::iterator, CompByXmax >( equinox->_tilesByXmax->begin(), equinox->_tilesByXmax->end(), CompByXmax() ); + + } + + + + + + + + + void WithoutAlimStrategy::operationAfterScanLine(EquinoxEngine* equinox) + { + Cell * cell = equinox->_cell; + if( cell->isLeaf()) // If this is a leaf cell + equinox->cleanUpLeafCell(); + else + equinox->getOccurrencesOfEquis(); + } + + + + + + // ------------------------------------------------------------------- + // Class : "Equinox::WithAlimStrategyFilter". + + /**/ WithAlimStrategyFilter::WithAlimStrategyFilter () {}; + /**/ WithAlimStrategyFilter::WithAlimStrategyFilter (const WithAlimStrategyFilter&) {}; + WithAlimStrategyFilter& WithAlimStrategyFilter::operator= (const WithAlimStrategyFilter&) {return *this; }; + Filter* WithAlimStrategyFilter::getClone () const {return new WithAlimStrategyFilter(*this); }; + string WithAlimStrategyFilter::_getString () const {return ""; }; + bool WithAlimStrategyFilter::accept (Occurrence item) const + { + + Component* component = dynamic_cast(item.getEntity()); + Box box = component->getBoundingBox(); + + // If box is not valid , this component occurrence is unuseful. + // ************************************************************ + if( (box.getYMin() == box.getYMax()) || (box.getXMin() == box.getXMax()) ) + return false; + + forEach ( BasicLayer*, i, component->getLayer()->getBasicLayers() ) + { + if (WithAlimStrategy::isExtractableLayer(*i)) return true; + } + return false; + + + }; + + + + + + + + + // ------------------------------------------------------------------- + // Class : "Equinox::WithoutAlimStrategyFilter". + + /**/ WithoutAlimStrategyFilter::WithoutAlimStrategyFilter () {}; + /**/ WithoutAlimStrategyFilter::WithoutAlimStrategyFilter (const WithoutAlimStrategyFilter&) {}; + WithoutAlimStrategyFilter& WithoutAlimStrategyFilter::operator= (const WithoutAlimStrategyFilter&) {return *this; }; + Filter* WithoutAlimStrategyFilter::getClone () const {return new WithoutAlimStrategyFilter(*this); }; + string WithoutAlimStrategyFilter::_getString () const {return ""; }; + bool WithoutAlimStrategyFilter::accept (Occurrence item) const + { + + Component* component = dynamic_cast(item.getEntity()); + Box box = component->getBoundingBox(); + Net * net = component->getNet(); + + if(net->isGlobal() || net->isGround() || net->isPower()) { + return false; + } + + // If box is not valid , this component occurrence is unuseful. + // ************************************************************ + if( (box.getYMin() == box.getYMax()) || (box.getXMin() == box.getXMax()) ) + return false; + + forEach ( BasicLayer*, i, component->getLayer()->getBasicLayers() ) + { + if (Strategy::isExtractableLayer(*i)) return true; + } + return false; + + + }; + + + + + + + + + + + +}// End of namespace Equinox + + diff --git a/equinox/src/Tile.cpp b/equinox/src/Tile.cpp new file mode 100644 index 00000000..b6ee16bc --- /dev/null +++ b/equinox/src/Tile.cpp @@ -0,0 +1,90 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./Tile.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + +#include "hurricane/Error.h" +#include "hurricane/Occurrence.h" + +#include "crlcore/Utilities.h" + +#include "equinox/Tile.h" +#include "equinox/Equi.h" + + +namespace Equinox { + + using Hurricane::Error; + + + // ------------------------------------------------------------------- + // Class : "EQUINOX::Tile". + + + + Tile::Tile (const Occurrence occurrence, const Box box, BasicLayer* basicLayer, Equi * equi) + : _occurrence(occurrence) + , _box(box) + , _basicLayer(basicLayer) + , _equi(equi) + { + } + + + + + + Tile* Tile::create(const Occurrence occurrence, Box box,BasicLayer* basiclayer, Equi * equi) + { + Tile* tile = new Tile(occurrence, box, basiclayer, equi); + if(!tile){ + throw Error("can't create Tile : allocation failed"); + } + tile->_postCreate(); + + + return tile; + } + + + + + string Tile::_getString() const + { + string s; + + if (!_equi) + { + s = "<" + _getTypeName() + " " + getString(_occurrence) + " >"; + } else { + s = "<" + _getTypeName() + " " + getString(_occurrence) + " " + _equi->_getString() + ">"; + } + return s; + } + + + + +}// End of namespace Equinox diff --git a/equinox/src/TileSweepLine.cpp b/equinox/src/TileSweepLine.cpp new file mode 100644 index 00000000..94dd70d6 --- /dev/null +++ b/equinox/src/TileSweepLine.cpp @@ -0,0 +1,47 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./TileSweepLine.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Equinox { + + template class SweepLine; + +} diff --git a/equinox/src/UnionFind.cpp b/equinox/src/UnionFind.cpp new file mode 100644 index 00000000..6a366b5f --- /dev/null +++ b/equinox/src/UnionFind.cpp @@ -0,0 +1,91 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./UnionFind.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + +#include "hurricane/Occurrence.h" + +#include "crlcore/Utilities.h" + +#include "equinox/UnionFind.h" +#include "equinox/Tile.h" +#include "equinox/Equi.h" + + +namespace Equinox { + + // ------------------------------------------------------------------- + // Class : "EQUINOX::UnionFind". + + + inline Equi * UnionFind::getRootEqui(Tile* tile) + { + assert(tile->getEqui()!=NULL); + Equi * equi = tile->getEqui(); + while( equi->getNextEqui()) + equi = equi->getNextEqui(); + return equi; + }; + + + + Equi * UnionFind::findValidEqui(Equi* equi) + { + if( (equi->getCount()>1) || (equi == NULL) ) + return equi; + else + return findValidEqui(equi->getNextEqui()); + }; + + + + Equi * UnionFind::getRootEquiWithCompression(Tile* tile) + { + Equi * root = getRootEqui(tile); + Equi * x = tile->getEqui(); + Equi * y = NULL; + + while(x!= root) { + y = x->getNextEqui(); + + if( y == root ) + break; + x->setNextEqui(root); + root->incrementCount(); + + if(y->getCount() == 1) { + Equi * tmpptr = findValidEqui(y); + assert (tmpptr!=NULL); + y->decrementCount(); + y = tmpptr; + } + else + y->decrementCount(); + x = y; + } + return root; + }; + +}// End of namespace Equinox diff --git a/equinox/src/equinox/Equi.h b/equinox/src/equinox/Equi.h new file mode 100644 index 00000000..ecd0767e --- /dev/null +++ b/equinox/src/equinox/Equi.h @@ -0,0 +1,165 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./equinox/Equi.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + +#ifndef __EQUINOX_EQUI__ +#define __EQUINOX_EQUI__ + +#include "hurricane/Entity.h" +#include "hurricane/Occurrence.h" +#include "hurricane/Occurrences.h" + + +namespace Hurricane { + class Box; + class Cell; + class Net; + class Entity; + class Occurence; + class Component; +} + +namespace Equinox { + + using std::set; + using std::string; + using std::map; + + using namespace Hurricane; + + class EquinoxEngine; + + + class Equi : public Entity { + + //Statics + public: + static Equi* create (EquinoxEngine* equinox, + Equi* nextequi = NULL, + const unsigned long& number = 0 + ); + //Some filters + static GenericFilter getIsEquiFilter (); + static GenericFilter getIsComponentFilter (); + static GenericFilter getIsNetFilter (); + static GenericFilter getIsLeafEquiFilter (); + static GenericFilter getIsNotLeafEquiFilter (); + // static GenericFilter getIsUsedByExtractFilter (); + static GenericFilter getIsNetOrComponentFilter (); + + + //Entity + public : + virtual Cell* getCell () const; + inline virtual Box getBoundingBox () const; + + //Functions + public: + /**/ bool isLeafEqui () const; + /**/ bool hasComponentOccurrence () const; + /**/ bool hasNetOccurrence () const; + /**/ Occurrences getEquiOccurrences () const; + /**/ Occurrences getNetOccurrences () const; + /**/ Occurrences getAllOccurrences () const; + /**/ Occurrences getNetAndComponentOccurrences () const; + + /**/ Occurrences getEquiComponentOccurrences () const; + + /**/ Occurrences getCurrentComponentOccurrences () const; + + /**/ Occurrences getComponentOccurrences () const; + + + + inline void setNextEqui (Equi* nextequi); + inline Equi * getNextEqui () const; + inline void setNumber (const unsigned long& number); + inline void incrementCount (); + inline void decrementCount (); + inline const unsigned long & getCount () const; + inline Occurrences getOccurrences () const; + inline void addOccurrence (const Occurrence& occurrence); + inline void erase (); + + /**/ void factorizeComponents (); + inline void merge (Equi* equi); + + + virtual string _getString () const; + protected: + virtual void _postCreate (); + virtual void _preDestroy (); + + //Attributes + protected : + static map _map_net2nb_usefulcomponent; + private: + /**/ EquinoxEngine * _equinox ; + /**/ set _occurrences ; + /**/ Equi * _nextequi ; + /**/ unsigned long _count ; + /**/ unsigned long _number ; + + // Constructors & Destructors. + private: + /**/ Equi (EquinoxEngine * equinox, + Equi* nextequi = NULL, + const unsigned long& number = 0 + ); + inline virtual ~Equi (); + /**/ Equi (const Equi&); + /**/ Equi& operator= (const Equi&); + + }; // End of class Equi + + + // Inline Functions. + inline Occurrences Equi::getOccurrences () const { return getCollection(_occurrences);}; + inline Equi * Equi::getNextEqui () const { return _nextequi; }; + inline const unsigned long & Equi::getCount () const { return _count; }; + inline void Equi::setNextEqui (Equi* nextequi) { _nextequi = nextequi; } ; + inline void Equi::setNumber (const unsigned long& number) { _number = number; }; + inline void Equi::incrementCount () { _count++ ; } ; + inline void Equi::decrementCount () { _count--; if( ( _count == 0 ) && ( _occurrences.empty() ) ) this->destroy(); }; + inline void Equi::addOccurrence (const Occurrence& occurrence) { _occurrences.insert(occurrence);}; + inline void Equi::erase () { _occurrences.clear();}; + inline Box Equi::getBoundingBox () const { return Box();} + inline Equi::~Equi () {} + inline void Equi::merge (Equi* equi) + { + forEach(Occurrence,occurrence,equi->getOccurrences()) + _occurrences.insert((*occurrence)); + equi->erase(); + }; + + +} // End of Equinox namespace. + + + + + +#endif // __EQUINOX_EQUI__ diff --git a/equinox/src/equinox/EquinoxCollections.h b/equinox/src/equinox/EquinoxCollections.h new file mode 100644 index 00000000..f9bb597e --- /dev/null +++ b/equinox/src/equinox/EquinoxCollections.h @@ -0,0 +1,269 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./equinox/EquinoxCollections.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +/******************************************************************** +* This file contains : * +* - AllOccurrencesCollection * +* Return nets and components of Equi and all subEquis * +* * +* - EquiComponentOccurrencesCollection * +* Return all components Occurrences of hyperNets * +* of this Equi and all subEquis. * +* * +* - CurrentComponentOccurrencesCollection * +* Return all components Occurrences of hyperNets * +* of this Equi. * +********************************************************************/ + + +#ifndef __EQUINOX_EQUINOX_COLLECTIONS__ +#define __EQUINOX_EQUINOX_COLLECTIONS__ + + +namespace Equinox { + + class Equi; + using namespace Hurricane; + + + class AllOccurrencesCollection : public Collection { + + + public : typedef Collection Inherit; + + public : class Locator : public Hurricane::Locator { + // ************************************************************* + + public : typedef Hurricane::Locator Inherit ; + + private : const Equi* _equi; + private : int _state; // state = 0 locator is invalid + private : OccurrenceLocator _componentLocator; + private : OccurrenceLocator _equioccurrenceLocator; + private : OccurrenceLocator _occurrenceLocator; + + public : Locator(); + public : Locator(const Equi* equi); + + public : Locator(const Locator& locator); + + public : Locator& operator=(const Locator& locator); + + public : virtual Occurrence getElement() const; + public : virtual Hurricane::Locator* getClone() const; + + public : virtual bool isValid() const; + + public : virtual void progress(); + + public : virtual string _getString() const; + + }; + +// Attributs +// ********* + + private : const Equi* _equi; + +// Constructors +// ************ + + public : AllOccurrencesCollection(); + public : AllOccurrencesCollection(const Equi* equi); + public : AllOccurrencesCollection(const AllOccurrencesCollection&); + +// Operators +// ********* + + public : AllOccurrencesCollection& operator=(const AllOccurrencesCollection&); +// Accessors +// ********* + + public : virtual Collection* getClone() const; + public : virtual Hurricane::Locator* getLocator() const; + +// Others +// ****** + + public : virtual string _getString() const ; + + }; // end of class AllOccurrencesCollection + + + + + + + class EquiComponentOccurrencesCollection : public Collection { + + + public : typedef Collection Inherit; + + public : class Locator : public Hurricane::Locator { + // ************************************************************* + + public : typedef Hurricane::Locator Inherit ; + + private : const Equi* _equi; + private : int _state; // state = 0 locator is invalid + private : OccurrenceLocator _componentLocator; + private : OccurrenceLocator _equioccurrenceLocator; + private : OccurrenceLocator _occurrenceLocator; + + public : Locator(); + public : Locator(const Equi* equi); + + public : Locator(const Locator& locator); + + public : Locator& operator=(const Locator& locator); + + public : virtual Occurrence getElement() const; + public : virtual Hurricane::Locator* getClone() const; + + public : virtual bool isValid() const; + + public : virtual void progress(); + + public : virtual string _getString() const; + + }; + +// Attributs +// ********* + + private : const Equi* _equi; + +// Constructors +// ************ + + public : EquiComponentOccurrencesCollection(); + public : EquiComponentOccurrencesCollection(const Equi* equi); + public : EquiComponentOccurrencesCollection(const EquiComponentOccurrencesCollection&); + +// Operators +// ********* + + public : EquiComponentOccurrencesCollection& operator=(const EquiComponentOccurrencesCollection&); +// Accessors +// ********* + + public : virtual Collection* getClone() const; + public : virtual Hurricane::Locator* getLocator() const; + +// Others +// ****** + + public : virtual string _getString() const ; + + }; // end of class EquiComponentOccurrencesCollection + + + + + + + + + + class CurrentComponentOccurrencesCollection : public Collection { + + + public : typedef Collection Inherit; + + public : class Locator : public Hurricane::Locator { + // ************************************************************* + + public : typedef Hurricane::Locator Inherit ; + + private : const Equi* _equi; + private : int _state; // state = 0 locator is invalid + private : OccurrenceLocator _componentLocator; + private : OccurrenceLocator _netoccurrenceLocator; + private : ComponentLocator _occurrenceLocator; + + public : Locator(); + public : Locator(const Equi* equi); + + public : Locator(const Locator& locator); + + public : Locator& operator=(const Locator& locator); + + public : virtual Occurrence getElement() const; + public : virtual Hurricane::Locator* getClone() const; + + public : virtual bool isValid() const; + + public : virtual void progress(); + + public : virtual string _getString() const; + + }; + +// Attributs +// ********* + + private : const Equi* _equi; + +// Constructors +// ************ + + public : CurrentComponentOccurrencesCollection(); + public : CurrentComponentOccurrencesCollection(const Equi* equi); + public : CurrentComponentOccurrencesCollection(const CurrentComponentOccurrencesCollection&); + +// Operators +// ********* + + public : CurrentComponentOccurrencesCollection& operator=(const CurrentComponentOccurrencesCollection&); +// Accessors +// ********* + + public : virtual Collection* getClone() const; + public : virtual Hurricane::Locator* getLocator() const; + +// Others +// ****** + + public : virtual string _getString() const ; + + }; // end of class CurrentComponentOccurrencesCollection + + + + + + + + + +} //end of namespace + + + + +#endif // __EQUINOX_EQUINOX_COLLECTIONS__ diff --git a/equinox/src/equinox/EquinoxEngine.h b/equinox/src/equinox/EquinoxEngine.h new file mode 100644 index 00000000..9332afe8 --- /dev/null +++ b/equinox/src/equinox/EquinoxEngine.h @@ -0,0 +1,209 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : " ./equinox/EquinoxEngine.h | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __EQUINOX_EQUINOX_ENGINE__ +#define __EQUINOX_EQUINOX_ENGINE__ + +#include +#include +#include +#include +#include +#include +#include +namespace { + using namespace Hurricane; + +} +namespace Hurricane { + class Box; + class Cell; + class Name; + class Record; + class Occurrence; + class BasicLayer; + + template class GenericFilter; + +} + +namespace CRL { + class ToolEngine; +} + +namespace Equinox { + + + using std::string; + using std::set; + using std::map; + using std::vector; + + using Hurricane::Cell; + using Hurricane::Box; + using Hurricane::Name; + using Hurricane::Record; + using Hurricane::GenericFilter; + using Hurricane::BasicLayer; + using Hurricane::OccurrenceFilter; + using Hurricane::Occurrence; + using Hurricane::Occurrences; + +using Hurricane::ComponentFilter; + using CRL::ToolEngine; + + + class Tile; + class Equi; + template + class SweepLine; + +// ------------------------------------------------------------------- +// Class : "Equinox::EquinoxEngine". + + + class EquinoxEngine : public ToolEngine { + + + // Friends + public: + friend class GraphicEquinoxEngine; + friend class Strategy; + friend class WithAlimStrategy; + friend class WithoutAlimStrategy; + + // Statics + public: + /**/ static EquinoxEngine* create (Cell*); + inline static const Name& staticGetName (); + inline static EquinoxEngine* get (const Cell* ); + inline static GenericFilter getIsRoutingFilter (); + /**/ static Strategy * getStrategy (); + /**/ static ComponentFilter getIsUsedByExtractFilter (); + private: + inline static void setStrategy (Strategy *); + + + public : + inline virtual const Name& getName () const; + inline Equis getRoutingEquis () const; + inline Equis getEquis () const; + inline unsigned long long getNumOfEquis (); + inline void addEqui (Equi* equi); + inline void removeEqui (Equi* equi); + inline map& _getOccurrences (); + + /**/ virtual Record* _getRecord () const; + /**/ virtual string _getString () const; + /**/ virtual string _getTypeName () const; + /**/ Occurrences getComponentOccurrencesBy (Occurrence); + inline bool isExtracted () const; + + /**/ bool hasEqui (Equi* equi); + + /**/ void removeEquis (); + + /**/ bool _IsToFilter (const Equi*) const; + /**/ void _FilterEquis (); + /**/ Occurrence _GetTopNetOccurrence (const Equi* equi) const; + /**/ void _WriteNetlist (); + /**/ void _CheckOut (Equi*); + /**/ void withAlimExtract (unsigned int); + /**/ void withoutAlimExtract (unsigned int); + /**/ void deviceExtract (unsigned int); + /**/ void extract (unsigned int); + /**/ void test (); + /**/ Box _getSweepLineBox (); + /**/ void insertInterval (Tile*,stack *enumResultStack); + /**/ void removeInterval (Tile* item); + protected: + /**/ Equi* getEquiByOccurrence (Occurrence occurrence); + /**/ Occurrence getEquiOccurrence (Occurrence occurrence); + /**/ Occurrence getUpperEquiOccurrence (Occurrence occurrence); + /**/ void setIsExtracted (const bool flag) ; + /**/ void scan (unsigned int); + /**/ void getOccurrencesOfEquis (); + /**/ void cleanUpLeafCell (); + /**/ void flushEquis (Cell*); + private: + /**/ void selectWindowsSize (); + /**/ void initTiles (); + /**/ void postSweepLine (); + /**/ void printEquis (); + + // Attributes + private: + static Name _toolName; + /**/ unsigned int _cWindows ; + /**/ unsigned int _nbWindows ; + + protected: + static Strategy * _strategy; + /**/ bool _isExtracted; + /**/ set _equis; + /**/ map _occurrences; + /**/ vector* _tilesByXmin; + /**/ vector* _tilesByXmax; + + protected: + // Constructors & Destructors. + /**/ EquinoxEngine (Cell*); + /**/ virtual ~EquinoxEngine (); + /**/ virtual void _postCreate (); + /**/ virtual void _preDestroy (); + /**/ void _destroy (); + /**/ void _depthDestroy (); + private: + /**/ EquinoxEngine (const EquinoxEngine&); + /**/ EquinoxEngine& operator= (const EquinoxEngine&); + + + + + }; // End of class EquinoxEngine + + // Inline Functions. + + inline bool EquinoxEngine::isExtracted () const { return _isExtracted; }; + inline const Name& EquinoxEngine::getName () const { return _toolName; }; + inline EquinoxEngine* EquinoxEngine::get (const Cell* cell ) { return static_cast(ToolEngine::get(cell,staticGetName())); }; + + inline const Name& EquinoxEngine::staticGetName () { return _toolName; } + inline map& EquinoxEngine::_getOccurrences () { return _occurrences; }; + inline void EquinoxEngine::setStrategy (Strategy * s) { if (_strategy) delete _strategy; _strategy = s; }; + inline EquiFilter EquinoxEngine::getIsRoutingFilter () { return IsRoutingFilter();} + inline Equis EquinoxEngine::getRoutingEquis () const { return getCollection(_equis).getSubSet(getIsRoutingFilter()); }; + inline Equis EquinoxEngine::getEquis () const { return getCollection(_equis); }; + inline unsigned long long EquinoxEngine::getNumOfEquis () { return _equis.size(); } + inline void EquinoxEngine::addEqui ( Equi* equi) { _equis.insert(equi); } + inline void EquinoxEngine::removeEqui ( Equi* equi) { _equis.erase(equi); } + +} // End of Equinox namespace. + + +#endif // __EQUINOX_EQUINOX_ENGINE__ diff --git a/equinox/src/equinox/EquinoxFilters.h b/equinox/src/equinox/EquinoxFilters.h new file mode 100644 index 00000000..0634b7e9 --- /dev/null +++ b/equinox/src/equinox/EquinoxFilters.h @@ -0,0 +1,250 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./equinox/EquinoxFilters.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + +#ifndef __EQUINOX_EQUINOX_FILTERS__ +#define __EQUINOX_EQUINOX_FILTERS__ + + + +/** + + Filter List : + - IsRouting (Equi) + - IsUsedByExtract (Component) + - IsEqui (Occurrence) + - IsComponent (Occurrence) + - IsNet (Occurrence) + - IsNetOrComponent (Occurrence) + - IsLeafEqui (Occurrence) + + + **/ + + + + +namespace Hurricane { + + template class GenericLocator; + template class GenericCollection; + template class GenericFilter; + + template class Filter; + + + class Occurrence; + class Component; + class Layer; + class Net; + +} + +namespace Equinox { + + using Hurricane::GenericCollection; + using Hurricane::GenericLocator; + using Hurricane::GenericFilter; + using Hurricane::Filter; + using Hurricane::Occurrence; + using Hurricane::Component; + using Hurricane::Layer; + using Hurricane::Net; + + + using std::string; + + class Equi; + + // ------------------------------------------------------------------- + // Class : "Equinox::IsRoutingEquiFilter". + + class IsRoutingFilter : public Filter + { + + public: + /**/ IsRoutingFilter (); + /**/ IsRoutingFilter (const IsRoutingFilter&); + /**/ IsRoutingFilter& operator= (const IsRoutingFilter&); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Equi* item) const; + + }; // End of class IsRoutingFilter + + + + // ------------------------------------------------------------------- + // Class : "Equinox::IsUsedByExtractFilter". + + class IsUsedByExtractFilter : public Filter + { + + public: + /**/ IsUsedByExtractFilter (); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Component*) const; + + /**/ IsUsedByExtractFilter (const IsUsedByExtractFilter&); + /**/ IsUsedByExtractFilter& operator= (const IsUsedByExtractFilter&); + }; // End of class IsUsedByExtractFilter + + + + + + + + + // ------------------------------------------------------------------- + // Class : "Equinox::IsNetOrComponentOccurrenceFilter". + + class IsNetOrComponentFilter : public Filter + { + + public: + /**/ IsNetOrComponentFilter (); + /**/ IsNetOrComponentFilter (const IsNetOrComponentFilter&); + /**/ IsNetOrComponentFilter& operator= (const IsNetOrComponentFilter&); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Occurrence item) const; + + }; // End of class IsNetOrComponentFilter + +// ------------------------------------------------------------------- + // Class : "Equinox::IsComponentOccurrenceFilter". + + class IsComponentFilter : public Filter + { + + public: + /**/ IsComponentFilter (); + /**/ IsComponentFilter (const IsComponentFilter&); + /**/ IsComponentFilter& operator= (const IsComponentFilter&); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Occurrence item) const; + + }; // End of class IsComponentFilter + + + + // ------------------------------------------------------------------- + // Class : "Equinox::IsNetOccurrenceFilter". + + class IsNetFilter : public Filter + { + + public: + /**/ IsNetFilter (); + /**/ IsNetFilter (const IsNetFilter&); + /**/ IsNetFilter& operator= (const IsNetFilter&); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Occurrence item) const; + + }; // End of class IsNetFilter + + + + // ------------------------------------------------------------------- + // Class : "Equinox::IsEquiOccurrenceFilter". + + class IsEquiFilter : public Filter + { + + public: + /**/ IsEquiFilter (); + /**/ IsEquiFilter (const IsEquiFilter&); + /**/ IsEquiFilter& operator= (const IsEquiFilter&); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Occurrence item) const; + + }; // End of class IsEquiFilter + + + + + + // ------------------------------------------------------------------- + // Class : "Equinox::IsEquiLeafOccurrenceFilter". + + class IsLeafEquiFilter : public Filter + { + + public: + /**/ IsLeafEquiFilter (); + /**/ IsLeafEquiFilter (const IsLeafEquiFilter&); + /**/ IsLeafEquiFilter& operator= (const IsLeafEquiFilter&); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Occurrence item) const; + + }; // End of class IsLeafEquiFilter + + +// ------------------------------------------------------------------- + // Class : "Equinox::IsNotEquiLeafOccurrenceFilter". + + class IsNotLeafEquiFilter : public Filter + { + + public: + /**/ IsNotLeafEquiFilter (); + /**/ IsNotLeafEquiFilter (const IsNotLeafEquiFilter&); + /**/ IsNotLeafEquiFilter& operator= (const IsNotLeafEquiFilter&); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Occurrence item) const; + + }; // End of class IsLeafEquiFilter + + + class NetIsUsedByExtractorFilter : public Filter + { + + public: + /**/ NetIsUsedByExtractorFilter (); + /**/ NetIsUsedByExtractorFilter (const NetIsUsedByExtractorFilter&); + /**/ NetIsUsedByExtractorFilter& operator= (const NetIsUsedByExtractorFilter&); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Component* item) const; + + }; // End of class NetIsUsedByExtractorFilter + + + + + +} // End of Equinox namespace. + + + +#endif // __EQUINOX_EQUINOX_FILTERS__ diff --git a/equinox/src/equinox/Equis.h b/equinox/src/equinox/Equis.h new file mode 100644 index 00000000..2fff65bf --- /dev/null +++ b/equinox/src/equinox/Equis.h @@ -0,0 +1,60 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./equinox/Equis.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + +#ifndef __EQUINOX_EQUIS__ +#define __EQUINOX_EQUIS__ + + +namespace Hurricane { + + template class GenericLocator; + template class GenericCollection; + template class GenericFilter; + +} + +namespace Equinox { + + + using Hurricane::GenericCollection; + using Hurricane::GenericLocator; + using Hurricane::GenericFilter; + + + class Equi; + + + typedef GenericCollection Equis; + typedef GenericLocator EquiLocator; + typedef GenericFilter EquiFilter; + + +} // End of Equinox namespace. + + + +#endif // __EQUINOX_EQUIS__ diff --git a/equinox/src/equinox/GraphicEquinoxEngine.h b/equinox/src/equinox/GraphicEquinoxEngine.h new file mode 100644 index 00000000..38c8b6c7 --- /dev/null +++ b/equinox/src/equinox/GraphicEquinoxEngine.h @@ -0,0 +1,98 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./equinox/GraphicEquinoxEngine.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __EQUINOX_GRAPHIC_EQUINOX_ENGINE__ +#define __EQUINOX_GRAPHIC_EQUINOX_ENGINE__ + +#include + + + +#include "crlcore/GraphicToolEngine.h" + + +namespace Hurricane { + class Go; + class BasicLayer; + class Transformation; + class CellWidget; + class CellViewer; +} + + +namespace Equinox { + + + + using Hurricane::Cell; + using Hurricane::Go; + using Hurricane::Box; + using Hurricane::BasicLayer; + using Hurricane::Transformation; + using Hurricane::CellWidget; + using Hurricane::CellViewer; + using CRL::GraphicTool; + using CRL::Name; + + class EquinoxEngine; + class Sweepline; + + +// ------------------------------------------------------------------- +// Class : "Equinox::GraphicEquinoxEngine". + + + class GraphicEquinoxEngine : public GraphicTool { + + Q_OBJECT; + + public: + inline + /**/ EquinoxEngine* createEngine (); + /**/ static GraphicEquinoxEngine* grab (); + /**/ virtual const Name& getName () const; + /**/ Cell* getCell (); + /**/ virtual size_t release (); + /**/ virtual void addToMenu ( CellViewer* ); + + public slots: + /**/ void runWithAlim (); + /**/ void runWithoutAlim (); + + private: + /**/ static size_t _references; + /**/ static GraphicEquinoxEngine* _singleton; + /**/ CellViewer* _viewer; + protected: + /**/ GraphicEquinoxEngine (); + /**/ virtual ~GraphicEquinoxEngine (); + }; + + + +} // End of Equinox namespace. + + +#endif // __EQUINOX_GRAPHIC_EQUINOX_ENGINE__ diff --git a/equinox/src/equinox/Interval.h.b b/equinox/src/equinox/Interval.h.b new file mode 100644 index 00000000..7249244f --- /dev/null +++ b/equinox/src/equinox/Interval.h.b @@ -0,0 +1,54 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./equinox/Interval.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __EQUINOX_INTERVAL__ +#define __EQUINOX_INTERVAL__ + +namespace Equinox { + + // ------------------------------------------------------------------- + // Class : "EQUINOX::Interval". + + + class Interval { + + public: + /**/ Interval (); + /**/ virtual ~Interval (); + /**/ virtual long GetLowPoint () const = 0; + /**/ virtual long GetHighPoint () const = 0; + /**/ virtual void Print () const; + + }; + + + +} // end of namespace + + +#endif //__EQUINOX_INTERVAL__ diff --git a/equinox/src/equinox/Strategy.h b/equinox/src/equinox/Strategy.h new file mode 100644 index 00000000..49f976db --- /dev/null +++ b/equinox/src/equinox/Strategy.h @@ -0,0 +1,165 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./equinox/Strategy.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + +#ifndef _EQUINOX_STRATEGY_H +#define _EQUINOX_STRATEGY_H + +namespace Hurricane { + class Net; + class Occurrence; + class Component; + + +} + +namespace Equinox { + + + using std::vector; + using std::map; + using std::string; + using Hurricane::Cell; + using Hurricane::Occurrence; + using Hurricane::Box; + using Hurricane::Filter; + using Hurricane::BasicLayer; + using Hurricane::Component; + using Hurricane::_TName; + using Hurricane::Net; + + class EquinoxEngine; + class Tile; + + + class Strategy { + + public: + //implemented + static bool const isExtractableLayer(BasicLayer *); + + public : + /**/ Strategy (); + virtual ~Strategy (){}; + + + virtual void run (EquinoxEngine* , unsigned int){}; + virtual void getTilesFor (EquinoxEngine*){}; + virtual void operationAfterScanLine (EquinoxEngine*){}; + + //not implemented + //virtual void createIntervalSets (TileSweepLine::IntervalSets*); + private : + /**/ Strategy (const Strategy&); + /**/ Strategy& operator= (const Strategy&); + + }; // End of Strategy + + + + class WithAlimStrategy : public Strategy { + + public : + /**/ WithAlimStrategy(); + virtual ~WithAlimStrategy(); + + + virtual void run(EquinoxEngine* , unsigned int); + virtual void getTilesFor(EquinoxEngine*) ; + virtual void operationAfterScanLine(EquinoxEngine*); + +};// End of WithAlimStrategy + + + class WithoutAlimStrategy : public Strategy { + + public : + /**/ WithoutAlimStrategy(); + virtual ~WithoutAlimStrategy(); + virtual void run(EquinoxEngine* , unsigned int); + virtual void getTilesFor(EquinoxEngine*) ; + virtual void operationAfterScanLine(EquinoxEngine*); + +};// End of WithAlimStrategy + + + + + class DefaultStrategy : public WithAlimStrategy { + public : + /**/ DefaultStrategy() {}; + };// End of DefaultStrategy + + + + + + // ------------------------------------------------------------------- + // Class : "Equinox::WithAlimStrategyFilter". + + class WithAlimStrategyFilter : public Filter + { + + public: + /**/ WithAlimStrategyFilter (); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Occurrence item) const; + + /**/ WithAlimStrategyFilter (const WithAlimStrategyFilter&); + /**/ WithAlimStrategyFilter& operator= (const WithAlimStrategyFilter&); + }; // End of class WithAlimStrategyFilter + + + + + // ------------------------------------------------------------------- + // Class : "Equinox::WithoutAlimStrategyFilter". + + class WithoutAlimStrategyFilter : public Filter + { + + public: + /**/ WithoutAlimStrategyFilter (); + virtual Filter* getClone () const; + virtual string _getString () const; + virtual bool accept (Occurrence item) const; + + /**/ WithoutAlimStrategyFilter (const WithoutAlimStrategyFilter&); + /**/ WithoutAlimStrategyFilter& operator= (const WithoutAlimStrategyFilter&); + }; // End of class WithoutAlimStrategyFilter + + + + + + + +}// End of namespace Equinox + + + +#endif // _EQUINOX_STRATEGY_H diff --git a/equinox/src/equinox/SweepLine.h b/equinox/src/equinox/SweepLine.h new file mode 100644 index 00000000..d5ae15b0 --- /dev/null +++ b/equinox/src/equinox/SweepLine.h @@ -0,0 +1,411 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./equinox/SweepLine.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + +#ifndef _EQUINOX_SWEEPLINE_H +#define _EQUINOX_SWEEPLINE_H + +#define INTERVALTREE 1 /*Without use STL map, VERY SLOW*/ + +//#define ASSERT 1 + + +#include "crlcore/Utilities.h" + +namespace Hurricane { + class BasicLayer; + class DataBase; +} + +namespace CRL { + class ToolEngine; +} +namespace Equinox { + + class EquinoxEngine; + class Strategy; + + using namespace Hurricane; + using CRL::ToolEngine; + +// ------------------------------------------------------------------- +// Class : "Equinox::SweepLine". + + + template < typename ITEM, typename ENGINE > + class SweepLine { + + private : + map _intervalTreeNodeMap; + int intervalsize; + float intervaltime; + int contactssize; + + + struct ItemComparator{ + inline bool operator() ( ITEM const& t1, ITEM const& t2) const; + }; + + + + public: + typedef vector < ITEM > ItemList; + + typedef set < ITEM , ItemComparator > IntervalSet; +#ifdef INTERVALTREE + typedef map < BasicLayer*, IntervalTree* > IntervalSets; +#else + typedef map < BasicLayer*, IntervalSet* > IntervalSets; +#endif + + public: + static SweepLine* create (ENGINE, + Strategy*); + virtual void destroy (); + + public: + /**/ Record* _getRecord () const; + /**/ string _getString () const; + /**/ Box getBoundingBox () const; + /**/ void run ( vector < ITEM >* _itemsByXmin, + vector < ITEM >* _itemsByXmax, + bool stopToMax, + int max); + + /**/ void initIntervalSets () ; + /**/inline void insertInterval (ITEM newitem); + /**/inline void removeInterval (ITEM newitem); + + public: + + virtual const Name& getName () const; + /**/ Strategy* getStrategy () ; + protected: + static const Name _extensionName; + /**/ ENGINE _engine; + /**/ IntervalSets _intervalSets; + /**/ Strategy* _strategy; + + protected: + /**/ void _postCreate (); + /**/ void _preDestroy (); + /**/ SweepLine ( ENGINE, + Strategy* ); + virtual ~SweepLine (); + + + }; //end of SweepLine + + + + template < typename ITEM, typename ENGINE > + inline bool SweepLine::ItemComparator::operator() ( ITEM const& t1, ITEM const& t2) const + { +#ifdef ASSERT + if (!t1 || !t2) throw Error("SweepLine Assert Error"); +#endif + if( t1->getYmin() < t2->getYmin() ) + return true; + + if( t1->getYmin() == t2->getYmin() ) + return t1 < t2; + + return false; + + } + + + + + + + + + + template < typename ITEM, typename ENGINE > + const Name SweepLine::_extensionName = "Equinox::SweepLine"; + + + + template < typename ITEM, typename ENGINE > + Strategy* SweepLine::getStrategy () + { + if (!_strategy) throw Error("Aucun strategy transmise pour la sweepLine"); + return _strategy; + } + + template < typename ITEM, typename ENGINE > + SweepLine* SweepLine::create (ENGINE engine, Strategy* strategy) { + + SweepLine* sweepLine = new SweepLine ( engine , strategy ); + + if(!sweepLine){ + throw Error("can't create SweepLine : allocation failed"); + } + + sweepLine->_postCreate (); + return sweepLine ; + +} + template < typename ITEM, typename ENGINE > + /**/ SweepLine::SweepLine (ENGINE engine, Strategy* strategy) : + // ExtensionGo(cell), + _engine(engine), + _intervalSets(), + _strategy(strategy) + { + + }; + + template < typename ITEM, typename ENGINE > + void SweepLine::_postCreate (){ + // ExtensionGo::_postCreate(); + initIntervalSets(); +} + template < typename ITEM, typename ENGINE > + /**/ SweepLine::~SweepLine (){} + + template < typename ITEM, typename ENGINE > + void SweepLine::destroy (){ _preDestroy(); delete this; } + + template < typename ITEM, typename ENGINE > + void SweepLine::_preDestroy (){ + // ExtensionGo::_preDestroy(); + typename IntervalSets::iterator it_intervaltree_begin = _intervalSets.begin(), + it_intervaltree_end = _intervalSets.end(); + + while(it_intervaltree_begin!=it_intervaltree_end){ + delete (*it_intervaltree_begin).second; + it_intervaltree_begin++; + } + } + + + + + template < typename ITEM, typename ENGINE > + void SweepLine::initIntervalSets() + { + + forEach ( BasicLayer*, basicLayer, DataBase::getDB()->getTechnology()->getBasicLayers()) { + if (Strategy::isExtractableLayer(*basicLayer) ) { +#ifdef INTERVALTREE + (_intervalSets)[*basicLayer] = new IntervalTree(); +#else + (_intervalSets)[*basicLayer] = new IntervalSet(); +#endif + } + } + + } + + + + template < typename ITEM, typename ENGINE > + Record* SweepLine::_getRecord() const + // *********************** + { + //Record* record = Inherit::_getRecord(); + Record* record = NULL; + if ( !record ) + record = new Record ( getString ( this ) ); + return record; + } + + template < typename ITEM, typename ENGINE > + string SweepLine::_getString() const + // **************************** + { + return "<" + _TName ( "SweepLine" ) + ">"; + } + + + + template < typename ITEM, typename ENGINE > + const Name& SweepLine::getName () const { + return _extensionName; + } + + + + template < typename ITEM, typename ENGINE > +inline void SweepLine::insertInterval(ITEM item) + { +#ifdef ASSERT + if (!item) throw Error("SweepLine : Insert null"); +#endif +#ifdef INTERVALTREE + //recherche du Layer du Item +#ifdef ASSERT + if (_intervalSets.find(item->getBasicLayer()) == _intervalSets.end()) + throw Error("Layer inconnu dans insertInterval"); +#endif + IntervalTree* intervaltree = _intervalSets.find(item->getBasicLayer())->second; + // Récuperation des intersections avec ce Item dans enumResultStack + stack * enumResultStack = (intervaltree->Enumerate((item->getYmin()),( item->getYmax()) )); +#else + typename IntervalSets::const_iterator mySetsIt = _intervalSets.find(item->getBasicLayer()); +#ifdef ASSERT + if (_intervalSets.find(item->getBasicLayer()) == _intervalSets.end()) + throw Error("Layer inconnu dans insertInterval"); +#endif + IntervalSet* intervaltree = mySetsIt->second; + stack * enumResultStack = new stack; + typename IntervalSet::iterator itmid2down = intervaltree->lower_bound( item ) ; + typename IntervalSet::iterator itbegin2mid = intervaltree->begin() ; + while ( itmid2down != intervaltree->end() ) + { + if ( (*itmid2down)->getYmin() <= item->getYmax() ) { enumResultStack->push((*itmid2down)); itmid2down++;} + else break; + } + + while ( itbegin2mid != ( intervaltree->upper_bound( item ) ) ) + { + if ( (*itbegin2mid)->getYmax() >= item->getYmin() ) { enumResultStack->push((*itbegin2mid));} + itbegin2mid++; + } +#endif + _engine->insertInterval(item,enumResultStack); + + +#ifdef INTERVALTREE + _intervalTreeNodeMap[(item)] = intervaltree->Insert((item)); +#else + //Ajout du Item aux intervals + intervaltree->insert(item); +#endif + + delete enumResultStack; + +} + + + template < typename ITEM, typename ENGINE > + inline void SweepLine::removeInterval(ITEM item) + { + + // /*DEBUG*/ cmess1 << " o removeInterval : " << endl; + + + //recherche du Layer du Item + typename IntervalSets::const_iterator mySetsIt = _intervalSets.find(item->getBasicLayer()); + +#ifdef ASSERT + //Valide la liste des layers + if(mySetsIt ==_intervalSets.end()) throw Error("SweepLine : La clé des Layers n'existe pas pas"); + + //Valide l'item à supprimer + typename IntervalSet::const_iterator mySetIt = mySetsIt->second->find(item); + if(mySetIt == mySetsIt->second->end()) throw Error("SweepLine : Un item à detruire du champ n'existe pas"); +#endif + +#ifdef INTERVALTREE + //Suppression du Item + mySetsIt->second->DeleteNode(_intervalTreeNodeMap[item]); + _intervalTreeNodeMap.erase(item); +#else + mySetsIt->second->erase(item); +#endif + + + _engine->removeInterval(item); + + + + ///*DEBUG*/ cmess1 << " - destroy tile OK " << endl; + ///*DEBUG*/ cmess1 << " - " << mySetsIt->second->size() << " interval(s) sur le Layer." < + void SweepLine::run (vector < ITEM >* _itemsByXmin, vector < ITEM >* _itemsByXmax,bool stopAtMax = false,int max = 0) + { + + ///*DEBUG*/ cmess1 << " o SweepLine :: run : " << endl; + + //Making iterators + typename vector::iterator it1 = _itemsByXmin->begin(); + typename vector::iterator it1_end = _itemsByXmin->end(); + typename vector::iterator it2 = _itemsByXmax->begin(); + typename vector::iterator it2_end = _itemsByXmax->end(); + typename vector::iterator it2_begin = _itemsByXmax->begin(); + + while(it2!=it2_end) + { + if( (it1 != it1_end) && ((*it1)->getXmin() <= (*it2)->getXmax()) ) /* Get some tiles */ + { + typename vector::iterator upper_it = upper_bound(it1, it1_end, *it1, CompByXmin_Upper_Bound() ); + while(it1 != upper_it) + { + insertInterval(*it1); + it1++; + } + } + else /* Throw some tiles */ + { + if(stopAtMax) + if ((*it2)->getXmax() >= max ) + break; + + typename vector::iterator upper_it = upper_bound(it2, it2_end, *it2, CompByXmax_Upper_Bound() ); + while(it2 != upper_it) + { + removeInterval(*it2); + it2++; + } + } + } // end while + + if (_itemsByXmin->size()) { + ///*DEBUG*/ intervalsize= intervalsize / _tilesByXmin->size(); + ///*DEBUG*/ contactssize= contactssize / _tilesByXmin->size(); + ///*DEBUG*/ intervaltime= intervaltime / _tilesByXmin->size(); + + ///*DEBUG*/ cmess1 << " -- FIN SWEEPLINE : intervalsize="<< intervalsize<< " contactssize=" < +#include +#include + +namespace Hurricane { + + class Box; + class Cell; + class Entity; + class BasicLayer; + class Record; + class Occurrence; + +} // End of Hurricane namespace. + + +namespace Equinox { + + using std::string; + + using Hurricane::BasicLayer; + using Hurricane::Occurrence; + using Hurricane::Box; + using Hurricane::DbU; + using Hurricane::Record; + + class Equi; + + + // ------------------------------------------------------------------- + // Class : "EQUINOX::Tile". + + class Tile : public Interval + { + + + + //Statics + public: + static Tile* create (const Occurrence, + const Box, + BasicLayer*, + Equi* equi = NULL); + + + //Functions + public: + inline void destroy (); + + public: + inline const Box& getBoundingBox (); + inline const Occurrence& getOccurrence () const; + inline BasicLayer* getBasicLayer () const; + inline Equi* getEqui () const; + inline void setEqui (Equi* equi); + + inline const DbU::Unit& getXmin () const; + inline const DbU::Unit& getYmin () const; + inline const DbU::Unit& getXmax () const; + inline const DbU::Unit& getYmax () const; + inline bool isEmpty () const; + inline virtual long GetLowPoint () const; + inline virtual long GetHighPoint () const; + /**/ bool intersect (const Tile* tile) const; + + inline virtual string _getTypeName () const; + /**/ virtual string _getString () const; + inline virtual Record* _getRecord () const; + + private: + /**/ const Occurrence _occurrence; + /**/ const Box _box; + /**/ BasicLayer* _basicLayer; + /**/ Equi* _equi; + + // Constructors & Destructors. + protected: + /**/ Tile (const Occurrence, + const Box, + BasicLayer*, + Equi* equi = NULL); + inline virtual ~Tile (); + inline virtual void _postCreate (); + inline virtual void _preDelete (); + private: + /**/ Tile (const Tile&); + /**/ Tile& operator= (const Tile&); + + }; // End of class Equi + + + // Inline Functions. + inline Equi* Tile::getEqui () const { return _equi; }; + inline const Box& Tile::getBoundingBox () { return _box; }; + inline const Occurrence& Tile::getOccurrence () const { return _occurrence; }; + inline BasicLayer* Tile::getBasicLayer () const { return _basicLayer; }; + inline void Tile::setEqui (Equi* equi) { _equi = equi; }; + + inline long Tile::GetLowPoint () const { return _box.getYMin(); } + inline long Tile::GetHighPoint () const { return _box.getYMax(); } + inline string Tile::_getTypeName () const { return "Equinox::Tile"; } + inline const DbU::Unit& Tile::getXmin () const { return _box.getXMin(); }; + inline const DbU::Unit& Tile::getYmin () const { return _box.getYMin(); }; + inline const DbU::Unit& Tile::getXmax () const { return _box.getXMax(); }; + inline const DbU::Unit& Tile::getYmax () const { return _box.getYMax(); }; + inline bool Tile::isEmpty () const { return _box.isEmpty(); }; + inline Record* Tile::_getRecord () const { return NULL; }; + inline void Tile::destroy () { _preDelete(); delete this; }; + inline void Tile::_postCreate () { }; + inline void Tile::_preDelete () { }; + inline /**/ Tile::~Tile () { }; + + + + + + + + +} // End of Equinox namespace. + + + + +#endif // __EQUINOX_TILE__ diff --git a/equinox/src/equinox/TileSweepLine.h b/equinox/src/equinox/TileSweepLine.h new file mode 100644 index 00000000..d780f0a4 --- /dev/null +++ b/equinox/src/equinox/TileSweepLine.h @@ -0,0 +1,43 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | =============================================================== | +// | C++ Header : "./TileSweepLine.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + +#ifndef _EQUINOX_TILESWEEPLINE_H +#define _EQUINOX_TILESWEEPLINE_H + +#include + +namespace Equinox { + + class Tile; + class EquinoxEngine; + template + class SweepLine; + + typedef SweepLine TileSweepLine; + +} + + + +#endif // _EQUINOX_TILESWEEPLINE_H diff --git a/equinox/src/equinox/Tiles.h b/equinox/src/equinox/Tiles.h new file mode 100644 index 00000000..7cdeb462 --- /dev/null +++ b/equinox/src/equinox/Tiles.h @@ -0,0 +1,128 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | =============================================================== | +// | C++ Header : "./Tiles.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __EQUINOX_TILES__ +#define __EQUINOX_TILES__ + +namespace Equinox { + + class Tile; + using namespace std; + + +// ********************************************************************************************************* +// Functeurs +// ********************************************************************************************************* + + template + class CompByXmin + // ****************** + { + public: bool operator()(const T1 t1, const T1 t2) + // ************************************** + { + if( t1->getXmin() < t2->getXmin() ) + return true; + + if( t1->getXmin() == t2->getXmin() ) { + if( t1->getYmin() < t2->getYmin() ) + return true; + + if( t1->getYmin() == t2->getYmin() ) + if( t1< t2 ) + return true; + } + return false; + } + }; + + + template + class CompByXmax + // ****************** + { + public: bool operator()(const T1 t1, const T1 t2) + // *************************************** + { + if( t1->getXmax() < t2->getXmax() ) + return true; + + if( t1->getXmax() == t2->getXmax() ) { + + if( t1->getYmax() < t2->getYmax() ) + return true; + + if( t1->getYmax() == t2->getYmax() ) + if(t1 < t2) + return true; + } + return false; + } + + }; + + + template + class CompByXmin_Upper_Bound + // *************************** + { + public: bool operator()(const T1 t1, const T1 t2) + // *************************************** + { + if( t1->getXmin() < t2->getXmin() ) + return true; + return false; + } + }; + + + template + class CompByXmax_Upper_Bound + // **************************** + { + + public: bool operator()(const T1 t1, const T1 t2) + // ************************************* + { + if( t1->getXmax() < t2->getXmax() ) + return true; + return false; + } + + }; + + + //typedef set > TilesByXmin; + //typedef set > TilesByXmax; + + typedef vector TileVector; +} // End of Equinox namespace. + + + + + + +#endif // __EQUINOX_TILES__ diff --git a/equinox/src/equinox/UnionFind.h b/equinox/src/equinox/UnionFind.h new file mode 100644 index 00000000..e012f466 --- /dev/null +++ b/equinox/src/equinox/UnionFind.h @@ -0,0 +1,60 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./equinox/UnionFind.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __EQUINOX_UNIONFIND__ +#define __EQUINOX_UNIONFIND__ + + +namespace Equinox { + + + class Tile; + class Equi; + + class UnionFind { + + public: + inline static Equi * getRootEqui (Tile* tile); /* internal inline */ + /**/ static Equi * getRootEquiWithCompression (Tile* tile); + /**/ static Equi * findValidEqui (Equi* equi); + + + + private : + /**/ UnionFind (); + /**/ UnionFind (const UnionFind&); + /**/ UnionFind& operator= (const UnionFind&); + + + }; + + +} //End of equinox namespace + + +#endif //End of __EQUINOX_UNIONFIND__ diff --git a/equinox/src/equinox/intervaltree.h.b b/equinox/src/equinox/intervaltree.h.b new file mode 100644 index 00000000..950c5df3 --- /dev/null +++ b/equinox/src/equinox/intervaltree.h.b @@ -0,0 +1,625 @@ +//#ifndef E_INTERVAL_TREE +//#define E_INTERVAL_TREE + +#ifndef INTERVALTREE_H +#define INTERVALTREE_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// The interval_tree.h and interval_tree.cc files contain code for +// interval trees implemented using red-black-trees as described in +// the book _Introduction_To_Algorithms_ by Cormen, Leisserson, +// and Rivest. + +// CONVENTIONS: +// Function names: Each word in a function name begins with +// a capital letter. An example funcntion name is +// CreateRedTree(a,b,c). Furthermore, each function name +// should begin with a capital letter to easily distinguish +// them from variables. +// +// Variable names: Each word in a variable name begins with +// a capital letter EXCEPT the first letter of the variable +// name. For example, int newLongInt. Global variables have +// names beginning with "g". An example of a global +// variable name is gNewtonsConstant. + + +#ifndef MAX_LONG +#define MAX_LONG LONG_MAX // some architechturs define INT_MAX not MAX_INT +#define MIN_LONG -MAX_LONG +#endif + +#define ITMax(a, b) ( (a > b) ? a : b ) + +//#ifndef MAX_INT +//#define MAX_INT INT_MAX // some architechturs define INT_MAX not MAX_INT +//#endif +// The Interval class is an Abstract Base Class. This means that no +// instance of the Interval class can exist. Only classes which +// inherit from the Interval class can exist. Furthermore any class +// which inherits from the Interval class must define the member +// functions GetLowPoint and GetHighPoint. +// +// The GetLowPoint should return the lowest point of the interval and +// the GetHighPoint should return the highest point of the interval. + + +namespace Equinox { + + using std::stack; + using Hurricane::Error; + + +# if !defined(__DOXYGEN_PROCESSOR__) + +static inline bool Overlap(long& a1, long& a2, long& b1, long& b2) { +// ***************************************************************** + if (a1 <= b1) { + return( (b1 <= a2) ); + } else { + return( (a1 <= b2) ); + } +} + +#endif + + +class IntervalTreeNode { +// ********************* + + friend class IntervalTree; + public: + IntervalTreeNode(Interval * ); + +# if !defined(__DOXYGEN_PROCESSOR__) + void Print(IntervalTreeNode*, IntervalTreeNode*) const; + IntervalTreeNode(); + ~IntervalTreeNode(); + + protected: + Interval * storedInterval; + long key; + long high; + long maxHigh; + long red; /* if red=0 then the node is black */ + IntervalTreeNode * left; + IntervalTreeNode * right; + IntervalTreeNode * parent; +# endif +}; + + +# if !defined(__DOXYGEN_PROCESSOR__) + +struct it_recursion_node { +// *********************** + +public: + /* this structure stores the information needed when we take the */ + /* right branch in searching for intervals but possibly come back */ + /* and check the left branch as well. */ + + IntervalTreeNode * start_node; + unsigned long parentIndex; + long tryRightBranch; +} ; + +#endif + + +class IntervalTree { +// ***************** + +// constructors +// ************ + public: IntervalTree(); + + +// destructors +// *********** + public: ~IntervalTree(); + + +// Prints +// ****** +# if !defined(__DOXYGEN_PROCESSOR__) + + public: void Print() const; + + + +inline void * SafeMalloc(size_t size) { + void * result; + + if ( (result = malloc(size)) ) { /* assignment intentional */ + return(result); + } else { + char errorMessagePartOne [200]; + char errorMessagePartTwo [200]; + strcat(errorMessagePartOne,errorMessagePartTwo); + throw Error("Bad malloc"); + return(0); + } +} + + + + +inline void * SafeCalloc(int numberOfElements , size_t size) { + void * result; + + if ( (result = calloc(numberOfElements, size)) ) + { /* assignment intentional in above line */ + return(result); + } else { + printf(" Exiting Program.\n"); + throw Error("Bad calloc"); + return(0); + } +} + + + + + + + + + + + + + +// Operations +// ********** + public : void FixUpMaxHigh(IntervalTreeNode * x) { + // ***************************************** + while(x != root) { + x->maxHigh=ITMax(x->high,ITMax(x->left->maxHigh,x->right->maxHigh)); + x=x->parent; + } + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #endif + }; + + + protected: void LeftRotate(IntervalTreeNode* x) { + // *********************************** + + IntervalTreeNode* y; + + /* I originally wrote this function to use the sentinel for */ + /* nil to avoid checking for nil. However this introduces a */ + /* very subtle bug because sometimes this function modifies */ + /* the parent pointer of nil. This can be a problem if a */ + /* function which calls LeftRotate also uses the nil sentinel */ + /* and expects the nil sentinel's parent pointer to be unchanged */ + /* after calling this function. For example, when DeleteFixUP */ + /* calls LeftRotate it expects the parent pointer of nil to be */ + /* unchanged. */ + + y=x->right; + x->right=y->left; + + if (y->left != nil) y->left->parent=x; /* used to use sentinel here */ + /* and do an unconditional assignment instead of testing for nil */ + + y->parent=x->parent; + + /* instead of checking if x->parent is the root as in the book, we */ + /* count on the root sentinel to implicitly take care of this case */ + if( x == x->parent->left) { + x->parent->left=y; + } else { + x->parent->right=y; + } + y->left=x; + x->parent=y; + + x->maxHigh=ITMax(x->left->maxHigh,ITMax(x->right->maxHigh,x->high)); + y->maxHigh=ITMax(x->maxHigh,ITMax(y->right->maxHigh,y->high)); + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not red in ITLeftRotate"); + Assert((nil->maxHigh=MIN_LONG), + "nil->maxHigh != MIN_LONG in ITLeftRotate"); + #endif + }; + + + protected: void RightRotate(IntervalTreeNode* y) { + // *************************************** + IntervalTreeNode* x; + + /* I originally wrote this function to use the sentinel for */ + /* nil to avoid checking for nil. However this introduces a */ + /* very subtle bug because sometimes this function modifies */ + /* the parent pointer of nil. This can be a problem if a */ + /* function which calls LeftRotate also uses the nil sentinel */ + /* and expects the nil sentinel's parent pointer to be unchanged */ + /* after calling this function. For example, when DeleteFixUP */ + /* calls LeftRotate it expects the parent pointer of nil to be */ + /* unchanged. */ + + x=y->left; + y->left=x->right; + + if (nil != x->right) x->right->parent=y; /*used to use sentinel here */ + /* and do an unconditional assignment instead of testing for nil */ + + /* instead of checking if x->parent is the root as in the book, we */ + /* count on the root sentinel to implicitly take care of this case */ + x->parent=y->parent; + if( y == y->parent->left) { + y->parent->left=x; + } else { + y->parent->right=x; + } + x->right=y; + y->parent=x; + + y->maxHigh=ITMax(y->left->maxHigh,ITMax(y->right->maxHigh,y->high)); + x->maxHigh=ITMax(x->left->maxHigh,ITMax(y->maxHigh,x->high)); + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not red in ITRightRotate"); + Assert((nil->maxHigh=MIN_LONG), + "nil->maxHigh != MIN_LONG in ITRightRotate"); + #endif + }; + +# endif + + public: Interval * DeleteNode(IntervalTreeNode * z) + // ***************************************************** + { + IntervalTreeNode* y; + IntervalTreeNode* x; + Interval * returnValue = z->storedInterval; + + y= ((z->left == nil) || (z->right == nil)) ? z : GetSuccessorOf(z); + x= (y->left == nil) ? y->right : y->left; + if (root == (x->parent = y->parent)) { /* assignment of y->p to x->p is intentional */ + root->left=x; + } else { + if (y == y->parent->left) { + y->parent->left=x; + } else { + y->parent->right=x; + } + } + if (y != z) { /* y should not be nil in this case */ + + #ifdef DEBUG_ASSERT + Assert( (y!=nil),"y is nil in DeleteNode \n"); + #endif + /* y is the node to splice out and x is its child */ + + y->maxHigh = MIN_LONG; + y->left=z->left; + y->right=z->right; + y->parent=z->parent; + z->left->parent=z->right->parent=y; + if (z == z->parent->left) { + z->parent->left=y; + } else { + z->parent->right=y; + } + FixUpMaxHigh(x->parent); + if (!(y->red)) { + y->red = z->red; + DeleteFixUp(x); + } else + y->red = z->red; + delete z; + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not black in ITDelete"); + Assert((nil->maxHigh=MIN_LONG),"nil->maxHigh != MIN_LONG in ITDelete"); + #endif + } else { + FixUpMaxHigh(x->parent); + if (!(y->red)) DeleteFixUp(x); + delete y; + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not black in ITDelete"); + Assert((nil->maxHigh=MIN_LONG),"nil->maxHigh != MIN_LONG in ITDelete"); + #endif + } + return returnValue; + }; + +# if !defined(__DOXYGEN_PROCESSOR__) + + protected: void TreeInsertHelp(IntervalTreeNode * z) + // ************************************** + { + /* This function should only be called by InsertITTree (see above) */ + IntervalTreeNode* x; + IntervalTreeNode* y; + + z->left=z->right=nil; + y=root; + x=root->left; + while( x != nil) { + y=x; + if ( x->key > z->key) { + x=x->left; + } else { /* x->key <= z->key */ + x=x->right; + } + } + z->parent=y; + if ( (y == root) || + (y->key > z->key) ) { + y->left=z; + } else { + y->right=z; + } + + #if defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not red in ITTreeInsertHelp"); + Assert((nil->maxHigh=MIN_LONG), + "nil->maxHigh != MIN_LONG in ITTreeInsertHelp"); + #endif + }; + + + protected: void DeleteFixUp(IntervalTreeNode * x) + // *********************************** + { + IntervalTreeNode * w; + IntervalTreeNode * rootLeft = root->left; + + while( (!x->red) && (rootLeft != x)) { + if (x == x->parent->left) { + w=x->parent->right; + if (w->red) { + w->red=0; + x->parent->red=1; + LeftRotate(x->parent); + w=x->parent->right; + } + if ( (!w->right->red) && (!w->left->red) ) { + w->red=1; + x=x->parent; + } else { + if (!w->right->red) { + w->left->red=0; + w->red=1; + RightRotate(w); + w=x->parent->right; + } + w->red=x->parent->red; + x->parent->red=0; + w->right->red=0; + LeftRotate(x->parent); + x=rootLeft; /* this is to exit while loop */ + } + } else { /* the code below is has left and right switched from above */ + w=x->parent->left; + if (w->red) { + w->red=0; + x->parent->red=1; + RightRotate(x->parent); + w=x->parent->left; + } + if ( (!w->right->red) && (!w->left->red) ) { + w->red=1; + x=x->parent; + } else { + if (!w->left->red) { + w->right->red=0; + w->red=1; + LeftRotate(w); + w=x->parent->left; + } + w->red=x->parent->red; + x->parent->red=0; + w->left->red=0; + RightRotate(x->parent); + x=rootLeft; /* this is to exit while loop */ + } + } + } + x->red=0; + + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not black in ITDeleteFixUp"); + Assert((nil->maxHigh=MIN_LONG), + "nil->maxHigh != MIN_LONG in ITDeleteFixUp"); + #endif + + }; + +# endif + + public: IntervalTreeNode * Insert(Interval * newInterval) + // ********************************************************** + { + IntervalTreeNode * y; + IntervalTreeNode * x; + IntervalTreeNode * newNode; + + x = new IntervalTreeNode(newInterval); + TreeInsertHelp(x); + FixUpMaxHigh(x->parent); + newNode = x; + x->red=1; + while(x->parent->red) { /* use sentinel instead of checking for root */ + if (x->parent == x->parent->parent->left) { + y=x->parent->parent->right; + if (y->red) { + x->parent->red=0; + y->red=0; + x->parent->parent->red=1; + x=x->parent->parent; + } else { + if (x == x->parent->right) { + x=x->parent; + LeftRotate(x); + } + x->parent->red=0; + x->parent->parent->red=1; + RightRotate(x->parent->parent); + } + } else { /* case for x->parent == x->parent->parent->right */ + /* this part is just like the section above with */ + /* left and right interchanged */ + y=x->parent->parent->left; + if (y->red) { + x->parent->red=0; + y->red=0; + x->parent->parent->red=1; + x=x->parent->parent; + } else { + if (x == x->parent->left) { + x=x->parent; + RightRotate(x); + } + x->parent->red=0; + x->parent->parent->red=1; + LeftRotate(x->parent->parent); + } + } + } + root->left->red=0; + return(newNode); + + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not red in ITTreeInsert"); + Assert(!root->red,"root not red in ITTreeInsert"); + Assert((nil->maxHigh=MIN_LONG), + "nil->maxHigh != MIN_LONG in ITTreeInsert"); + #endif + }; + + + + /* The basic idea for the function below is to take the IntervalSearch */ + /* function from the book and modify to find all overlapping intervals */ + /* instead of just one. This means that any time we take the left */ + /* branch down the tree we must also check the right branch if and only if */ + /* we find an overlapping interval in that left branch. Note this is a */ + /* recursive condition because if we go left at the root then go left */ + /* again at the first left child and find an overlap in the left subtree */ + /* of the left child of root we must recursively check the right subtree */ + /* of the left child of root as well as the right child of root. */ + public: stack * Enumerate(long low, long high) + // ***************************************************** + { + stack * enumResultStack; + IntervalTreeNode* x=root->left; + long stuffToDo = (x != nil); + + // Possible speed up: add min field to prune right searches // + + #ifdef DEBUG_ASSERT + Assert((recursionNodeStackTop == 0), + "recursionStack not empty when entering IntervalTree::Enumerate"); + #endif + currentParent = 0; + enumResultStack = new stack; + + while(stuffToDo) { + if (Overlap(low,high,x->key,x->high) ) { + enumResultStack->push(x->storedInterval); + recursionNodeStack[currentParent].tryRightBranch=1; + } + if(x->left->maxHigh >= low) { // implies x != nil + if ( recursionNodeStackTop == recursionNodeStackSize ) { + recursionNodeStackSize *= 2; + recursionNodeStack = (it_recursion_node *) + realloc(recursionNodeStack, + recursionNodeStackSize * sizeof(it_recursion_node)); + if (recursionNodeStack == NULL) + throw Error("realloc failed in IntervalTree::Enumerate\n"); + } + recursionNodeStack[recursionNodeStackTop].start_node = x; + recursionNodeStack[recursionNodeStackTop].tryRightBranch = 0; + recursionNodeStack[recursionNodeStackTop].parentIndex = currentParent; + currentParent = recursionNodeStackTop++; + x = x->left; + } else { + x = x->right; + } + stuffToDo = (x != nil); + while( (!stuffToDo) && (recursionNodeStackTop > 1) ) { + if(recursionNodeStack[--recursionNodeStackTop].tryRightBranch) { + x=recursionNodeStack[recursionNodeStackTop].start_node->right; + currentParent=recursionNodeStack[recursionNodeStackTop].parentIndex; + recursionNodeStack[currentParent].tryRightBranch=1; + stuffToDo = ( x != nil); + } + } + } + #ifdef DEBUG_ASSERT + Assert((recursionNodeStackTop == 1), + "recursionStack not empty when exiting IntervalTree::Enumerate"); + #endif + return(enumResultStack); + }; + +# if !defined(__DOXYGEN_PROCESSOR__) + + protected: void CheckAssumptions() const; + + /* A sentinel is used for root and for nil. These sentinels are */ + /* created when ITTreeCreate is caled. root->left should always */ + /* point to the node which is the root of the tree. nil points to a */ + /* node which should always be black but has aribtrary children and */ + /* parent and no key or info. The point of using these sentinels is so */ + /* that the root and nil nodes do not require special cases in the code */ + + protected: IntervalTreeNode * root; + protected: IntervalTreeNode * nil; + + public: IntervalTreeNode * GetPredecessorOf(IntervalTreeNode *) const; + + public: IntervalTreeNode * GetSuccessorOf(IntervalTreeNode * ) const; + protected: void TreePrintHelper(IntervalTreeNode *) const; + protected: void CheckMaxHighFields(IntervalTreeNode *) const; + protected: long CheckMaxHighFieldsHelper(IntervalTreeNode * y, + const long currentHigh, + long match) const; + +// Attributs +// ********* + private: unsigned long recursionNodeStackSize; + private: it_recursion_node * recursionNodeStack; + private: unsigned long currentParent; + private: unsigned long recursionNodeStackTop; +# endif + + +}; + + +} // end of namespace +#endif + + + + + + diff --git a/equinox/src/equinox/misc.h.b b/equinox/src/equinox/misc.h.b new file mode 100644 index 00000000..7fac7491 --- /dev/null +++ b/equinox/src/equinox/misc.h.b @@ -0,0 +1,166 @@ +#ifndef INC_E_MISC_DOT_H +#define INC_E_MISC_DOT_H +#include +#include +#include +#include +//#include +#include + + +namespace EQUINOX { + +/* CONVENTIONS */ +/* */ +/* Function names: Each word in a function name begins with */ +/* a capital letter. An example funcntion name is */ +/* CreateRedTree(a,b,c). Furthermore, each function name */ +/* should begin with a capital letter to easily distinguish */ +/* them from variables. */ +/* */ +/* Variable names: Each word in a variable name begins with */ +/* a capital letter EXCEPT the first letter of the variable */ +/* name. For example, int newLongInt. Global variables have */ +/* names beginning with "g" or "global:. */ +/* An example of a global variable name is gNewtonsConstant. */ + + +// The ExitProgramMacro is used to exit the program when a +// catastrophe occurs (e.g. assertion failure). You can define +// your own version of the ExitProgramMacro to dump core, log +// things or do something else that you want. If the symbol +// ExitProgramMacro is not defined though, then a default +// definition is created. + +#ifndef ExitProgramMacro + +#define ExitProgramMacro(a) { \ +printf("Error: "); printf(a); \ +printf("Exiting from line %i in file %s\n",__LINE__,__FILE__); \ +printf("\nCausing Segmentation Fault to exit ungracefully\n"); \ + int * junk = NULL; (*junk)++;\ + printf("%p\n",junk);} + +// printf("%i\n",(int)junk);} + +#endif /* ends #ifndef ExitProgramMacro */ + + +#define VERIFY(condition) \ +if (!(condition)) { \ +fprintf(stderr, "Assumption \"%s\"\nFailed in file %s: at line:%i\n", \ +#condition,__FILE__,__LINE__); \ +ExitProgramMacro(#condition);} + +#ifdef CHECK_ASSUMPTIONS +#define ASSUME(x) VERIFY(x) +#else +#define ASSUME(x) ; +#endif + +/***********************************************************************/ +/* FUNCTION: void Assert(int assertion, char* error) */ +/**/ +/* INPUTS: assertion should be a predicated that the programmer */ +/* assumes to be true. If this assumption is not true the message */ +/* error is printed and the program exits. */ +/**/ +/* OUTPUT: None. */ +/**/ +/* Modifies input: none */ +/**/ +/* Note: If DEBUG_ASSERT is not defined then assertions should not */ +/* be in use as they will slow down the code. Therefore the */ +/* compiler will complain if an assertion is used when */ +/* DEBUG_ASSERT is undefined. */ +/***********************************************************************/ + + +inline void Assert(int assertion, char* error) { + if(!assertion) { + printf("Assertion Failed: %s\n",error); + ExitProgramMacro("Exiting From Function Assert(...)\n"); + } +} + +/***********************************************************************/ +/* FUNCTION: SafeMalloc */ +/**/ +/* INPUTS: size is the size to malloc */ +/**/ +/* OUTPUT: returns pointer to allocated memory if succesful */ +/**/ +/* EFFECT: mallocs new memory. If malloc fails, prints error message */ +/* and terminates program. */ +/**/ +/* Modifies Input: none */ +/**/ +/***********************************************************************/ + +inline void * SafeMalloc(size_t size) { + void * result; + + if ( (result = malloc(size)) ) { /* assignment intentional */ + return(result); + } else { + char errorMessagePartOne [200]; + char errorMessagePartTwo [200]; + sprintf(errorMessagePartOne, + "Exiting From SafeMalloc because malloc of size %i failed.\n", + size); + sprintf(errorMessagePartTwo, + "Calling sbrk(0) gives %x\n",(long)sbrk(0)); + strcat(errorMessagePartOne,errorMessagePartTwo); + ExitProgramMacro(errorMessagePartOne); + return(0); + } +} + +/***********************************************************************/ +/* FUNCTION: SafeCalloc */ +/**/ +/* INPUTS: size is the size to calloc */ +/**/ +/* OUTPUT: returns pointer to allocated memory if succesful */ +/**/ +/* EFFECT: callocs new memory. If calloc fails, prints error message */ +/* and terminates program. */ +/**/ +/* Modifies Input: none */ +/**/ +/***********************************************************************/ + +inline void * SafeCalloc(int numberOfElements , size_t size) { + void * result; + + if ( (result = calloc(numberOfElements, size)) ) + { /* assignment intentional in above line */ + return(result); + } else { + printf("memory overflow: calloc failed in SafeCalloc(%i,%i).", + numberOfElements, size); + printf("sbrk(0) gives %x\n",(long)sbrk(0)); + printf(" Exiting Program.\n"); + ExitProgramMacro("Exiting From Function SafeCalloc(...)\n"); + return(0); + } +} + +/* NullFunction does nothing it is included so that it can be passed */ +/* as a function to RBTreeCreate when no other suitable function has */ +/* been defined */ + +inline void NullFunction(void * ) { ; } +inline void NullFunction(const void * ) { ; } + +} + +#endif + + + + + + + + diff --git a/equinox/src/intervalTree/src/IntervalTree.cpp b/equinox/src/intervalTree/src/IntervalTree.cpp new file mode 100644 index 00000000..4d767632 --- /dev/null +++ b/equinox/src/intervalTree/src/IntervalTree.cpp @@ -0,0 +1,410 @@ +#include +#include + +// If the symbol CHECK_INTERVAL_TREE_ASSUMPTIONS is defined then the +// code does a lot of extra checking to make sure certain assumptions +// are satisfied. This only needs to be done if you suspect bugs are +// present or if you make significant changes and want to make sure +// your changes didn't mess anything up. +// #define CHECK_INTERVAL_TREE_ASSUMPTIONS 1 + +using namespace std; + +#include "equinox/IntervalTree.h" + +namespace Equinox { + +//long MIN_LONG=-MAX_LONG; + +// define a function to find the maximum of two objects. +#define ITMax(a, b) ( (a > b) ? a : b ) + +IntervalTreeNode::IntervalTreeNode(){ +}; + +IntervalTreeNode::IntervalTreeNode(Interval * newInterval) + : storedInterval (newInterval) , + key(newInterval->GetLowPoint()), + high(newInterval->GetHighPoint()) , + maxHigh(high) { +}; +IntervalTreeNode::~IntervalTreeNode(){ +}; +Interval::Interval(){ +}; +Interval::~Interval(){ +}; + +void Interval::Print() const { + cout << "No Print Method defined for instance of Interval" << endl; +} + +IntervalTree::IntervalTree() +{ + nil = new IntervalTreeNode; + nil->left = nil->right = nil->parent = nil; + nil->red = 0; + nil->key = nil->high = nil->maxHigh = MIN_LONG; + nil->storedInterval = NULL; + + root = new IntervalTreeNode; + root->parent = root->left = root->right = nil; + root->key = root->high = root->maxHigh = MAX_LONG; + root->red=0; + root->storedInterval = NULL; + + /* the following are used for the Enumerate function */ + recursionNodeStackSize = 128; + recursionNodeStack = (it_recursion_node *) + SafeMalloc(recursionNodeStackSize*sizeof(it_recursion_node)); + recursionNodeStackTop = 1; + recursionNodeStack[0].start_node = NULL; + +} + +/***********************************************************************/ +/* FUNCTION: LeftRotate */ +/**/ +/* INPUTS: the node to rotate on */ +/**/ +/* OUTPUT: None */ +/**/ +/* Modifies Input: this, x */ +/**/ +/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */ +/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */ +/* makes the parent of x be to the left of x, x the parent of */ +/* its parent before the rotation and fixes other pointers */ +/* accordingly. Also updates the maxHigh fields of x and y */ +/* after rotation. */ +/***********************************************************************/ + + +/***********************************************************************/ +/* FUNCTION: RighttRotate */ +/**/ +/* INPUTS: node to rotate on */ +/**/ +/* OUTPUT: None */ +/**/ +/* Modifies Input?: this, y */ +/**/ +/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */ +/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */ +/* makes the parent of x be to the left of x, x the parent of */ +/* its parent before the rotation and fixes other pointers */ +/* accordingly. Also updates the maxHigh fields of x and y */ +/* after rotation. */ +/***********************************************************************/ + + +/***********************************************************************/ +/* FUNCTION: TreeInsertHelp */ +/**/ +/* INPUTS: z is the node to insert */ +/**/ +/* OUTPUT: none */ +/**/ +/* Modifies Input: this, z */ +/**/ +/* EFFECTS: Inserts z into the tree as if it were a regular binary tree */ +/* using the algorithm described in _Introduction_To_Algorithms_ */ +/* by Cormen et al. This funciton is only intended to be called */ +/* by the InsertTree function and not by the user */ +/***********************************************************************/ + + +/***********************************************************************/ +/* FUNCTION: FixUpMaxHigh */ +/**/ +/* INPUTS: x is the node to start from*/ +/**/ +/* OUTPUT: none */ +/**/ +/* Modifies Input: this */ +/**/ +/* EFFECTS: Travels up to the root fixing the maxHigh fields after */ +/* an insertion or deletion */ +/***********************************************************************/ + + + +/* Before calling InsertNode the node x should have its key set */ + +/***********************************************************************/ +/* FUNCTION: InsertNode */ +/**/ +/* INPUTS: newInterval is the interval to insert*/ +/**/ +/* OUTPUT: This function returns a pointer to the newly inserted node */ +/* which is guarunteed to be valid until this node is deleted. */ +/* What this means is if another data structure stores this */ +/* pointer then the tree does not need to be searched when this */ +/* is to be deleted. */ +/**/ +/* Modifies Input: tree */ +/**/ +/* EFFECTS: Creates a node node which contains the appropriate key and */ +/* info pointers and inserts it into the tree. */ +/***********************************************************************/ + + + +/***********************************************************************/ +/* FUNCTION: GetSuccessorOf */ +/**/ +/* INPUTS: x is the node we want the succesor of */ +/**/ +/* OUTPUT: This function returns the successor of x or NULL if no */ +/* successor exists. */ +/**/ +/* Modifies Input: none */ +/**/ +/* Note: uses the algorithm in _Introduction_To_Algorithms_ */ +/***********************************************************************/ + +IntervalTreeNode * IntervalTree::GetSuccessorOf(IntervalTreeNode * x) const + // *********************************************************************** + { + IntervalTreeNode* y; + + if (nil!= (y = x->right)) { /* assignment to y is intentional */ + while(y->left != nil) { /* returns the minium of the right subtree of x */ + y=y->left; + } + return(y); + } else { + y=x->parent; + while(x == y->right) { /* sentinel used instead of checking for nil */ + x=y; + y=y->parent; + } + if (y == root) return(nil); + return(y); + } + } + + + +/***********************************************************************/ +/* FUNCTION: GetPredecessorOf */ +/**/ +/* INPUTS: x is the node to get predecessor of */ +/**/ +/* OUTPUT: This function returns the predecessor of x or NULL if no */ +/* predecessor exists. */ +/**/ +/* Modifies Input: none */ +/**/ +/* Note: uses the algorithm in _Introduction_To_Algorithms_ */ +/***********************************************************************/ + +IntervalTreeNode * IntervalTree::GetPredecessorOf(IntervalTreeNode * x) const { + IntervalTreeNode* y; + + if (nil != (y = x->left)) { /* assignment to y is intentional */ + while(y->right != nil) { /* returns the maximum of the left subtree of x */ + y=y->right; + } + return(y); + } else { + y=x->parent; + while(x == y->left) { + if (y == root) return(nil); + x=y; + y=y->parent; + } + return(y); + } +} + +/***********************************************************************/ +/* FUNCTION: Print */ +/**/ +/* INPUTS: none */ +/**/ +/* OUTPUT: none */ +/**/ +/* EFFECTS: This function recursively prints the nodes of the tree */ +/* inorder. */ +/**/ +/* Modifies Input: none */ +/**/ +/* Note: This function should only be called from ITTreePrint */ +/***********************************************************************/ + +void IntervalTreeNode::Print(IntervalTreeNode * nil, + IntervalTreeNode * root) const { + storedInterval->Print(); + printf(", k=%li, h=%li, mH=%li",key,high,maxHigh); + printf(" l->key="); + if( left == nil) printf("NULL"); else printf("%li",left->key); + printf(" r->key="); + if( right == nil) printf("NULL"); else printf("%li",right->key); + printf(" p->key="); + if( parent == root) printf("NULL"); else printf("%li",parent->key); + printf(" red=%li\n",red); +} + +void IntervalTree::TreePrintHelper( IntervalTreeNode* x) const { + + if (x != nil) { + TreePrintHelper(x->left); + x->Print(nil,root); + TreePrintHelper(x->right); + } +} + +IntervalTree::~IntervalTree() { + IntervalTreeNode * x = root->left; + stack stuffToFree; + + if (x != nil) { + if (x->left != nil) { + stuffToFree.push(x->left); + } + if (x->right != nil) { + stuffToFree.push(x->right); + } + // delete x->storedInterval; + delete x; + while(!stuffToFree.empty() ) { + x = stuffToFree.top(); + stuffToFree.pop(); + if (x->left != nil) { + stuffToFree.push(x->left); + } + if (x->right != nil) { + stuffToFree.push(x->right); + } + // delete x->storedInterval; + delete x; + } + } + delete nil; + delete root; + free(recursionNodeStack); +} + + +/***********************************************************************/ +/* FUNCTION: Print */ +/**/ +/* INPUTS: none */ +/**/ +/* OUTPUT: none */ +/**/ +/* EFFECT: This function recursively prints the nodes of the tree */ +/* inorder. */ +/**/ +/* Modifies Input: none */ +/**/ +/***********************************************************************/ + +void IntervalTree::Print() const { + TreePrintHelper(root->left); +} + +/***********************************************************************/ +/* FUNCTION: DeleteFixUp */ +/**/ +/* INPUTS: x is the child of the spliced */ +/* out node in DeleteNode. */ +/**/ +/* OUTPUT: none */ +/**/ +/* EFFECT: Performs rotations and changes colors to restore red-black */ +/* properties after a node is deleted */ +/**/ +/* Modifies Input: this, x */ +/**/ +/* The algorithm from this function is from _Introduction_To_Algorithms_ */ +/***********************************************************************/ + + + +/***********************************************************************/ +/* FUNCTION: DeleteNode */ +/**/ +/* INPUTS: tree is the tree to delete node z from */ +/**/ +/* OUTPUT: returns the Interval stored at deleted node */ +/**/ +/* EFFECT: Deletes z from tree and but don't call destructor */ +/* Then calls FixUpMaxHigh to fix maxHigh fields then calls */ +/* ITDeleteFixUp to restore red-black properties */ +/**/ +/* Modifies Input: z */ +/**/ +/* The algorithm from this function is from _Introduction_To_Algorithms_ */ +/***********************************************************************/ + + + +/***********************************************************************/ +/* FUNCTION: Enumerate */ +/**/ +/* INPUTS: tree is the tree to look for intervals overlapping the */ +/* closed interval [low,high] */ +/**/ +/* OUTPUT: stack containing pointers to the nodes overlapping */ +/* [low,high] */ +/**/ +/* Modifies Input: none */ +/**/ +/* EFFECT: Returns a stack containing pointers to nodes containing */ +/* intervals which overlap [low,high] in O(max(N,k*log(N))) */ +/* where N is the number of intervals in the tree and k is */ +/* the number of overlapping intervals */ +/**/ +/* Note: This basic idea for this function comes from the */ +/* _Introduction_To_Algorithms_ book by Cormen et al, but */ +/* modifications were made to return all overlapping intervals */ +/* instead of just the first overlapping interval as in the */ +/* book. The natural way to do this would require recursive */ +/* calls of a basic search function. I translated the */ +/* recursive version into an interative version with a stack */ +/* as described below. */ +/***********************************************************************/ + + + + + +long IntervalTree::CheckMaxHighFieldsHelper(IntervalTreeNode * y, + const long currentHigh, + long match) const +{ + if (y != nil) { + match = CheckMaxHighFieldsHelper(y->left,currentHigh,match) ? + 1 : match; + if (y->high == currentHigh) + match = 1; + match = CheckMaxHighFieldsHelper(y->right,currentHigh,match) ? + 1 : match; + } + return match; +} + + + +/* Make sure the maxHigh fields for everything makes sense. * + * If something is wrong, print a warning and exit */ +void IntervalTree::CheckMaxHighFields(IntervalTreeNode * x) const { + if (x != nil) { + CheckMaxHighFields(x->left); + if(!(CheckMaxHighFieldsHelper(x,x->maxHigh,0) > 0)) { + throw Error("pouet"); + } + CheckMaxHighFields(x->right); + } +} + +void IntervalTree::CheckAssumptions() const { + + CheckMaxHighFields(root->left); +} + + +} // end of namespace + diff --git a/equinox/src/intervalTree/src/equinox/Interval.h b/equinox/src/intervalTree/src/equinox/Interval.h new file mode 100644 index 00000000..7249244f --- /dev/null +++ b/equinox/src/intervalTree/src/equinox/Interval.h @@ -0,0 +1,54 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | E q u i n o x - E x t r a c t o r | +// | | +// | Author : Wu Yife | +// | E-mail : Wu.Yifei@lip6.fr | +// | | +// | Updater : Bodin bruno | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./equinox/Interval.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __EQUINOX_INTERVAL__ +#define __EQUINOX_INTERVAL__ + +namespace Equinox { + + // ------------------------------------------------------------------- + // Class : "EQUINOX::Interval". + + + class Interval { + + public: + /**/ Interval (); + /**/ virtual ~Interval (); + /**/ virtual long GetLowPoint () const = 0; + /**/ virtual long GetHighPoint () const = 0; + /**/ virtual void Print () const; + + }; + + + +} // end of namespace + + +#endif //__EQUINOX_INTERVAL__ diff --git a/equinox/src/intervalTree/src/equinox/IntervalTree.h b/equinox/src/intervalTree/src/equinox/IntervalTree.h new file mode 100644 index 00000000..950c5df3 --- /dev/null +++ b/equinox/src/intervalTree/src/equinox/IntervalTree.h @@ -0,0 +1,625 @@ +//#ifndef E_INTERVAL_TREE +//#define E_INTERVAL_TREE + +#ifndef INTERVALTREE_H +#define INTERVALTREE_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// The interval_tree.h and interval_tree.cc files contain code for +// interval trees implemented using red-black-trees as described in +// the book _Introduction_To_Algorithms_ by Cormen, Leisserson, +// and Rivest. + +// CONVENTIONS: +// Function names: Each word in a function name begins with +// a capital letter. An example funcntion name is +// CreateRedTree(a,b,c). Furthermore, each function name +// should begin with a capital letter to easily distinguish +// them from variables. +// +// Variable names: Each word in a variable name begins with +// a capital letter EXCEPT the first letter of the variable +// name. For example, int newLongInt. Global variables have +// names beginning with "g". An example of a global +// variable name is gNewtonsConstant. + + +#ifndef MAX_LONG +#define MAX_LONG LONG_MAX // some architechturs define INT_MAX not MAX_INT +#define MIN_LONG -MAX_LONG +#endif + +#define ITMax(a, b) ( (a > b) ? a : b ) + +//#ifndef MAX_INT +//#define MAX_INT INT_MAX // some architechturs define INT_MAX not MAX_INT +//#endif +// The Interval class is an Abstract Base Class. This means that no +// instance of the Interval class can exist. Only classes which +// inherit from the Interval class can exist. Furthermore any class +// which inherits from the Interval class must define the member +// functions GetLowPoint and GetHighPoint. +// +// The GetLowPoint should return the lowest point of the interval and +// the GetHighPoint should return the highest point of the interval. + + +namespace Equinox { + + using std::stack; + using Hurricane::Error; + + +# if !defined(__DOXYGEN_PROCESSOR__) + +static inline bool Overlap(long& a1, long& a2, long& b1, long& b2) { +// ***************************************************************** + if (a1 <= b1) { + return( (b1 <= a2) ); + } else { + return( (a1 <= b2) ); + } +} + +#endif + + +class IntervalTreeNode { +// ********************* + + friend class IntervalTree; + public: + IntervalTreeNode(Interval * ); + +# if !defined(__DOXYGEN_PROCESSOR__) + void Print(IntervalTreeNode*, IntervalTreeNode*) const; + IntervalTreeNode(); + ~IntervalTreeNode(); + + protected: + Interval * storedInterval; + long key; + long high; + long maxHigh; + long red; /* if red=0 then the node is black */ + IntervalTreeNode * left; + IntervalTreeNode * right; + IntervalTreeNode * parent; +# endif +}; + + +# if !defined(__DOXYGEN_PROCESSOR__) + +struct it_recursion_node { +// *********************** + +public: + /* this structure stores the information needed when we take the */ + /* right branch in searching for intervals but possibly come back */ + /* and check the left branch as well. */ + + IntervalTreeNode * start_node; + unsigned long parentIndex; + long tryRightBranch; +} ; + +#endif + + +class IntervalTree { +// ***************** + +// constructors +// ************ + public: IntervalTree(); + + +// destructors +// *********** + public: ~IntervalTree(); + + +// Prints +// ****** +# if !defined(__DOXYGEN_PROCESSOR__) + + public: void Print() const; + + + +inline void * SafeMalloc(size_t size) { + void * result; + + if ( (result = malloc(size)) ) { /* assignment intentional */ + return(result); + } else { + char errorMessagePartOne [200]; + char errorMessagePartTwo [200]; + strcat(errorMessagePartOne,errorMessagePartTwo); + throw Error("Bad malloc"); + return(0); + } +} + + + + +inline void * SafeCalloc(int numberOfElements , size_t size) { + void * result; + + if ( (result = calloc(numberOfElements, size)) ) + { /* assignment intentional in above line */ + return(result); + } else { + printf(" Exiting Program.\n"); + throw Error("Bad calloc"); + return(0); + } +} + + + + + + + + + + + + + +// Operations +// ********** + public : void FixUpMaxHigh(IntervalTreeNode * x) { + // ***************************************** + while(x != root) { + x->maxHigh=ITMax(x->high,ITMax(x->left->maxHigh,x->right->maxHigh)); + x=x->parent; + } + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #endif + }; + + + protected: void LeftRotate(IntervalTreeNode* x) { + // *********************************** + + IntervalTreeNode* y; + + /* I originally wrote this function to use the sentinel for */ + /* nil to avoid checking for nil. However this introduces a */ + /* very subtle bug because sometimes this function modifies */ + /* the parent pointer of nil. This can be a problem if a */ + /* function which calls LeftRotate also uses the nil sentinel */ + /* and expects the nil sentinel's parent pointer to be unchanged */ + /* after calling this function. For example, when DeleteFixUP */ + /* calls LeftRotate it expects the parent pointer of nil to be */ + /* unchanged. */ + + y=x->right; + x->right=y->left; + + if (y->left != nil) y->left->parent=x; /* used to use sentinel here */ + /* and do an unconditional assignment instead of testing for nil */ + + y->parent=x->parent; + + /* instead of checking if x->parent is the root as in the book, we */ + /* count on the root sentinel to implicitly take care of this case */ + if( x == x->parent->left) { + x->parent->left=y; + } else { + x->parent->right=y; + } + y->left=x; + x->parent=y; + + x->maxHigh=ITMax(x->left->maxHigh,ITMax(x->right->maxHigh,x->high)); + y->maxHigh=ITMax(x->maxHigh,ITMax(y->right->maxHigh,y->high)); + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not red in ITLeftRotate"); + Assert((nil->maxHigh=MIN_LONG), + "nil->maxHigh != MIN_LONG in ITLeftRotate"); + #endif + }; + + + protected: void RightRotate(IntervalTreeNode* y) { + // *************************************** + IntervalTreeNode* x; + + /* I originally wrote this function to use the sentinel for */ + /* nil to avoid checking for nil. However this introduces a */ + /* very subtle bug because sometimes this function modifies */ + /* the parent pointer of nil. This can be a problem if a */ + /* function which calls LeftRotate also uses the nil sentinel */ + /* and expects the nil sentinel's parent pointer to be unchanged */ + /* after calling this function. For example, when DeleteFixUP */ + /* calls LeftRotate it expects the parent pointer of nil to be */ + /* unchanged. */ + + x=y->left; + y->left=x->right; + + if (nil != x->right) x->right->parent=y; /*used to use sentinel here */ + /* and do an unconditional assignment instead of testing for nil */ + + /* instead of checking if x->parent is the root as in the book, we */ + /* count on the root sentinel to implicitly take care of this case */ + x->parent=y->parent; + if( y == y->parent->left) { + y->parent->left=x; + } else { + y->parent->right=x; + } + x->right=y; + y->parent=x; + + y->maxHigh=ITMax(y->left->maxHigh,ITMax(y->right->maxHigh,y->high)); + x->maxHigh=ITMax(x->left->maxHigh,ITMax(y->maxHigh,x->high)); + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not red in ITRightRotate"); + Assert((nil->maxHigh=MIN_LONG), + "nil->maxHigh != MIN_LONG in ITRightRotate"); + #endif + }; + +# endif + + public: Interval * DeleteNode(IntervalTreeNode * z) + // ***************************************************** + { + IntervalTreeNode* y; + IntervalTreeNode* x; + Interval * returnValue = z->storedInterval; + + y= ((z->left == nil) || (z->right == nil)) ? z : GetSuccessorOf(z); + x= (y->left == nil) ? y->right : y->left; + if (root == (x->parent = y->parent)) { /* assignment of y->p to x->p is intentional */ + root->left=x; + } else { + if (y == y->parent->left) { + y->parent->left=x; + } else { + y->parent->right=x; + } + } + if (y != z) { /* y should not be nil in this case */ + + #ifdef DEBUG_ASSERT + Assert( (y!=nil),"y is nil in DeleteNode \n"); + #endif + /* y is the node to splice out and x is its child */ + + y->maxHigh = MIN_LONG; + y->left=z->left; + y->right=z->right; + y->parent=z->parent; + z->left->parent=z->right->parent=y; + if (z == z->parent->left) { + z->parent->left=y; + } else { + z->parent->right=y; + } + FixUpMaxHigh(x->parent); + if (!(y->red)) { + y->red = z->red; + DeleteFixUp(x); + } else + y->red = z->red; + delete z; + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not black in ITDelete"); + Assert((nil->maxHigh=MIN_LONG),"nil->maxHigh != MIN_LONG in ITDelete"); + #endif + } else { + FixUpMaxHigh(x->parent); + if (!(y->red)) DeleteFixUp(x); + delete y; + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not black in ITDelete"); + Assert((nil->maxHigh=MIN_LONG),"nil->maxHigh != MIN_LONG in ITDelete"); + #endif + } + return returnValue; + }; + +# if !defined(__DOXYGEN_PROCESSOR__) + + protected: void TreeInsertHelp(IntervalTreeNode * z) + // ************************************** + { + /* This function should only be called by InsertITTree (see above) */ + IntervalTreeNode* x; + IntervalTreeNode* y; + + z->left=z->right=nil; + y=root; + x=root->left; + while( x != nil) { + y=x; + if ( x->key > z->key) { + x=x->left; + } else { /* x->key <= z->key */ + x=x->right; + } + } + z->parent=y; + if ( (y == root) || + (y->key > z->key) ) { + y->left=z; + } else { + y->right=z; + } + + #if defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not red in ITTreeInsertHelp"); + Assert((nil->maxHigh=MIN_LONG), + "nil->maxHigh != MIN_LONG in ITTreeInsertHelp"); + #endif + }; + + + protected: void DeleteFixUp(IntervalTreeNode * x) + // *********************************** + { + IntervalTreeNode * w; + IntervalTreeNode * rootLeft = root->left; + + while( (!x->red) && (rootLeft != x)) { + if (x == x->parent->left) { + w=x->parent->right; + if (w->red) { + w->red=0; + x->parent->red=1; + LeftRotate(x->parent); + w=x->parent->right; + } + if ( (!w->right->red) && (!w->left->red) ) { + w->red=1; + x=x->parent; + } else { + if (!w->right->red) { + w->left->red=0; + w->red=1; + RightRotate(w); + w=x->parent->right; + } + w->red=x->parent->red; + x->parent->red=0; + w->right->red=0; + LeftRotate(x->parent); + x=rootLeft; /* this is to exit while loop */ + } + } else { /* the code below is has left and right switched from above */ + w=x->parent->left; + if (w->red) { + w->red=0; + x->parent->red=1; + RightRotate(x->parent); + w=x->parent->left; + } + if ( (!w->right->red) && (!w->left->red) ) { + w->red=1; + x=x->parent; + } else { + if (!w->left->red) { + w->right->red=0; + w->red=1; + LeftRotate(w); + w=x->parent->left; + } + w->red=x->parent->red; + x->parent->red=0; + w->left->red=0; + RightRotate(x->parent); + x=rootLeft; /* this is to exit while loop */ + } + } + } + x->red=0; + + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not black in ITDeleteFixUp"); + Assert((nil->maxHigh=MIN_LONG), + "nil->maxHigh != MIN_LONG in ITDeleteFixUp"); + #endif + + }; + +# endif + + public: IntervalTreeNode * Insert(Interval * newInterval) + // ********************************************************** + { + IntervalTreeNode * y; + IntervalTreeNode * x; + IntervalTreeNode * newNode; + + x = new IntervalTreeNode(newInterval); + TreeInsertHelp(x); + FixUpMaxHigh(x->parent); + newNode = x; + x->red=1; + while(x->parent->red) { /* use sentinel instead of checking for root */ + if (x->parent == x->parent->parent->left) { + y=x->parent->parent->right; + if (y->red) { + x->parent->red=0; + y->red=0; + x->parent->parent->red=1; + x=x->parent->parent; + } else { + if (x == x->parent->right) { + x=x->parent; + LeftRotate(x); + } + x->parent->red=0; + x->parent->parent->red=1; + RightRotate(x->parent->parent); + } + } else { /* case for x->parent == x->parent->parent->right */ + /* this part is just like the section above with */ + /* left and right interchanged */ + y=x->parent->parent->left; + if (y->red) { + x->parent->red=0; + y->red=0; + x->parent->parent->red=1; + x=x->parent->parent; + } else { + if (x == x->parent->left) { + x=x->parent; + RightRotate(x); + } + x->parent->red=0; + x->parent->parent->red=1; + LeftRotate(x->parent->parent); + } + } + } + root->left->red=0; + return(newNode); + + #ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS + CheckAssumptions(); + #elif defined(DEBUG_ASSERT) + Assert(!nil->red,"nil not red in ITTreeInsert"); + Assert(!root->red,"root not red in ITTreeInsert"); + Assert((nil->maxHigh=MIN_LONG), + "nil->maxHigh != MIN_LONG in ITTreeInsert"); + #endif + }; + + + + /* The basic idea for the function below is to take the IntervalSearch */ + /* function from the book and modify to find all overlapping intervals */ + /* instead of just one. This means that any time we take the left */ + /* branch down the tree we must also check the right branch if and only if */ + /* we find an overlapping interval in that left branch. Note this is a */ + /* recursive condition because if we go left at the root then go left */ + /* again at the first left child and find an overlap in the left subtree */ + /* of the left child of root we must recursively check the right subtree */ + /* of the left child of root as well as the right child of root. */ + public: stack * Enumerate(long low, long high) + // ***************************************************** + { + stack * enumResultStack; + IntervalTreeNode* x=root->left; + long stuffToDo = (x != nil); + + // Possible speed up: add min field to prune right searches // + + #ifdef DEBUG_ASSERT + Assert((recursionNodeStackTop == 0), + "recursionStack not empty when entering IntervalTree::Enumerate"); + #endif + currentParent = 0; + enumResultStack = new stack; + + while(stuffToDo) { + if (Overlap(low,high,x->key,x->high) ) { + enumResultStack->push(x->storedInterval); + recursionNodeStack[currentParent].tryRightBranch=1; + } + if(x->left->maxHigh >= low) { // implies x != nil + if ( recursionNodeStackTop == recursionNodeStackSize ) { + recursionNodeStackSize *= 2; + recursionNodeStack = (it_recursion_node *) + realloc(recursionNodeStack, + recursionNodeStackSize * sizeof(it_recursion_node)); + if (recursionNodeStack == NULL) + throw Error("realloc failed in IntervalTree::Enumerate\n"); + } + recursionNodeStack[recursionNodeStackTop].start_node = x; + recursionNodeStack[recursionNodeStackTop].tryRightBranch = 0; + recursionNodeStack[recursionNodeStackTop].parentIndex = currentParent; + currentParent = recursionNodeStackTop++; + x = x->left; + } else { + x = x->right; + } + stuffToDo = (x != nil); + while( (!stuffToDo) && (recursionNodeStackTop > 1) ) { + if(recursionNodeStack[--recursionNodeStackTop].tryRightBranch) { + x=recursionNodeStack[recursionNodeStackTop].start_node->right; + currentParent=recursionNodeStack[recursionNodeStackTop].parentIndex; + recursionNodeStack[currentParent].tryRightBranch=1; + stuffToDo = ( x != nil); + } + } + } + #ifdef DEBUG_ASSERT + Assert((recursionNodeStackTop == 1), + "recursionStack not empty when exiting IntervalTree::Enumerate"); + #endif + return(enumResultStack); + }; + +# if !defined(__DOXYGEN_PROCESSOR__) + + protected: void CheckAssumptions() const; + + /* A sentinel is used for root and for nil. These sentinels are */ + /* created when ITTreeCreate is caled. root->left should always */ + /* point to the node which is the root of the tree. nil points to a */ + /* node which should always be black but has aribtrary children and */ + /* parent and no key or info. The point of using these sentinels is so */ + /* that the root and nil nodes do not require special cases in the code */ + + protected: IntervalTreeNode * root; + protected: IntervalTreeNode * nil; + + public: IntervalTreeNode * GetPredecessorOf(IntervalTreeNode *) const; + + public: IntervalTreeNode * GetSuccessorOf(IntervalTreeNode * ) const; + protected: void TreePrintHelper(IntervalTreeNode *) const; + protected: void CheckMaxHighFields(IntervalTreeNode *) const; + protected: long CheckMaxHighFieldsHelper(IntervalTreeNode * y, + const long currentHigh, + long match) const; + +// Attributs +// ********* + private: unsigned long recursionNodeStackSize; + private: it_recursion_node * recursionNodeStack; + private: unsigned long currentParent; + private: unsigned long recursionNodeStackTop; +# endif + + +}; + + +} // end of namespace +#endif + + + + + +