From 61e9abddbd06fd2c5b86257ecff1443a1c12d317 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Mon, 23 May 2016 16:15:25 +0200 Subject: [PATCH] Anabatic transient commit 1. * New: In Anabatic, basic support for GCell/Edge creation. --- anabatic/CMakeLists.txt | 39 ++ anabatic/cmake_modules/CMakeLists.txt | 1 + anabatic/cmake_modules/FindANABATIC.cmake | 37 ++ anabatic/src/AnabaticEngine.cpp | 138 +++++ anabatic/src/CMakeLists.txt | 72 +++ anabatic/src/Configuration.cpp | 312 +++++++++++ anabatic/src/Constants.cpp | 50 ++ anabatic/src/Edge.cpp | 238 +++++++++ anabatic/src/GCell.cpp | 490 ++++++++++++++++++ anabatic/src/GraphicAnabaticEngine.cpp | 286 ++++++++++ anabatic/src/Matrix.cpp | 127 +++++ anabatic/src/PyAnabatic.cpp | 94 ++++ anabatic/src/PyAnabaticEngine.cpp | 217 ++++++++ anabatic/src/PyGraphicAnabaticEngine.cpp | 122 +++++ anabatic/src/anabatic/AnabaticEngine.h | 92 ++++ anabatic/src/anabatic/Configuration.h | 159 ++++++ anabatic/src/anabatic/Constants.h | 60 +++ anabatic/src/anabatic/Edge.h | 115 ++++ anabatic/src/anabatic/GCell.h | 132 +++++ anabatic/src/anabatic/GraphicAnabaticEngine.h | 90 ++++ anabatic/src/anabatic/Matrix.h | 210 ++++++++ anabatic/src/anabatic/PyAnabaticEngine.h | 55 ++ .../src/anabatic/PyGraphicAnabaticEngine.h | 53 ++ bootstrap/build.conf | 1 + unicorn/src/cgt.py | 2 +- 25 files changed, 3191 insertions(+), 1 deletion(-) create mode 100644 anabatic/CMakeLists.txt create mode 100644 anabatic/cmake_modules/CMakeLists.txt create mode 100644 anabatic/cmake_modules/FindANABATIC.cmake create mode 100644 anabatic/src/AnabaticEngine.cpp create mode 100644 anabatic/src/CMakeLists.txt create mode 100644 anabatic/src/Configuration.cpp create mode 100644 anabatic/src/Constants.cpp create mode 100644 anabatic/src/Edge.cpp create mode 100644 anabatic/src/GCell.cpp create mode 100644 anabatic/src/GraphicAnabaticEngine.cpp create mode 100644 anabatic/src/Matrix.cpp create mode 100644 anabatic/src/PyAnabatic.cpp create mode 100644 anabatic/src/PyAnabaticEngine.cpp create mode 100644 anabatic/src/PyGraphicAnabaticEngine.cpp create mode 100644 anabatic/src/anabatic/AnabaticEngine.h create mode 100644 anabatic/src/anabatic/Configuration.h create mode 100644 anabatic/src/anabatic/Constants.h create mode 100644 anabatic/src/anabatic/Edge.h create mode 100644 anabatic/src/anabatic/GCell.h create mode 100644 anabatic/src/anabatic/GraphicAnabaticEngine.h create mode 100644 anabatic/src/anabatic/Matrix.h create mode 100644 anabatic/src/anabatic/PyAnabaticEngine.h create mode 100644 anabatic/src/anabatic/PyGraphicAnabaticEngine.h diff --git a/anabatic/CMakeLists.txt b/anabatic/CMakeLists.txt new file mode 100644 index 00000000..4187e409 --- /dev/null +++ b/anabatic/CMakeLists.txt @@ -0,0 +1,39 @@ +# -*- explicit-buffer-name: "CMakeLists.txt" -*- + + set(CMAKE_LEGACY_CYGWIN_WIN32 0) + project(ANABATIC) + + option(BUILD_DOC "Build the documentation (doxygen)" OFF) + option(CHECK_DATABASE "Run database in full check mode (very slow)" OFF) + + cmake_minimum_required(VERSION 2.8.9) + + list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/") + find_package(Bootstrap REQUIRED) + setup_project_paths(CORIOLIS) + + set_cmake_policies() + set_lib_link_mode() + setup_boost() + setup_qt() + + find_package(PythonLibs REQUIRED) + find_package(PythonSitePackages REQUIRED) + find_package(VLSISAPD REQUIRED) + find_package(HURRICANE REQUIRED) + find_package(CORIOLIS REQUIRED) + + add_subdirectory(src) + add_subdirectory(cmake_modules) + +#if(BUILD_DOC) +# find_package(Doxygen) +# if(DOXYGEN_FOUND) +# add_subdirectory(doc) +# endif() +#endif() + + if(CHECK_DATABASE) + add_definitions(-DCHECK_DATABASE) + message(STATUS "Checking database enabled (very slow).") + endif(CHECK_DATABASE) diff --git a/anabatic/cmake_modules/CMakeLists.txt b/anabatic/cmake_modules/CMakeLists.txt new file mode 100644 index 00000000..cfeffb37 --- /dev/null +++ b/anabatic/cmake_modules/CMakeLists.txt @@ -0,0 +1 @@ +install ( FILES FindANABATIC.cmake DESTINATION share/cmake/Modules ) diff --git a/anabatic/cmake_modules/FindANABATIC.cmake b/anabatic/cmake_modules/FindANABATIC.cmake new file mode 100644 index 00000000..2c56eabc --- /dev/null +++ b/anabatic/cmake_modules/FindANABATIC.cmake @@ -0,0 +1,37 @@ +# - Find the Katabatic includes and libraries. +# The following variables are set if Coriolis is found. If ANABATIC is not +# found, ANABATIC_FOUND is set to false. +# ANABATIC_FOUND - True when the Coriolis include directory is found. +# ANABATIC_INCLUDE_DIR - the path to where the Coriolis include files are. +# ANABATIC_LIBRARIES - The path to where the Coriolis library files are. + + +SET(ANABATIC_INCLUDE_PATH_DESCRIPTION "directory containing the Katabatic include files. E.g /usr/local/include/coriolis or /asim/coriolis/include/coriolis") + +SET(ANABATIC_DIR_MESSAGE "Set the ANABATIC_INCLUDE_DIR cmake cache entry to the ${ANABATIC_INCLUDE_PATH_DESCRIPTION}") + +# don't even bother under WIN32 +IF(UNIX) + # + # Look for an installation. + # + FIND_PATH(ANABATIC_INCLUDE_PATH NAMES anabatic/AnabaticEngine.h PATHS + # Look in other places. + ${CORIOLIS_DIR_SEARCH} + PATH_SUFFIXES include/coriolis + # Help the user find it if we cannot. + DOC "The ${ANABATIC_INCLUDE_PATH_DESCRIPTION}" + ) + + FIND_LIBRARY(ANABATIC_LIBRARY_PATH + NAMES anabatic + PATHS ${CORIOLIS_DIR_SEARCH} + PATH_SUFFIXES lib${LIB_SUFFIX} + # Help the user find it if we cannot. + DOC "The ${ANABATIC_INCLUDE_PATH_DESCRIPTION}" + ) + + SET_LIBRARIES_PATH(ANABATIC ANABATIC) + HURRICANE_CHECK_LIBRARIES(ANABATIC) + +ENDIF(UNIX) diff --git a/anabatic/src/AnabaticEngine.cpp b/anabatic/src/AnabaticEngine.cpp new file mode 100644 index 00000000..27eda78d --- /dev/null +++ b/anabatic/src/AnabaticEngine.cpp @@ -0,0 +1,138 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./AnabaticEngine.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include "hurricane/Error.h" +#include "hurricane/Cell.h" +#include "hurricane/UpdateSession.h" +#include "anabatic/GCell.h" +#include "anabatic/AnabaticEngine.h" + + +namespace Anabatic { + + using std::cerr; + using std::cout; + using std::endl; + using std::ostringstream; + using Hurricane::Error; + using Hurricane::Cell; + using Hurricane::UpdateSession; + + +// ------------------------------------------------------------------- +// Class : "Anabatic::AnabaticEngine". + + Name AnabaticEngine::_toolName = "Anabatic"; + + + AnabaticEngine* AnabaticEngine::get ( const Cell* cell ) + { return static_cast(ToolEngine::get(cell,staticGetName())); } + + + const Name& AnabaticEngine::staticGetName () + { return _toolName; } + + + const Name& AnabaticEngine::getName () const + { return _toolName; } + + + AnabaticEngine::AnabaticEngine ( Cell* cell ) + : Super(cell) + , _configuration (new ConfigurationConcrete()) + , _matrix () + , _southWestGCell(NULL) + { + _matrix.setCell( cell, _configuration->getSliceHeight() ); + } + + + void AnabaticEngine::_postCreate () + { + Super::_postCreate(); + + //cdebug.setMinLevel(110); + //cdebug.setMaxLevel(120); + + UpdateSession::open(); + _southWestGCell = GCell::create( this ); + + UpdateSession::close(); + } + + + AnabaticEngine* AnabaticEngine::create ( Cell* cell ) + { + if (not cell) throw Error( "AnabaticEngine::create(): NULL cell argument." ); + if (cell->getAbutmentBox().isEmpty()) + throw Error( "AnabaticEngine::create(): %s has no abutment box." , getString(cell).c_str() ); + + AnabaticEngine* engine = new AnabaticEngine ( cell ); + engine->_postCreate(); + return engine; + } + + + AnabaticEngine::~AnabaticEngine () + { + delete _configuration; + } + + + void AnabaticEngine::_preDestroy () + { + // To be done: destroy the whole set of GCells. + // Must be stored in some way before destruction (in a set<> ?). + + Super::_preDestroy(); + } + + + Configuration* AnabaticEngine::getConfiguration () + { return _configuration; } + + + void AnabaticEngine::_runTest () + { + cerr << "AnabaticEngine::_runTest() called." << endl; + } + + + string AnabaticEngine::_getTypeName () const + { return getString(_toolName); } + + + string AnabaticEngine::_getString () const + { + ostringstream os; + os << "<" << _toolName << " " << _cell->getName() << ">"; + return os.str(); + } + + + Record* AnabaticEngine::_getRecord () const + { + Record* record = Super::_getRecord(); + record->add( getSlot("_configuration" , _configuration ) ); + record->add( getSlot("_southWestGCell", _southWestGCell) ); + record->add( getSlot("_matrix" , &_matrix ) ); + return record; + } + + +} // Anabatic namespace. diff --git a/anabatic/src/CMakeLists.txt b/anabatic/src/CMakeLists.txt new file mode 100644 index 00000000..20163a25 --- /dev/null +++ b/anabatic/src/CMakeLists.txt @@ -0,0 +1,72 @@ +# -*- explicit-buffer-name: "CMakeLists.txt" -*- + +if ( CHECK_DETERMINISM ) + add_definitions ( -DCHECK_DETERMINISM ) +endif ( CHECK_DETERMINISM ) + + include_directories( ${ANABATIC_SOURCE_DIR}/src + ${CORIOLIS_INCLUDE_DIR} + ${HURRICANE_INCLUDE_DIR} + ${CONFIGURATION_INCLUDE_DIR} + ${Boost_INCLUDE_DIRS} + ${QtX_INCLUDE_DIR} + ${PYTHON_INCLUDE_PATH} + ) + set( includes anabatic/Constants.h + anabatic/Configuration.h + anabatic/Matrix.h + anabatic/Edge.h + anabatic/GCell.h #anabatic/GCells.h + anabatic/AnabaticEngine.h + anabatic/GraphicAnabaticEngine.h + ) + set( mocIncludes anabatic/GraphicAnabaticEngine.h ) + set( pyIncludes anabatic/PyAnabaticEngine.h + anabatic/PyGraphicAnabaticEngine.h + ) + set( cpps Constants.cpp + Configuration.cpp + Matrix.cpp + Edge.cpp + GCell.cpp + AnabaticEngine.cpp + GraphicAnabaticEngine.cpp + ) + set( pyCpps PyAnabaticEngine.cpp + PyGraphicAnabaticEngine.cpp + PyAnabatic.cpp + ) + qtX_wrap_cpp( mocCpps ${mocIncludes} ) + + set( depLibs ${CORIOLIS_PYTHON_LIBRARIES} + ${CORIOLIS_LIBRARIES} + ${HURRICANE_PYTHON_LIBRARIES} + ${HURRICANE_GRAPHICAL_LIBRARIES} + ${HURRICANE_LIBRARIES} + ${CONFIGURATION_LIBRARY} + ${CIF_LIBRARY} + ${AGDS_LIBRARY} + ${LEFDEF_LIBRARIES} + ${OA_LIBRARIES} + ${QtX_LIBRARIES} + ${Boost_LIBRARIES} + ${LIBXML2_LIBRARIES} + ${PYTHON_LIBRARIES} -lutil + ) + + add_library( anabatic ${cpps} ${mocCpps} ) + set_target_properties( anabatic PROPERTIES VERSION 1.0 SOVERSION 1 ) + target_link_libraries( anabatic ${depLibs} ) + + add_python_module( "${pyCpps}" + "${pyIncludes}" + "pyanabatic;1.0;1" + Anabatic + "anabatic;${depLibs}" + include/coriolis2/anabatic + ) + + install( TARGETS anabatic DESTINATION lib${LIB_SUFFIX} ) + install( FILES ${includes} + ${mocIncludes} DESTINATION include/coriolis2/anabatic ) + diff --git a/anabatic/src/Configuration.cpp b/anabatic/src/Configuration.cpp new file mode 100644 index 00000000..847621c7 --- /dev/null +++ b/anabatic/src/Configuration.cpp @@ -0,0 +1,312 @@ +// -*- mode: C++; explicit-buffer-name: "Configuration.cpp" -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./Configuration.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include +#include "vlsisapd/configuration/Configuration.h" +#include "hurricane/Warning.h" +#include "hurricane/Error.h" +#include "hurricane/Technology.h" +#include "hurricane/DataBase.h" +#include "hurricane/RegularLayer.h" +#include "hurricane/Cell.h" +#include "crlcore/Utilities.h" +#include "crlcore/CellGauge.h" +#include "crlcore/RoutingGauge.h" +#include "crlcore/RoutingLayerGauge.h" +#include "crlcore/AllianceFramework.h" +#include "anabatic/Configuration.h" + + + +namespace Anabatic { + + + using std::cout; + using std::cerr; + using std::endl; + using std::setprecision; + using std::ostringstream; + using std::vector; + using Hurricane::tab; + using Hurricane::Warning; + using Hurricane::Error; + using Hurricane::Technology; + using Hurricane::DataBase; + using Hurricane::RegularLayer; + using CRL::AllianceFramework; + using CRL::RoutingGauge; + using CRL::RoutingLayerGauge; + + +// ------------------------------------------------------------------- +// Class : "Anabatic::Configuration". + + + Configuration::Configuration () { } + Configuration::~Configuration () { } + + +// ------------------------------------------------------------------- +// Class : "Anabatic::ConfigurationConcrete". + + + ConfigurationConcrete::ConfigurationConcrete ( const CellGauge* cg, const RoutingGauge* rg ) + : Configuration () + , _cg (NULL) + , _rg (NULL) + , _extensionCaps () + , _allowedDepth (0) + { + if (cg == NULL) cg = AllianceFramework::get()->getCellGauge(); + if (rg == NULL) rg = AllianceFramework::get()->getRoutingGauge(); + _cg = cg->getClone(); + _rg = rg->getClone(); + + if (Cfg::hasParameter("anabatic.topRoutingLayer")) { + _setTopRoutingLayer( Cfg::getParamString("anabatic.topRoutingLayer")->asString() ); + } else + _allowedDepth = rg->getDepth()-1; + + _gmetalh = DataBase::getDB()->getTechnology()->getLayer("gmetalh"); + _gmetalv = DataBase::getDB()->getTechnology()->getLayer("gmetalv"); + _gcontact = DataBase::getDB()->getTechnology()->getLayer("gcontact"); + + if (_gcontact == NULL) cerr << Warning("Cannot get \"gcontact\" layer from the Technology.") << endl; + if (_gmetalv == NULL) cerr << Warning("Cannot get \"gmetalv\" layer from the Technology.") << endl; + if (_gmetalh == NULL) cerr << Warning("Cannot get \"gmetalh\" layer from the Technology.") << endl; + + //DbU::Unit sliceHeight = _cg->getSliceHeight(); + + const vector& layerGauges = rg->getLayerGauges(); + for ( size_t depth=0 ; depth < layerGauges.size() ; ++depth ) { + const RegularLayer* regularLayer = dynamic_cast( layerGauges[depth]->getLayer() ); + if (regularLayer) + _extensionCaps.push_back( regularLayer->getExtentionCap() ); + else { + _extensionCaps.push_back( 0 ); + cerr << Warning( "Routing layer at depth %d is *not* a RegularLayer, cannot guess extension cap.\n" + " (%s)" + , depth + , getString(layerGauges[depth]->getLayer()).c_str() + ) << endl; + } + } + } + + + ConfigurationConcrete::ConfigurationConcrete ( const ConfigurationConcrete& other ) + : Configuration() + , _gmetalh (other._gmetalh) + , _gmetalv (other._gmetalv) + , _gcontact (other._gcontact) + , _cg (NULL) + , _rg (NULL) + , _extensionCaps (other._extensionCaps) + , _allowedDepth (other._allowedDepth) + { + if (other._cg) _cg = other._cg->getClone(); + if (other._rg) _rg = other._rg->getClone(); + } + + + ConfigurationConcrete::~ConfigurationConcrete () + { + cdebug.log(145) << "About to delete attribute _rg (RoutingGauge)." << endl; + _cg->destroy (); + _rg->destroy (); + } + + + ConfigurationConcrete* ConfigurationConcrete::clone () const + { return new ConfigurationConcrete(*this); } + + + bool ConfigurationConcrete::isGMetal ( const Layer* layer ) const + { return (layer and ((layer == _gmetalh) or (layer == _gmetalv))); } + + + bool ConfigurationConcrete::isGContact ( const Layer* layer ) const + { return (layer and (layer == _gcontact)); } + + + size_t ConfigurationConcrete::getDepth () const + { return _rg->getDepth(); } + + + size_t ConfigurationConcrete::getAllowedDepth () const + { return _allowedDepth; } + + + size_t ConfigurationConcrete::getLayerDepth ( const Layer* layer ) const + { return _rg->getLayerDepth(layer); } + + + CellGauge* ConfigurationConcrete::getCellGauge () const + { return _cg; } + + + RoutingGauge* ConfigurationConcrete::getRoutingGauge () const + { return _rg; } + + + RoutingLayerGauge* ConfigurationConcrete::getLayerGauge ( size_t depth ) const + { return _rg->getLayerGauge(depth); } + + + const Layer* ConfigurationConcrete::getRoutingLayer ( size_t depth ) const + { return _rg->getRoutingLayer(depth); } + + + Layer* ConfigurationConcrete::getContactLayer ( size_t depth ) const + { return _rg->getContactLayer(depth); } + + + DbU::Unit ConfigurationConcrete::getSliceHeight () const + { return _cg->getSliceHeight(); } + + + DbU::Unit ConfigurationConcrete::getSliceStep () const + { return _cg->getSliceStep(); } + + + DbU::Unit ConfigurationConcrete::getPitch ( const Layer* layer, Flags flags ) const + { return getPitch( getLayerDepth(layer), flags ); } + + + DbU::Unit ConfigurationConcrete::getOffset ( const Layer* layer ) const + { return getOffset( getLayerDepth(layer) ); } + + + DbU::Unit ConfigurationConcrete::getExtensionCap ( const Layer* layer ) const + { return getExtensionCap( getLayerDepth(layer) ); } + + + DbU::Unit ConfigurationConcrete::getWireWidth ( const Layer* layer ) const + { return getWireWidth( getLayerDepth(layer) ); } + + + Flags ConfigurationConcrete::getDirection ( const Layer* layer ) const + { return getDirection( getLayerDepth(layer) ); } + + + DbU::Unit ConfigurationConcrete::getPitch ( size_t depth, Flags flags ) const + { + if (flags == Flags::NoFlags) return _rg->getLayerPitch(depth); + + if (flags & Flags::PitchAbove) { + if (depth < getAllowedDepth()) + return _rg->getLayerPitch( depth + 1 ); + else { + if ( (depth > 0) and (_rg->getLayerType(depth-1) != Constant::PinOnly) ) + return _rg->getLayerPitch( depth - 1 ); + } + } + + if (flags & Flags::PitchBelow) { + if ( (depth > 0) and (_rg->getLayerType(depth-1) != Constant::PinOnly) ) + return _rg->getLayerPitch( depth - 1 ); + else { + if (depth < getAllowedDepth()) + return _rg->getLayerPitch( depth + 1 ); + } + } + + // Should issue at least a warning here. + return _rg->getLayerPitch(depth); + } + + + DbU::Unit ConfigurationConcrete::getOffset ( size_t depth ) const + { return _rg->getLayerOffset(depth); } + + + DbU::Unit ConfigurationConcrete::getWireWidth ( size_t depth ) const + { return _rg->getLayerWireWidth(depth); } + + + DbU::Unit ConfigurationConcrete::getExtensionCap ( size_t depth ) const + { return _extensionCaps[depth]; } + + + Flags ConfigurationConcrete::getDirection ( size_t depth ) const + { return _rg->getLayerDirection(depth); } + + + void ConfigurationConcrete::setAllowedDepth ( size_t allowedDepth ) + { _allowedDepth = (allowedDepth > getDepth()) ? getDepth() : allowedDepth; } + + + void ConfigurationConcrete::_setTopRoutingLayer ( Name name ) + { + for ( size_t depth=0 ; depth<_rg->getDepth() ; ++depth ) { + if (_rg->getRoutingLayer(depth)->getName() == name) { + _allowedDepth = _rg->getLayerGauge(depth)->getDepth(); + return; + } + } + cerr << Error( "In Configuration::Concrete::_setTopRoutingLayer():\n" + " The routing gauge <%s> has no layer named <%s>" + , getString(_rg->getName()).c_str() + , getString(name).c_str() ) << endl; + } + + + void ConfigurationConcrete::print ( Cell* cell ) const + { + string topLayerName = "UNKOWN"; + const Layer* topLayer = _rg->getRoutingLayer( _allowedDepth ); + if (topLayer) + topLayerName = getString( topLayer->getName() ); + + cout << " o Configuration of ToolEngine for Cell <" << cell->getName() << ">" << endl; + cout << Dots::asIdentifier(" - Routing Gauge" ,getString(_rg->getName())) << endl; + cout << Dots::asString (" - Top routing layer" ,topLayerName) << endl; + } + + + string ConfigurationConcrete::_getTypeName () const + { + return "ConfigurationConcrete"; + } + + + string ConfigurationConcrete::_getString () const + { + ostringstream os; + + os << "<" << _getTypeName() << " " << _rg->getName() << ">"; + + return os.str(); + } + + + Record* ConfigurationConcrete::_getRecord () const + { + Record* record = new Record ( _getString() ); + record->add ( getSlot( "_rg" , _rg ) ); + record->add ( getSlot( "_gmetalh" , _gmetalh ) ); + record->add ( getSlot( "_gmetalv" , _gmetalv ) ); + record->add ( getSlot( "_gcontact" , _gcontact ) ); + record->add ( getSlot( "_allowedDepth" , _allowedDepth ) ); + + return ( record ); + } + + + +} // Anabatic namespace. diff --git a/anabatic/src/Constants.cpp b/anabatic/src/Constants.cpp new file mode 100644 index 00000000..cd72bf44 --- /dev/null +++ b/anabatic/src/Constants.cpp @@ -0,0 +1,50 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./Constants.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include "anabatic/Constants.h" + + +namespace Anabatic { + + using std::string; + + + Flags::~Flags () + { } + + + string Flags::_getTypeName () const + { return "Anabatic::Flags"; } + + + string Flags::_getString () const + { + string s = ""; + s += (_flags & Horizontal ) ? 'h' : '-'; + s += (_flags & Vertical ) ? 'v' : '-'; + s += (_flags & SourceGCell) ? 's' : '-'; + s += (_flags & TargetGCell) ? 't' : '-'; + s += (_flags & Invalidated) ? 'i' : '-'; + s += (_flags & MoveSide ) ? 'M' : '-'; + s += (_flags & PitchAbove ) ? 'A' : '-'; + s += (_flags & PitchBelow ) ? 'B' : '-'; + + return s; + } + + +} // Anabatic namespace. diff --git a/anabatic/src/Edge.cpp b/anabatic/src/Edge.cpp new file mode 100644 index 00000000..da775b93 --- /dev/null +++ b/anabatic/src/Edge.cpp @@ -0,0 +1,238 @@ +// -*- mode: C++; explicit-buffer-name: "Edge.cpp" -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./Edge.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include "hurricane/Error.h" +#include "anabatic/Edge.h" +#include "anabatic/GCell.h" + + +namespace Anabatic { + + using std::cerr; + using std::endl; + using Hurricane::Error; + + + Name Edge::_extensionName = "Anabatic::Edge"; + + + Edge::Edge ( GCell* source, GCell* target, Flags flags ) + : Super(source->getCell()) + , _flags (flags|Flags::Invalidated) + , _capacity (0) + , _realOccupancy (0) + , _estimateOccupancy(0.0) + , _source (source) + , _target (target) + , _axis (0) + { } + + + void Edge::_postCreate () + { + Super::_postCreate(); + + if (_flags.isset(Flags::Horizontal)) { + _axis = std::max( _source->getYMin(), _target->getYMin() ); + _source->_add( this, Flags::EastSide ); + _target->_add( this, Flags::WestSide ); + } else { + _axis = std::max( _source->getXMin(), _target->getXMin() ); + _source->_add( this, Flags::NorthSide ); + _target->_add( this, Flags::SouthSide ); + } + } + + + Edge* Edge::create ( GCell* source, GCell* target, Flags flags ) + { + if (not source) throw Error( "Edge::create(): NULL source argument." ); + if (not target) throw Error( "Edge::create(): NULL target argument." ); + if (source == target) + throw Error("Edge::create(): Source & target are the same (%s).", getString(source).c_str() ); + + if (not (flags.intersect(Flags::Horizontal|Flags::Vertical))) { + Box border = GCell::getBorder( source, target ); + + if (border.isEmpty()) + throw Error( "Edge::create(): source & target GCells are *not* contiguous.\n" + " source:%s\n" + " target:%s" + , getString(source).c_str() + , getString(target).c_str() + ); + + if (border.getYMin() == border.getYMax()) flags |= Flags::Horizontal; + else flags |= Flags::Vertical; + } + + Edge* edge = new Edge ( source, target, flags ); + edge->_postCreate(); + + cdebug.log(110,1) << "Edge::create(): " << (void*)edge << ":" << edge << endl; + cdebug.log(110) << "source:" << edge->getSource() << endl; + cdebug.log(110) << "target:" << edge->getTarget() << endl; + cdebug.tabw(110,-1); + return edge; + } + + + Edge::~Edge () + { } + + + void Edge::_preDestroy () + { + _source->_remove( this, _flags|Flags::SourceGCell ); + _target->_remove( this, _flags|Flags::TargetGCell ); + + Super::_preDestroy(); + } + + + void Edge::destroy () + { + _preDestroy(); + delete this; + } + + + DbU::Unit Edge::getAxisMin () const + { + if (_flags.isset(Flags::Vertical)) + return std::max( _source->getXMin(), _target->getXMin() ); + return std::max( _source->getYMin(), _target->getYMin() ); + } + + + GCell* Edge::getOpposite ( const GCell* from ) const + { + if (from == _source) return _target; + if (from == _target) return _source; + + cerr << Error( "Edge::getOpposite(): On %s,\n" + " \"from\" CGell id:%u is neither source nor target (S-id:%u, T-id:%u)." + , getString(this).c_str() + , from->getId() + , _source->getId() + , _target->getId() + ) << endl; + return NULL; + } + + + Interval Edge::getSide () const + { + Interval side; + + if (_flags.isset(Flags::Vertical)) + side = Interval( std::max(_source->getXMin(),_target->getXMin()) + , std::min(_source->getXMax(),_target->getXMax()) ); + else + side = Interval( std::max(_source->getYMin(),_target->getYMin()) + , std::min(_source->getYMax(),_target->getYMax()) ); + + return side; + } + + + void Edge::_setSource ( GCell* source ) + { + if (source == _target) + throw Error("Edge::_setSource(): Source & target are the same (%s).", getString(source).c_str() ); + + invalidate(); _source=source; + } + + + void Edge::_setTarget ( GCell* target ) + { + if (_source == target) + throw Error("Edge::_setTarget(): Source & target are the same (%s).", getString(target).c_str() ); + + invalidate(); _target=target; + } + + + void Edge::_revalidate () + { + _axis = getSide().getCenter(); + _flags.reset( Flags::Invalidated ); + + cdebug.log(110) << "Edge::_revalidate() " << this << endl; + } + + + const Name& Edge::getName () const + { return _extensionName; } + + + Box Edge::getBoundingBox () const + { + static DbU::Unit halfThickness = DbU::fromLambda( 2.0 ); + static DbU::Unit halfLength = DbU::fromLambda( 12.0 ); + + if (_flags.isset(Flags::Horizontal)) + return Box( _target->getXMin() - halfLength, _axis - halfThickness + , _target->getXMin() + halfLength, _axis + halfThickness + ); + + return Box( _axis - halfThickness, _target->getYMin() - halfLength + , _axis + halfThickness, _target->getYMin() + halfLength + ); + } + + + void Edge::translate ( const DbU::Unit&, const DbU::Unit& ) + { + cerr << Error( "Edge::translate(): On %s,\n" + " Must never be called on a Edge object (ignored)." + , getString(this).c_str() + ) << endl; + } + + + string Edge::_getTypeName () const + { return getString(_extensionName); } + + + string Edge::_getString () const + { + string s = Super::_getString(); + s.insert( s.size()-1, " "+DbU::getValueString(_axis) ); + s.insert( s.size()-1, " "+getString(_realOccupancy) ); + s.insert( s.size()-1, "/"+getString(_capacity) ); + s.insert( s.size()-1, " "+getString(_flags) ); + return s; + } + + + Record* Edge::_getRecord () const + { + Record* record = Super::_getRecord(); + record->add( getSlot("_flags" , _flags ) ); + record->add( getSlot("_capacity" , _capacity ) ); + record->add( getSlot("_realOccupancy" , _realOccupancy ) ); + record->add( getSlot("_estimateOccupancy", _estimateOccupancy) ); + record->add( getSlot("_source" , _source ) ); + record->add( getSlot("_target" , _target ) ); + record->add( DbU::getValueSlot("_axis", &_axis) ); + return record; + } + + +} // Anabatic namespace. diff --git a/anabatic/src/GCell.cpp b/anabatic/src/GCell.cpp new file mode 100644 index 00000000..e6baa7e9 --- /dev/null +++ b/anabatic/src/GCell.cpp @@ -0,0 +1,490 @@ +// -*- mode: C++; explicit-buffer-name: "GCell.cpp" -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./GCell.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include "anabatic/GCell.h" +#include "anabatic/AnabaticEngine.h" + + +namespace Anabatic { + + using std::cerr; + using std::endl; + using Hurricane::Error; + + + Name GCell::_extensionName = "Anabatic::GCell"; + + + GCell::GCell ( AnabaticEngine* anabatic, DbU::Unit xmin, DbU::Unit ymin ) + : Super(anabatic->getCell()) + , _anabatic (anabatic) + , _flags (Flags::NoFlags) + , _westEdges () + , _eastEdges () + , _southEdges() + , _northEdges() + , _xmin (xmin) + , _ymin (ymin) + { } + + + void GCell::_postCreate () + { + Super::_postCreate(); + } + + + GCell* GCell::create ( AnabaticEngine* anabatic ) + { + if (not anabatic) throw Error( "GCell::create(): NULL anabatic argument." ); + if (not anabatic->getCell()) throw Error( "GCell::create(): AnabaticEngine has no Cell loaded." ); + + GCell* gcell = new GCell ( anabatic + , anabatic->getCell()->getAbutmentBox().getXMin() + , anabatic->getCell()->getAbutmentBox().getYMin() ); + gcell->_postCreate(); + gcell->_revalidate(); + return gcell; + } + + + GCell* GCell::_create ( DbU::Unit xmin, DbU::Unit ymin ) + { + GCell* gcell = new GCell ( getAnabatic(), xmin, ymin ); + gcell->_postCreate(); + return gcell; + } + + + GCell::~GCell () + { } + + + void GCell::_preDestroy () + { + for ( Edge* edge : _westEdges ) edge->destroy(); + for ( Edge* edge : _eastEdges ) edge->destroy(); + for ( Edge* edge : _southEdges ) edge->destroy(); + for ( Edge* edge : _northEdges ) edge->destroy(); + + Super::_preDestroy(); + } + + + void GCell::destroy () + { + _preDestroy(); + delete this; + } + + + void GCell::_remove ( Edge* edge, Flags side ) + { + if (side.contains(Flags::WestSide )) erase_element( _westEdges, edge ); + if (side.contains(Flags::EastSide )) erase_element( _eastEdges, edge ); + if (side.contains(Flags::SouthSide)) erase_element( _southEdges, edge ); + if (side.contains(Flags::NorthSide)) erase_element( _northEdges, edge ); + } + + + void GCell::_add ( Edge* edge, Flags side ) + { + cdebug.log(110,1) << "GCell::_add(side): side:" << side << " " << edge << endl; + if (side.contains(Flags::WestSide)) { + cdebug.log(110) << "Adding to West side of " << this << endl; + for ( auto iedge=_westEdges.begin() ; iedge != _westEdges.end() ; ++iedge ) + if ((*iedge)->getAxisMin() >= edge->getAxisMin()) { + _westEdges.insert( iedge, edge ); + cdebug.tabw(110,-1); + return; + } + _westEdges.push_back( edge ); + } + + if (side.contains(Flags::EastSide)) { + cdebug.log(110) << "Adding to East side of " << this << endl; + for ( auto iedge=_eastEdges.begin() ; iedge != _eastEdges.end() ; ++iedge ) + if ((*iedge)->getAxisMin() >= edge->getAxisMin()) { + _eastEdges.insert( iedge, edge ); + cdebug.tabw(110,-1); + return; + } + _eastEdges.push_back( edge ); + } + + if (side.contains(Flags::SouthSide)) { + cdebug.log(110) << "Adding to South side of " << this << endl; + for ( auto iedge=_southEdges.begin() ; iedge != _southEdges.end() ; ++iedge ) + cdebug.log(110) << "| @" << DbU::getValueString((*iedge)->getAxisMin()) << " " << *iedge << endl; + + for ( auto iedge=_southEdges.begin() ; iedge != _southEdges.end() ; ++iedge ) + if ((*iedge)->getAxisMin() >= edge->getAxisMin()) { + cdebug.log(110) << "Insert *before* " << *iedge << endl; + + _southEdges.insert( iedge, edge ); + for ( auto iedge2=_southEdges.begin() ; iedge2 != _southEdges.end() ; ++iedge2 ) + cdebug.log(110) << "| @" << DbU::getValueString((*iedge)->getAxisMin()) << " " << *iedge2 << endl; + cdebug.tabw(110,-1); + return; + } + _southEdges.push_back( edge ); + } + + if (side.contains(Flags::NorthSide)) { + cdebug.log(110) << "Adding to North side of " << this << endl; + for ( auto iedge=_northEdges.begin() ; iedge != _northEdges.end() ; ++iedge ) + if ((*iedge)->getAxisMin() >= edge->getAxisMin()) { + _northEdges.insert( iedge, edge ); + cdebug.tabw(110,-1); + return; + } + _northEdges.push_back( edge ); + } + + cdebug.tabw(110,-1); + } + + + Box GCell::getBorder ( const GCell* s, const GCell* t ) + { + Flags flags = Flags::NoFlags; + flags |= (s->getXMax() == t->getXMin()) ? Flags::EastSide : 0; + flags |= (t->getXMax() == s->getXMin()) ? Flags::WestSide : 0; + flags |= (s->getYMax() == t->getYMin()) ? Flags::NorthSide : 0; + flags |= (t->getYMax() == s->getYMin()) ? Flags::SouthSide : 0; + + if (flags & Flags::Vertical) { + if (flags & Flags::Horizontal) return Box(); + if (flags & Flags::WestSide) + return Box( s->getXMin(), std::max( s->getYMin(), t->getYMin() ) + , s->getXMin(), std::min( s->getYMax(), t->getYMax() ) ); + else + return Box( t->getXMin(), std::max( s->getYMin(), t->getYMin() ) + , t->getXMin(), std::min( s->getYMax(), t->getYMax() ) ); + } + + if (flags & Flags::Horizontal) { + if (flags & Flags::Vertical) return Box(); + if (flags & Flags::NorthSide) + return Box( std::max( s->getXMin(), t->getXMin() ), t->getYMin() + , std::min( s->getXMax(), t->getXMax() ), t->getYMin() ); + else + return Box( std::max( s->getXMin(), t->getXMin() ), s->getYMin() + , std::min( s->getXMax(), t->getXMax() ), s->getYMin() ); + } + + return Box(); + } + + + GCell* GCell::vcut ( DbU::Unit x ) + { + cdebug.log(110,1) << "GCell::vcut() @x:" << DbU::getValueString(x) << " " << this << endl; + + if ( (x < getXMin()) or (x > getXMax()) ) + throw Error( "GCell::vcut(): Vertical cut axis at %s is outside GCell box,\n" + " in %s." + , DbU::getValueString(x).c_str() + , getString(this).c_str() + ); + + GCell* chunk = _create( x, getYMin() ); + + _moveEdges( chunk, 0, Flags::EastSide|Flags::MoveSide ); + Edge::create( this, chunk, Flags::Horizontal ); + + if (not _southEdges.empty()) { + cdebug.log(110) << "Split/create south edges." << endl; + + size_t iedge = 0; + for ( ; (iedge < _southEdges.size()) ; ++iedge ) { + cdebug.log(110) << "[" << iedge << "] xmax of:" + << _southEdges[iedge]->getOpposite(this) + << " " << _southEdges[iedge] << endl; + if (x <= _southEdges[iedge]->getOpposite(this)->getXMax()) break; + } + if (x < _southEdges[iedge]->getOpposite(this)->getXMax()) + Edge::create( _southEdges[iedge]->getOpposite(this), chunk, Flags::Vertical ); + _moveEdges( chunk, iedge+1, Flags::SouthSide ); + } + + if (not _northEdges.empty()) { + cdebug.log(110) << "Split/create north edges." << endl; + + size_t iedge = 0; + for ( ; (iedge < _northEdges.size()) ; ++iedge ) + if (x <= _northEdges[iedge]->getOpposite(this)->getXMax()) break; + if (x < _northEdges[iedge]->getOpposite(this)->getXMax()) + Edge::create( chunk, _northEdges[iedge]->getOpposite(this), Flags::Vertical ); + _moveEdges( chunk, iedge+1, Flags::NorthSide ); + } + + _revalidate(); + chunk->_revalidate(); + + cdebug.tabw(110,-1); + + return chunk; + } + + + GCell* GCell::hcut ( DbU::Unit y ) + { + cdebug.log(110,1) << "GCell::hcut() @y:" << DbU::getValueString(y) << " " << this << endl; + + if ( (y < getYMin()) or (y > getYMax()) ) + throw Error( "GCell::hcut(): Horizontal cut axis at %s is outside GCell box,\n" + " in %s." + , DbU::getValueString(y).c_str() + , getString(this).c_str() + ); + + GCell* chunk = _create( getXMin(), y ); + + _moveEdges( chunk, 0, Flags::NorthSide|Flags::MoveSide ); + Edge::create( this, chunk, Flags::Vertical ); + + if (not _westEdges.empty()) { + size_t iedge = 0; + for ( ; (iedge < _westEdges.size()) ; ++iedge ) + if (y <= _westEdges[iedge]->getOpposite(this)->getYMax()) break; + if (y < _westEdges[iedge]->getOpposite(this)->getYMax()) + Edge::create( _westEdges[iedge]->getOpposite(this), chunk, Flags::Horizontal ); + _moveEdges( chunk, iedge+1, Flags::WestSide ); + } + + if (not _eastEdges.empty()) { + size_t iedge = 0; + for ( ; (iedge < _eastEdges.size()) ; ++iedge ) + if (y <= _eastEdges[iedge]->getOpposite(this)->getYMax()) break; + if (y < _eastEdges[iedge]->getOpposite(this)->getYMax()) + Edge::create( chunk, _eastEdges[iedge]->getOpposite(this), Flags::Horizontal ); + _moveEdges( chunk, iedge+1, Flags::EastSide ); + } + + _revalidate(); + chunk->_revalidate(); + + cdebug.tabw(110,-1); + + return chunk; + } + + + bool GCell::doGrid () + { + DbU::Unit side = getAnabatic()->getConfiguration()->getSliceHeight(); + + Interval hspan = getSide( Flags::Horizontal ); + Interval vspan = getSide( Flags::Vertical ); + + if (hspan.getSize() < 3*side) { + cerr << Error( "GCell::doGrid(): GCell is too narrow (dx:%s) to build a grid.\n" + " (%s)" + , DbU::getValueString(hspan.getSize()).c_str() + , getString(this).c_str() + ) << endl; + return false; + } + + if (vspan.getSize() < 3*side) { + cerr << Error( "GCell::doGrid(): GCell is too narrow (dy:%s) to build a grid.\n" + " (%s)" + , DbU::getValueString(vspan.getSize()).c_str() + , getString(this).c_str() + ) << endl; + return false; + } + + GCell* row = this; + GCell* column = NULL; + DbU::Unit ycut = vspan.getVMin()+side; + for ( ; ycut < vspan.getVMax() ; ycut += side ) { + column = row; + row = row->hcut( ycut ); + + for ( DbU::Unit xcut = hspan.getVMin()+side ; xcut < hspan.getVMax() ; xcut += side ) { + column = column->vcut( xcut ); + } + } + + column = row; + for ( DbU::Unit xcut = hspan.getVMin()+side ; xcut < hspan.getVMax() ; xcut += side ) { + column = column->vcut( xcut ); + } + + return true; + } + + + void GCell::_revalidate () + { + cdebug.log(110,1) << "GCell::revalidate() " << this << endl; + cdebug.log(110,1) << "West side." << endl; for ( Edge* edge : _westEdges ) edge->revalidate(); cdebug.tabw(110,-1); + cdebug.log(110,1) << "East side." << endl; for ( Edge* edge : _eastEdges ) edge->revalidate(); cdebug.tabw(110,-1); + cdebug.log(110,1) << "South side." << endl; for ( Edge* edge : _southEdges ) edge->revalidate(); cdebug.tabw(110,-1); + cdebug.log(110,1) << "North side." << endl; for ( Edge* edge : _northEdges ) edge->revalidate(); cdebug.tabw(110,-1); + + _anabatic->_updateLookup( this ); + cdebug.tabw(110,-1); + } + + + void GCell::_moveEdges ( GCell* dest, size_t ibegin, Flags flags ) + { + cdebug.log(110,1) << "GCell::_moveEdges() " << this << endl; + cdebug.log(110) << " toward " << dest << endl; + cdebug.log(110) << " ibegin: " << ibegin << " flags:" << flags << endl; + + size_t iclear = ibegin; + + if (flags.contains(Flags::SouthSide) and not _southEdges.empty()) { + cdebug.log(110) << "South side." << endl; + + if (iclear < _southEdges.size()) { + for ( size_t iedge=ibegin ; (iedge < _southEdges.size()) ; ++iedge ) { + if (flags & Flags::MoveSide) _southEdges[iedge]->_setSource( dest ); + else _southEdges[iedge]->_setTarget( dest ); + dest->_southEdges.push_back( _southEdges[iedge] ); + } + _southEdges.resize( iclear ); + } else { + if (iclear > _southEdges.size()) + cerr << Error("GCell::_moveEdges(): On south side, iclear=%u is greater than size()-1=%u\n" + " (%s)" + , iclear + , _southEdges.size() + , getString(this).c_str() + ) << endl; + } + } + + if (flags.contains(Flags::NorthSide) and not _northEdges.empty()) { + cdebug.log(110) << "North side." << endl; + + if (iclear < _northEdges.size()) { + for ( size_t iedge=ibegin ; (iedge < _northEdges.size()) ; ++iedge ) { + if (flags & Flags::MoveSide) _northEdges[iedge]->_setTarget( dest ); + else _northEdges[iedge]->_setSource( dest ); + dest->_northEdges.push_back( _northEdges[iedge] ); + } + _northEdges.resize( iclear ); + } else { + if (iclear > _northEdges.size()) + cerr << Error("GCell::_moveEdges(): On north side, iclear=%u is greater than size()-1=%u\n" + " (%s)" + , iclear + , _northEdges.size() + , getString(this).c_str() + ) << endl; + } + } + + if (flags.contains(Flags::WestSide) and not _westEdges.empty()) { + cdebug.log(110) << "West side." << endl; + + if (iclear < _westEdges.size()) { + for ( size_t iedge=ibegin ; (iedge < _westEdges.size()) ; ++iedge ) { + if (flags & Flags::MoveSide) _westEdges[iedge]->_setSource( dest ); + else _westEdges[iedge]->_setTarget( dest ); + dest->_westEdges.push_back( _westEdges[iedge] ); + } + _westEdges.resize( iclear ); + } else { + if (iclear > _westEdges.size()) + cerr << Error("GCell::_moveEdges(): On west side, iclear=%u is greater than size()-1=%u\n" + " (%s)" + , iclear + , _westEdges.size() + , getString(this).c_str() + ) << endl; + } + } + + if (flags.contains(Flags::EastSide) and not _eastEdges.empty()) { + cdebug.log(110) << "East side." << endl; + + if (iclear < _eastEdges.size()) { + for ( size_t iedge=ibegin ; (iedge < _eastEdges.size()) ; ++iedge ) { + if (flags & Flags::MoveSide) _eastEdges[iedge]->_setTarget( dest ); + else _eastEdges[iedge]->_setSource( dest ); + dest->_eastEdges.push_back( _eastEdges[iedge] ); + } + _eastEdges.resize( iclear ); + } else { + if (iclear > _eastEdges.size()) + cerr << Error("GCell::_moveEdges(): On east side, iclear=%u is greater than size()-1=%u\n" + " (%s)" + , iclear + , _eastEdges.size() + , getString(this).c_str() + ) << endl; + } + } + + cdebug.tabw(110,-1); + } + + + const Name& GCell::getName () const + { return _extensionName; } + + + Box GCell::getBoundingBox () const + { + return Box( getXMin(), getYMin(), getXMax(), getYMax() ); + } + + + void GCell::translate ( const DbU::Unit&, const DbU::Unit& ) + { + cerr << Error( "GCell::translate(): On %s,\n" + " Must never be called on a GCell object (ignored)." + , getString(this).c_str() + ) << endl; + } + + + string GCell::_getTypeName () const + { return getString(_extensionName); } + + + string GCell::_getString () const + { + string s = Super::_getString(); + s.insert( s.size()-1, " "+getString(getBoundingBox()) ); + s.insert( s.size()-1, " "+getString(_flags) ); + return s; + } + + + Record* GCell::_getRecord () const + { + Record* record = Super::_getRecord(); + record->add( getSlot("_flags" , &_flags ) ); + record->add( getSlot("_westEdges" , &_westEdges ) ); + record->add( getSlot("_eastEdges" , &_eastEdges ) ); + record->add( getSlot("_southEdges", &_southEdges) ); + record->add( getSlot("_northEdges", &_northEdges) ); + record->add( DbU::getValueSlot("_xmin", &_xmin) ); + record->add( DbU::getValueSlot("_ymin", &_ymin) ); + return record; + } + + + +} // Anabatic namespace. diff --git a/anabatic/src/GraphicAnabaticEngine.cpp b/anabatic/src/GraphicAnabaticEngine.cpp new file mode 100644 index 00000000..ddc037ab --- /dev/null +++ b/anabatic/src/GraphicAnabaticEngine.cpp @@ -0,0 +1,286 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "GraphicAnabaticEngine.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "anabatic/GCell.h" +#include "anabatic/GraphicAnabaticEngine.h" + + +namespace Anabatic { + + using namespace std; + using Hurricane::Error; + using Hurricane::Warning; + using Hurricane::Exception; + using Hurricane::Breakpoint; + using Hurricane::DebugSession; + using Hurricane::Point; + using Hurricane::Entity; + using Hurricane::Net; + using Hurricane::Graphics; + using Hurricane::ColorScale; + using Hurricane::DisplayStyle; + using Hurricane::ControllerWidget; + using Hurricane::ExceptionWidget; + using CRL::Catalog; + using CRL::AllianceFramework; + + + size_t GraphicAnabaticEngine::_references = 0; + GraphicAnabaticEngine* GraphicAnabaticEngine::_singleton = NULL; + + + void GraphicAnabaticEngine::initGCell ( CellWidget* widget ) + { + widget->getDrawingPlanes().setPen( Qt::NoPen ); + } + + + void GraphicAnabaticEngine::drawGCell ( CellWidget* widget + , const Go* go + , const BasicLayer* basicLayer + , const Box& box + , const Transformation& transformation + ) + { + const GCell* gcell = static_cast(go); + + QPainter& painter = widget->getPainter(); + + painter.setPen ( Graphics::getPen ("gcell",widget->getDarkening()) ); + painter.setBrush( Graphics::getBrush("gcell",widget->getDarkening()) ); + painter.drawRect( widget->dbuToScreenRect(gcell->getBoundingBox()) ); + } + + + void GraphicAnabaticEngine::initEdge ( CellWidget* widget ) + { + widget->getDrawingPlanes().setPen( Qt::NoPen ); + } + + + void GraphicAnabaticEngine::drawEdge ( CellWidget* widget + , const Go* go + , const BasicLayer* basicLayer + , const Box& box + , const Transformation& transformation + ) + { + const Edge* edge = static_cast(go); + + if (edge) { + unsigned int occupancy = 255; + if (edge->getRealOccupancy() < edge->getCapacity()) + occupancy = (unsigned int)( 255.0 * ( (float)edge->getRealOccupancy() / (float)edge->getCapacity() ) ); + + QPainter& painter = widget->getPainter(); + if (edge->getRealOccupancy() > edge->getCapacity()) { + QColor color ( Qt::cyan ); + painter.setPen( DisplayStyle::darken(color,widget->getDarkening()) ); + } + + QBrush brush = QBrush( Qt::white, Qt::DiagCrossPattern ); + if (edge->getCapacity() > 0.0) + brush = Graphics::getColorScale( ColorScale::Fire ).getBrush( occupancy, widget->getDarkening() ); + + painter.setPen( Qt::NoPen ); + painter.setBrush( brush ); + painter.drawRect( widget->dbuToScreenRect(edge->getBoundingBox(), false) ); + } + } + + + AnabaticEngine* GraphicAnabaticEngine::createEngine () + { + Cell* cell = getCell(); + + AnabaticEngine* engine = AnabaticEngine::get( cell ); + if (not engine) { + engine = AnabaticEngine::create( cell ); + } else + cerr << Warning( "%s already has a Anabatic engine.", getString(cell).c_str() ) << endl; + + return engine; + } + + + AnabaticEngine* GraphicAnabaticEngine::getForFramework ( unsigned int flags ) + { + // Currently, only one framework is avalaible: Alliance. + + AnabaticEngine* engine = AnabaticEngine::get( getCell() ); + if (engine) return engine; + + if (flags & CreateEngine) { + engine = createEngine(); + if (not engine) + throw Error( "Failed to create Anabatic engine on %s.", getString(getCell()).c_str() ); + } else { + throw Error( "AnabaticEngine not created yet, run the global router first." ); + } + + return engine; + } + + + void GraphicAnabaticEngine::_runTest () + { + if (_viewer) _viewer->emitCellAboutToChange(); + AnabaticEngine* engine = getForFramework( CreateEngine ); + + engine->getSouthWestGCell()->doGrid(); + + // GCell* row0 = getSouthWestGCell(); + // DbU::Unit xcorner = getCell()->getAbutmentBox().getXMin(); + // DbU::Unit ycorner = getCell()->getAbutmentBox().getYMin(); + + // cdebug.log(119,1) << "row0: " << row0 << endl; + + // GCell* row1 = row0->hcut( ycorner+DbU::fromLambda(50.0) ); + // cdebug.tabw(119,-1); + // cdebug.log(119,1) << "row1: " << row1 << endl; + + // GCell* row2 = row1->hcut( ycorner+DbU::fromLambda(2*50.0) ); + // cdebug.tabw(119,-1); + // cdebug.log(119,1) << "row2: " << row2 << endl; + + // row0 = row0->vcut( xcorner+DbU::fromLambda(50.0) ); + // cdebug.tabw(119,-1); + // cdebug.log(119,1) << "row0+1: " << row0 << endl; + + // row0 = row0->vcut( xcorner+DbU::fromLambda(3*50.0) ); + // cdebug.tabw(119,-1); + // cdebug.log(119,1) << "row0+2: " << row0 << endl; + + // row0 = row0->vcut( xcorner+DbU::fromLambda(5*50.0) ); + // cdebug.tabw(119,-1); + // cdebug.log(119,1) << "row0+3: " << row0 << endl; + + // row1 = row1->vcut( xcorner+DbU::fromLambda(2*50.0) ); + // cdebug.tabw(119,-1); + // cdebug.log(119,1) << "row1+1: " << row1 << endl; + + + // cdebug.tabw(119,-1); + + // gcell = gcell->hcut( ycut+DbU::fromLambda(50.0) ); + // cerr << "New GCell: " << gcell << endl; + + // DbU::Unit ycut = getCell()->getAbutmentBox().getYMin() + DbU::fromLambda(50.0); + // for ( ; ycut < getCell()->getAbutmentBox().getYMax() ; ycut += DbU::fromLambda(50.0) ) { + // cdebug.log(119,2) << "H cut line (y coordinate): " << DbU::getValueString(ycut) << endl; + // gcell = gcell->hcut( ycut ); + // cerr << gcell << endl; + // cdebug.tabw(119,-2); + // } + + // if (_viewer) _viewer->emitCellChanged(); + } + + + void GraphicAnabaticEngine::addToMenu ( CellViewer* viewer ) + { + assert( _viewer == NULL ); + + _viewer = viewer; + + if (_viewer->hasMenuAction("placeAndRoute.anabatic")) { + cerr << Warning( "GraphicAnabaticEngine::addToMenu() - Anabatic engine already hooked in." ) << endl; + return; + } + + _viewer->addToMenu( "placeAndRoute.anabatic" + , "Anabatic - &Test Run" + , "Perform a test run of Anabatic on the design" + , std::bind(&GraphicAnabaticEngine::_runTest,this) + ); + } + + + const Name& GraphicAnabaticEngine::getName () const + { return AnabaticEngine::staticGetName(); } + + + Cell* GraphicAnabaticEngine::getCell () + { + if (_viewer == NULL) { + throw Error( "Anabatic: GraphicAnabaticEngine not bound to any Viewer." ); + return NULL; + } + + if (_viewer->getCell() == NULL) { + throw Error( "Anabatic: No Cell is loaded into the Viewer." ); + return NULL; + } + + return _viewer->getCell(); + } + + + GraphicAnabaticEngine* GraphicAnabaticEngine::grab () + { + if (not _references) + _singleton = new GraphicAnabaticEngine (); + _references++; + + return _singleton; + } + + + size_t GraphicAnabaticEngine::release () + { + --_references; + if (not _references) { + delete _singleton; + _singleton = NULL; + } + return _references; + } + + + GraphicAnabaticEngine::GraphicAnabaticEngine () + : GraphicTool() + , _viewer (NULL) + { + addDrawGo( "Anabatic::GCell", initGCell, drawGCell ); + addDrawGo( "Anabatic::Edge" , initEdge , drawEdge ); + } + + + GraphicAnabaticEngine::~GraphicAnabaticEngine () + { } + + + +} // Anabatic namespace. diff --git a/anabatic/src/Matrix.cpp b/anabatic/src/Matrix.cpp new file mode 100644 index 00000000..5e40d90b --- /dev/null +++ b/anabatic/src/Matrix.cpp @@ -0,0 +1,127 @@ +// -*- mode: C++; explicit-buffer-name: "Matrix.cpp" -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./Matrix.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include "hurricane/Cell.h" +#include "anabatic/Matrix.h" +#include "anabatic/GCell.h" + + +namespace Anabatic { + + using std::cout; + using std::cerr; + using std::endl; + using std::ostringstream; + using Hurricane::Error; + + + Matrix::Matrix () + : _area () + , _side (1) + , _gcells() + , _imax (0) + , _jmax (0) + { } + + + Matrix::Matrix ( Box area, DbU::Unit side ) + : _area (area) + , _side (side) + , _gcells() + , _imax (0) + , _jmax (0) + { + _imax = _area.getWidth () / side; + _jmax = _area.getHeight() / side; + _gcells.resize( _imax*_jmax ); + } + + + Matrix::~Matrix () + { } + + + void Matrix::setCell ( Cell* cell, DbU::Unit side ) + { + _area = cell->getAbutmentBox(); + _side = side; + _imax = _area.getWidth () / side; + _jmax = _area.getHeight() / side; + _gcells.resize( _imax*_jmax ); + } + + + void Matrix::updateLookup ( GCell* gcell ) + { + cdebug.log(110,1) << "Matrix::updateLookup(): " << gcell << endl; + + Box gcellBb = gcell->getBoundingBox(); + Box updateArea = _area.getIntersection( gcellBb ); + + if (updateArea.isEmpty()) { + cerr << Error( "Matrix::updateLookup(): %s is not under area of %s." + , getString(gcell).c_str() + , getString(this).c_str() + ) << endl; + } + + Index indexMin = Index( this, updateArea.getXMin() , updateArea.getYMin() ); + Index indexMax = Index( this, updateArea.getXMax()-1, updateArea.getYMax()-1 ); + int xspan = indexMax.i() - indexMin.i(); + + cdebug.log(110) << "indexMin:" << indexMin << endl; + cdebug.log(110) << "indexMax:" << indexMax << endl; + + int index = indexMin.index(); + while ( index <= indexMax.index() ) { + _gcells[index] = gcell; + + if (index <= indexMax.j()) ++index; + else index += _imax - xspan; + } + + cdebug.tabw(110,-1); + } + + + string Matrix::_getTypeName () const + { return "Matrix"; } + + + string Matrix::_getString () const + { + ostringstream os; + os << "<" << _getTypeName() << " " << _imax << "x" << _jmax + << " " << _area << "/" << DbU::getValueString(_side) << ">"; + return os.str(); + } + + + Record* Matrix::_getRecord () const + { + Record* record = new Record( _getString() ); + record->add( getSlot ("_area" , _area ) ); + record->add( DbU::getValueSlot("_side" , &_side ) ); + record->add( getSlot ("_imax" , _imax ) ); + record->add( getSlot ("_jmax" , _jmax ) ); + record->add( getSlot ("_gcells", &_gcells) ); + return record; + } + + +} // Anabatic namespace; diff --git a/anabatic/src/PyAnabatic.cpp b/anabatic/src/PyAnabatic.cpp new file mode 100644 index 00000000..a83f8a4e --- /dev/null +++ b/anabatic/src/PyAnabatic.cpp @@ -0,0 +1,94 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./PyAnabatic.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/isobar/PyHurricane.h" +#include "hurricane/isobar/PyCell.h" +#include "anabatic/PyAnabaticEngine.h" +#include "anabatic/PyGraphicAnabaticEngine.h" + + +namespace Anabatic { + + using std::cerr; + using std::endl; + using Hurricane::tab; + using Isobar::__cs; + using CRL::PyTypeToolEngine; + using CRL::PyTypeGraphicTool; + + +#if !defined(__PYTHON_MODULE__) + +// +=================================================================+ +// | "PyAnabatic" Shared Library Code Part | +// +=================================================================+ + + +# else // End of PyHurricane Shared Library Code Part. + + +// +=================================================================+ +// | "PyAnabatic" Python Module Code Part | +// +=================================================================+ + + +extern "C" { + + + // +-------------------------------------------------------------+ + // | "PyAnabatic" Module Methods | + // +-------------------------------------------------------------+ + + + static PyMethodDef PyAnabatic_Methods[] = + { {NULL, NULL, 0, NULL} /* sentinel */ + }; + + + // --------------------------------------------------------------- + // Module Initialization : "initAnabatic ()" + + DL_EXPORT(void) initAnabatic () { + cdebug.log(32) << "initAnabatic()" << endl; + + PyAnabaticEngine_LinkPyType(); + PyGraphicAnabaticEngine_LinkPyType(); + + PYTYPE_READY_SUB( AnabaticEngine , ToolEngine ); + PYTYPE_READY_SUB( GraphicAnabaticEngine, GraphicTool ); + + + PyObject* module = Py_InitModule( "Anabatic", PyAnabatic_Methods ); + if (module == NULL) { + cerr << "[ERROR]\n" + << " Failed to initialize Anabatic module." << endl; + return; + } + + Py_INCREF( &PyTypeAnabaticEngine ); + PyModule_AddObject( module, "AnabaticEngine", (PyObject*)&PyTypeAnabaticEngine ); + Py_INCREF( &PyTypeGraphicAnabaticEngine ); + PyModule_AddObject( module, "GraphicAnabaticEngine", (PyObject*)&PyTypeGraphicAnabaticEngine ); + } + + +} // End of extern "C". + + +#endif // End of Python Module Code Part. + + +} // End of Anabatic namespace. diff --git a/anabatic/src/PyAnabaticEngine.cpp b/anabatic/src/PyAnabaticEngine.cpp new file mode 100644 index 00000000..3fe9d06f --- /dev/null +++ b/anabatic/src/PyAnabaticEngine.cpp @@ -0,0 +1,217 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./PyAnabaticEngine.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/isobar/PyCell.h" +#include "hurricane/viewer/PyCellViewer.h" +#include "hurricane/viewer/ExceptionWidget.h" +#include "hurricane/Cell.h" +#include "anabatic/PyAnabaticEngine.h" +#include + +# undef ACCESS_OBJECT +# undef ACCESS_CLASS +# define ACCESS_OBJECT _baseObject._object +# define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject) +#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(AnabaticEngine,engine,function) + + +namespace Anabatic { + + using std::cerr; + using std::endl; + using std::hex; + using std::ostringstream; + using Hurricane::tab; + using Hurricane::Exception; + using Hurricane::Bug; + using Hurricane::Error; + using Hurricane::Warning; + using Hurricane::ExceptionWidget; + using Isobar::ProxyProperty; + using Isobar::ProxyError; + using Isobar::ConstructorError; + using Isobar::HurricaneError; + using Isobar::HurricaneWarning; + using Isobar::ParseOneArg; + using Isobar::ParseTwoArg; + using Isobar::PyCell; + using Isobar::PyCell_Link; + using Isobar::PyCellViewer; + using Isobar::PyTypeCellViewer; + using CRL::PyToolEngine; + + +extern "C" { + +#if defined(__PYTHON_MODULE__) + + +#define DirectVoidToolMethod(SELF_TYPE, SELF_OBJECT, FUNC_NAME) \ + static PyObject* Py##SELF_TYPE##_##FUNC_NAME(Py##SELF_TYPE* self) \ + { \ + trace << "Py" #SELF_TYPE "_" #FUNC_NAME "()" << endl; \ + HTRY \ + METHOD_HEAD(#SELF_TYPE "." #FUNC_NAME "()") \ + if (SELF_OBJECT->getViewer()) { \ + if (ExceptionWidget::catchAllWrapper( std::bind(&AnabaticEngine::FUNC_NAME,SELF_OBJECT) )) { \ + PyErr_SetString( HurricaneError, #FUNC_NAME "() has thrown an exception (C++)." ); \ + return NULL; \ + } \ + } else { \ + SELF_OBJECT->FUNC_NAME(); \ + } \ + HCATCH \ + Py_RETURN_NONE; \ + } + + +// +=================================================================+ +// | "PyAnabaticEngine" Python Module Code Part | +// +=================================================================+ + + + static PyObject* PyAnabaticEngine_get ( PyObject*, PyObject* args ) + { + cdebug.log(32) << "PyAnabaticEngine_get()" << endl; + + AnabaticEngine* engine = NULL; + + HTRY + PyObject* arg0; + + if (not ParseOneArg("Anabatic.get", args, CELL_ARG, &arg0)) return NULL; + engine = AnabaticEngine::get(PYCELL_O(arg0)); + HCATCH + + return PyAnabaticEngine_Link(engine); + } + + + static PyObject* PyAnabaticEngine_create ( PyObject*, PyObject* args ) + { + cdebug.log(32) << "PyAnabaticEngine_create()" << endl; + + AnabaticEngine* engine = NULL; + + HTRY + PyObject* arg0; + + if (not ParseOneArg("Anabatic.get", args, CELL_ARG, &arg0)) return NULL; + + Cell* cell = PYCELL_O(arg0); + engine = AnabaticEngine::get(cell); + + if (engine == NULL) { + engine = AnabaticEngine::create(cell); + } else + cerr << Warning("%s already has a Anabatic engine.",getString(cell).c_str()) << endl; + HCATCH + + return PyAnabaticEngine_Link(engine); + } + + + static PyObject* PyAnabaticEngine_setViewer ( PyAnabaticEngine* self, PyObject* args ) + { + cdebug.log(32) << "PyAnabaticEngine_setViewer ()" << endl; + + HTRY + METHOD_HEAD( "AnabaticEngine.setViewer()" ) + + PyObject* pyViewer = NULL; + if (not PyArg_ParseTuple(args,"O:EtesianEngine.setViewer()",&pyViewer)) { + PyErr_SetString( ConstructorError, "Bad parameters given to EtesianEngine.setViewer()." ); + return NULL; + } + if (IsPyCellViewer(pyViewer)) { + engine->setViewer( PYCELLVIEWER_O(pyViewer) ); + } + HCATCH + + Py_RETURN_NONE; + } + + + PyObject* PyAnabaticEngine_runTest ( PyAnabaticEngine* self, PyObject* args ) + { + cdebug.log(32) << "PyAnabaticEngine_runTest()" << endl; + + HTRY + METHOD_HEAD("AnabaticEngine.runTest()") + unsigned int flags = 0; + if (PyArg_ParseTuple(args,"I:AnabaticEngine.runTest", &flags)) { + if (engine->getViewer()) { + if (ExceptionWidget::catchAllWrapper( std::bind(&AnabaticEngine::_runTest,engine) )) { + PyErr_SetString( HurricaneError, "AnabaticEngine::runTest() has thrown an exception (C++)." ); + return NULL; + } + } else { + engine->_runTest(); + } + } else { + PyErr_SetString(ConstructorError, "AnabaticEngine.runGlobalRouter(): Invalid number/bad type of parameter."); + return NULL; + } + HCATCH + + Py_RETURN_NONE; + } + + + // Standart Accessors (Attributes). + + // Standart Destroy (Attribute). + DBoDestroyAttribute(PyAnabaticEngine_destroy,PyAnabaticEngine) + + + PyMethodDef PyAnabaticEngine_Methods[] = + { { "get" , (PyCFunction)PyAnabaticEngine_get , METH_VARARGS|METH_STATIC + , "Returns the Anabatic engine attached to the Cell, None if there isnt't." } + , { "create" , (PyCFunction)PyAnabaticEngine_create , METH_VARARGS|METH_STATIC + , "Create a Anabatic engine on this cell." } + , { "setViewer" , (PyCFunction)PyAnabaticEngine_setViewer , METH_VARARGS + , "Associate a Viewer to this AnabaticEngine." } + , { "runTest" , (PyCFunction)PyAnabaticEngine_runTest , METH_VARARGS + , "Run the test procedure." } + , { "destroy" , (PyCFunction)PyAnabaticEngine_destroy , METH_NOARGS + , "Destroy the associated hurricane object. The python object remains." } + , {NULL, NULL, 0, NULL} /* sentinel */ + }; + + + DBoDeleteMethod(AnabaticEngine) + PyTypeObjectLinkPyType(AnabaticEngine) + + +#else // End of Python Module Code Part. + + +// +=================================================================+ +// | "PyAnabaticEngine" Shared Library Code Part | +// +=================================================================+ + + + // Link/Creation Method. + PyTypeInheritedObjectDefinitions(AnabaticEngine,PyToolEngine) + DBoLinkCreateMethod(AnabaticEngine) + + +#endif // Shared Library Code Part. + +} // extern "C". + +} // Anabatic namespace. + diff --git a/anabatic/src/PyGraphicAnabaticEngine.cpp b/anabatic/src/PyGraphicAnabaticEngine.cpp new file mode 100644 index 00000000..da307240 --- /dev/null +++ b/anabatic/src/PyGraphicAnabaticEngine.cpp @@ -0,0 +1,122 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./PyGraphicAnabaticEngine.cpp" | +// +-----------------------------------------------------------------+ + + +#include "anabatic/PyGraphicAnabaticEngine.h" +#include "hurricane/isobar/PyCell.h" +#include "hurricane/Cell.h" + + +#undef ACCESS_OBJECT +#undef ACCESS_CLASS +#define ACCESS_OBJECT _baseObject._object +#define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject) +#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(GraphicAnabaticEngine,gengine,function) + + +namespace Anabatic { + +using namespace Hurricane; +using namespace Isobar; + +extern "C" { + + +// +=================================================================+ +// | "PyGraphicAnabaticEngine" Python Module Code Part | +// +=================================================================+ + +#if defined(__PYTHON_MODULE__) + + + // +-------------------------------------------------------------+ + // | "PyGraphicAnabaticEngine" Attribute Methods | + // +-------------------------------------------------------------+ + + + static PyObject* PyGraphicAnabaticEngine_grab ( PyObject* ) + { + cdebug.log(32) << "PyGraphicAnabaticEngine_grab()" << endl; + PyGraphicAnabaticEngine* pyGraphicAnabaticEngine = NULL; + + HTRY + pyGraphicAnabaticEngine = PyObject_NEW ( PyGraphicAnabaticEngine, &PyTypeGraphicAnabaticEngine ); + if ( pyGraphicAnabaticEngine == NULL ) return NULL; + + pyGraphicAnabaticEngine->ACCESS_OBJECT = GraphicAnabaticEngine::grab(); + HCATCH + + return (PyObject*)pyGraphicAnabaticEngine; + } + + + static PyObject* PyGraphicAnabaticEngine_getCell ( PyGraphicAnabaticEngine* self ) + { + cdebug.log(32) << "PyGraphicAnabaticEngine_getCell ()" << endl; + + Cell* cell = NULL; + + HTRY + METHOD_HEAD("GraphicAnabaticEngine.getCell()") + cell = gengine->getCell (); + HCATCH + + if (cell == NULL) Py_RETURN_NONE; + return PyCell_Link(cell); + } + + + GetNameMethod(GraphicAnabaticEngine, gengine) + + // Standart destroy (Attribute). + + + PyMethodDef PyGraphicAnabaticEngine_Methods[] = + { { "grab" , (PyCFunction)PyGraphicAnabaticEngine_grab , METH_NOARGS|METH_STATIC + , "Returns the GraphicAnabaticEngine singleton." } + , { "getName" , (PyCFunction)PyGraphicAnabaticEngine_getName , METH_NOARGS + , "Returns the name of the GraphicAnabaticEngine (class attribute)." } + , { "getCell" , (PyCFunction)PyGraphicAnabaticEngine_getCell , METH_NOARGS + , "Returns the Cell on which this GraphicAnabaticEngine is attached." } + , {NULL, NULL, 0, NULL} /* sentinel */ + }; + + + // --------------------------------------------------------------- + // PyGraphicAnabaticEngine Type Methods. + + + PythonOnlyDeleteMethod(GraphicAnabaticEngine) + PyTypeObjectLinkPyType(GraphicAnabaticEngine) + + +#else // End of Python Module Code Part. + + +// +=================================================================+ +// | "PyGraphicAnabaticEngine" Shared Library Code Part | +// +=================================================================+ + + // Link/Creation Method. + LinkCreateMethod(GraphicAnabaticEngine) + + PyTypeInheritedObjectDefinitions(GraphicAnabaticEngine,GraphicTool) + + +#endif // End of Shared Library Code Part. + +} // extern "C". + +} // CRL namespace. diff --git a/anabatic/src/anabatic/AnabaticEngine.h b/anabatic/src/anabatic/AnabaticEngine.h new file mode 100644 index 00000000..31c0268d --- /dev/null +++ b/anabatic/src/anabatic/AnabaticEngine.h @@ -0,0 +1,92 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./anabatic/AnabaticEngine.h" | +// +-----------------------------------------------------------------+ + + +#ifndef ANABATIC_ANABATIC_ENGINE_H +#define ANABATIC_ANABATIC_ENGINE_H + +#include + +namespace Hurricane { + class Name; + class Cell; + class Instance; + class CellViewer; +} + +#include "crlcore/ToolEngine.h" +#include "anabatic/Configuration.h" +#include "anabatic/Matrix.h" + + +namespace Anabatic { + + using std::string; + using Hurricane::Name; + using Hurricane::Record; + using Hurricane::Cell; + using Hurricane::CellViewer; + using CRL::ToolEngine; + + class GCell; + + + class AnabaticEngine : public ToolEngine { + public: + typedef ToolEngine Super; + public: + static AnabaticEngine* create ( Cell* ); + static AnabaticEngine* get ( const Cell* ); + static const Name& staticGetName (); + virtual const Name& getName () const; + virtual Configuration* getConfiguration (); + inline CellViewer* getViewer () const; + inline void setViewer ( CellViewer* ); + inline GCell* getSouthWestGCell () const; + inline void _updateLookup ( GCell* ); + void _runTest (); + // Inspector support. + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + protected: + AnabaticEngine ( Cell* ); + virtual ~AnabaticEngine (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + AnabaticEngine ( const AnabaticEngine& ); + AnabaticEngine& operator= ( const AnabaticEngine& ); + private: + static Name _toolName; + Configuration* _configuration; + Matrix _matrix; + GCell* _southWestGCell; + CellViewer* _viewer; + }; + + + inline CellViewer* AnabaticEngine::getViewer () const { return _viewer; } + inline void AnabaticEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; } + inline GCell* AnabaticEngine::getSouthWestGCell () const { return _southWestGCell; } + inline void AnabaticEngine::_updateLookup ( GCell* gcell ) { _matrix.updateLookup(gcell); } + + +} // Anabatic namespace. + + +INSPECTOR_P_SUPPORT(Anabatic::AnabaticEngine); + +#endif // ANABATIC_ANABATIC_ENGINE_H diff --git a/anabatic/src/anabatic/Configuration.h b/anabatic/src/anabatic/Configuration.h new file mode 100644 index 00000000..f9479de2 --- /dev/null +++ b/anabatic/src/anabatic/Configuration.h @@ -0,0 +1,159 @@ +// -*- mode: C++; explicit-buffer-name: "Configuration.h" -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./anabatic/Configuration.h" | +// +-----------------------------------------------------------------+ + + +#ifndef ANABATIC_CONFIGURATION_H +#define ANABATIC_CONFIGURATION_H + +#include +#include + +#include "hurricane/DbU.h" +namespace Hurricane { + class Layer; + class Cell; +} + +namespace CRL { + class CellGauge; + class RoutingGauge; + class RoutingLayerGauge; +} + +#include "anabatic/Constants.h" + + +namespace Anabatic { + + + using std::string; + using Hurricane::Record; + using Hurricane::Name; + using Hurricane::Layer; + using Hurricane::DbU; + using Hurricane::Cell; + using CRL::CellGauge; + using CRL::RoutingGauge; + using CRL::RoutingLayerGauge; + + +// ------------------------------------------------------------------- +// Class : "Anabatic::Configuration" (decorator). + + class Configuration { + public: + // Constructor & Destructor. + virtual ~Configuration (); + virtual Configuration* clone () const = 0; + // Methods. + virtual bool isGMetal ( const Layer* ) const = 0; + virtual bool isGContact ( const Layer* ) const = 0; + virtual size_t getDepth () const = 0; + virtual size_t getAllowedDepth () const = 0; + virtual size_t getLayerDepth ( const Layer* ) const = 0; + virtual CellGauge* getCellGauge () const = 0; + virtual RoutingGauge* getRoutingGauge () const = 0; + virtual RoutingLayerGauge* getLayerGauge ( size_t depth ) const = 0; + virtual const Layer* getRoutingLayer ( size_t depth ) const = 0; + virtual Layer* getContactLayer ( size_t depth ) const = 0; + virtual DbU::Unit getSliceHeight () const = 0; + virtual DbU::Unit getSliceStep () const = 0; + virtual DbU::Unit getPitch ( size_t depth, Flags flags ) const = 0; + virtual DbU::Unit getOffset ( size_t depth ) const = 0; + virtual DbU::Unit getWireWidth ( size_t depth ) const = 0; + virtual DbU::Unit getExtensionCap ( size_t depth ) const = 0; + virtual Flags getDirection ( size_t depth ) const = 0; + virtual DbU::Unit getPitch ( const Layer*, Flags flags ) const = 0; + virtual DbU::Unit getOffset ( const Layer* ) const = 0; + virtual DbU::Unit getWireWidth ( const Layer* ) const = 0; + virtual DbU::Unit getExtensionCap ( const Layer* ) const = 0; + virtual Flags getDirection ( const Layer* ) const = 0; + virtual void setAllowedDepth ( size_t ) = 0; + virtual void print ( Cell* ) const = 0; + virtual Record* _getRecord () const = 0; + virtual string _getString () const = 0; + virtual string _getTypeName () const = 0; + protected: + Configuration (); + private: + Configuration ( const Configuration& ); + Configuration& operator= ( const Configuration& ); + private: + static Configuration* _default; + }; + + +// ------------------------------------------------------------------- +// Class : "Anabatic::ConfigurationConcrete". + + class ConfigurationConcrete : public Configuration { + friend class Configuration; + public: + // Constructor & Destructor. + ConfigurationConcrete ( const CellGauge* cg=NULL, const RoutingGauge* rg=NULL ); + virtual ~ConfigurationConcrete (); + virtual ConfigurationConcrete* clone () const; + // Methods. + virtual bool isGMetal ( const Layer* ) const; + virtual bool isGContact ( const Layer* ) const; + virtual size_t getDepth () const; + virtual size_t getAllowedDepth () const; + virtual size_t getLayerDepth ( const Layer* ) const; + virtual CellGauge* getCellGauge () const; + virtual RoutingGauge* getRoutingGauge () const; + virtual RoutingLayerGauge* getLayerGauge ( size_t depth ) const; + virtual const Layer* getRoutingLayer ( size_t depth ) const; + virtual Layer* getContactLayer ( size_t depth ) const; + virtual DbU::Unit getSliceHeight () const; + virtual DbU::Unit getSliceStep () const; + virtual DbU::Unit getPitch ( size_t depth, Flags flags ) const; + virtual DbU::Unit getOffset ( size_t depth ) const; + virtual DbU::Unit getWireWidth ( size_t depth ) const; + virtual DbU::Unit getExtensionCap ( size_t depth ) const; + virtual Flags getDirection ( size_t depth ) const; + virtual DbU::Unit getPitch ( const Layer*, Flags flags ) const; + virtual DbU::Unit getOffset ( const Layer* ) const; + virtual DbU::Unit getWireWidth ( const Layer* ) const; + virtual DbU::Unit getExtensionCap ( const Layer* ) const; + virtual Flags getDirection ( const Layer* ) const; + virtual void setAllowedDepth ( size_t ); + virtual void print ( Cell* ) const; + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + protected: + // Attributes. + const Layer* _gmetalh; + const Layer* _gmetalv; + const Layer* _gcontact; + CellGauge* _cg; + RoutingGauge* _rg; + std::vector _extensionCaps; + size_t _allowedDepth; + private: + ConfigurationConcrete ( const ConfigurationConcrete& ); + ConfigurationConcrete& operator= ( const ConfigurationConcrete& ); + void _setTopRoutingLayer ( Name name ); + }; + + +} // Anabatic namespace. + + +INSPECTOR_P_SUPPORT(Anabatic::Configuration); +INSPECTOR_P_SUPPORT(Anabatic::ConfigurationConcrete); + + +#endif // ANABATIC_CONFIGURATION_H diff --git a/anabatic/src/anabatic/Constants.h b/anabatic/src/anabatic/Constants.h new file mode 100644 index 00000000..509c5498 --- /dev/null +++ b/anabatic/src/anabatic/Constants.h @@ -0,0 +1,60 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./anabatic/Constants.h" | +// +-----------------------------------------------------------------+ + + +#ifndef ANABATIC_CONSTANTS_H +#define ANABATIC_CONSTANTS_H + +#include "hurricane/Flags.h" + +namespace Anabatic { + + + class Flags : public Hurricane::BaseFlags { + public: + enum Flag { NoFlags = 0 + , Horizontal = (1<<0) + , Vertical = (1<<1) + , SourceGCell = (1<<2) + , TargetGCell = (1<<3) + , MoveSide = (1<<4) + , Invalidated = (1<<5) + , WestSide = Horizontal|TargetGCell + , EastSide = Horizontal|SourceGCell + , SouthSide = Vertical |TargetGCell + , NorthSide = Vertical |SourceGCell + , AllSides = WestSide|EastSide|SouthSide|NorthSide + , PitchAbove = (1<<6) + , PitchBelow = (1<<7) + }; + public: + inline Flags ( unsigned int flags = NoFlags ); + inline Flags ( BaseFlags ); + virtual ~Flags (); + virtual std::string _getTypeName () const; + virtual std::string _getString () const; + }; + + + Flags::Flags ( unsigned int flags ) : BaseFlags(flags) { } + Flags::Flags ( BaseFlags base ) : BaseFlags(base) { } + + +} // Anabatic namespace. + + +INSPECTOR_PV_SUPPORT(Anabatic::Flags) + +#endif // ANABATIC_CONSTANTS_H diff --git a/anabatic/src/anabatic/Edge.h b/anabatic/src/anabatic/Edge.h new file mode 100644 index 00000000..108180e9 --- /dev/null +++ b/anabatic/src/anabatic/Edge.h @@ -0,0 +1,115 @@ +// -*- mode: C++; explicit-buffer-name: "Edge.h" -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./anabatic/Edge.h" | +// +-----------------------------------------------------------------+ + + +#ifndef ANABATIC_EDGE_H +#define ANABATIC_EDGE_H + +#include +#include "hurricane/Name.h" +#include "hurricane/Interval.h" +#include "hurricane/Box.h" +#include "hurricane/ExtensionGo.h" +#include "anabatic/Constants.h" + + +namespace Anabatic { + + using std::string; + using Hurricane::Name; + using Hurricane::Record; + using Hurricane::DbU; + using Hurricane::Interval; + using Hurricane::Box; + using Hurricane::Cell; + using Hurricane::ExtensionGo; + + class GCell; + + + class Edge : public ExtensionGo { + public: + typedef ExtensionGo Super; + public: + static Edge* create ( GCell* source, GCell* target, Flags flags=Flags::NoFlags ); + virtual void destroy (); + public: + inline unsigned int getCapacity () const; + inline unsigned int getRealOccupancy () const; + inline unsigned int getEstimateOccupancy () const; + inline GCell* getSource () const; + inline GCell* getTarget () const; + GCell* getOpposite ( const GCell* ) const; + inline DbU::Unit getAxis () const; + DbU::Unit getAxisMin () const; + Interval getSide () const; + inline const Flags& flags () const; + inline Flags& flags (); + inline void invalidate (); + inline void revalidate () const; + void _setSource ( GCell* ); + void _setTarget ( GCell* ); + private: + void _revalidate (); + public: + // ExtensionGo support. + inline const Name& staticGetName (); + virtual const Name& getName () const; + virtual void translate ( const DbU::Unit&, const DbU::Unit& ); + virtual Box getBoundingBox () const; + public: + // Inspector support. + virtual string _getTypeName () const; + virtual string _getString () const; + virtual Record* _getRecord () const; + protected: + Edge ( GCell* source, GCell* target, Flags flags ); + virtual ~Edge (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + Edge ( const Edge& ); + Edge& operator= ( const Edge& ); + private: + static Name _extensionName; + Flags _flags; + unsigned int _capacity; + unsigned int _realOccupancy; + float _estimateOccupancy; + GCell* _source; + GCell* _target; + DbU::Unit _axis; + }; + + + inline const Name& Edge::staticGetName () { return _extensionName; } + inline unsigned int Edge::getCapacity () const { return _capacity; } + inline unsigned int Edge::getRealOccupancy () const { return _realOccupancy; } + inline unsigned int Edge::getEstimateOccupancy () const { return _estimateOccupancy; } + inline GCell* Edge::getSource () const { return _source; } + inline GCell* Edge::getTarget () const { return _target; } + inline DbU::Unit Edge::getAxis () const { return _axis; } + inline const Flags& Edge::flags () const { return _flags; } + inline Flags& Edge::flags () { return _flags; } + inline void Edge::invalidate () { _flags |= Flags::Invalidated; } + inline void Edge::revalidate () const { /*if (_flags&Flags::Invalidated)*/ const_cast(this)->_revalidate(); } + + +} // Anabatic namespace. + + +INSPECTOR_P_SUPPORT(Anabatic::Edge); + +#endif // ANABATIC_EDGE_H diff --git a/anabatic/src/anabatic/GCell.h b/anabatic/src/anabatic/GCell.h new file mode 100644 index 00000000..b921a104 --- /dev/null +++ b/anabatic/src/anabatic/GCell.h @@ -0,0 +1,132 @@ +// -*- mode: C++; explicit-buffer-name: "GCell.h" -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./anabatic/GCell.h" | +// +-----------------------------------------------------------------+ + + +#ifndef ANABATIC_GCELL_H +#define ANABATIC_GCELL_H + +#include +#include +#include "hurricane/Name.h" +#include "hurricane/Box.h" +#include "hurricane/Cell.h" +#include "hurricane/ExtensionGo.h" +#include "anabatic/Edge.h" + + +namespace Anabatic { + + using std::string; + using std::vector; + using Hurricane::Name; + using Hurricane::Record; + using Hurricane::DbU; + using Hurricane::Point; + using Hurricane::Interval; + using Hurricane::Box; + using Hurricane::Cell; + + class AnabaticEngine; + + + class GCell : public ExtensionGo { + public: + typedef ExtensionGo Super; + public: + static Box getBorder ( const GCell*, const GCell* ); + public: + static GCell* create ( AnabaticEngine* ); + virtual void destroy (); + public: + inline AnabaticEngine* getAnabatic () const; + inline DbU::Unit getXMin () const; + inline DbU::Unit getYMin () const; + inline DbU::Unit getXMax () const; + inline DbU::Unit getYMax () const; + inline Interval getSide ( Flags direction ) const; + inline Point getCenter () const; + GCell* hcut ( DbU::Unit y ); + GCell* vcut ( DbU::Unit x ); + bool doGrid (); + inline const Flags& flags () const; + inline Flags& flags (); + void _add ( Edge* edge, Flags side ); + void _remove ( Edge* edge, Flags side=Flags::AllSides ); + private: + void _revalidate (); + void _moveEdges ( GCell* dest, size_t ibegin, Flags flags ); + public: + // ExtensionGo support. + inline const Name& staticGetName (); + virtual const Name& getName () const; + virtual void translate ( const DbU::Unit&, const DbU::Unit& ); + virtual Box getBoundingBox () const; + public: + // Inspector support. + virtual string _getTypeName () const; + virtual string _getString () const; + virtual Record* _getRecord () const; + protected: + GCell ( AnabaticEngine*, DbU::Unit xmin, DbU::Unit ymin ); + virtual ~GCell (); + GCell* _create ( DbU::Unit xmin, DbU::Unit ymin ); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + GCell ( const GCell& ); + GCell& operator= ( const GCell& ); + private: + static Name _extensionName; + AnabaticEngine* _anabatic; + Flags _flags; + vector _westEdges; + vector _eastEdges; + vector _southEdges; + vector _northEdges; + DbU::Unit _xmin; + DbU::Unit _ymin; + }; + + + inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; } + inline DbU::Unit GCell::getXMin () const { return _xmin; } + inline DbU::Unit GCell::getYMin () const { return _ymin; } + inline const Flags& GCell::flags () const { return _flags; } + inline Flags& GCell::flags () { return _flags; } + + inline DbU::Unit GCell::getXMax () const + { return _eastEdges.empty() ? getCell()->getAbutmentBox().getXMax() + : _eastEdges[0]->getOpposite(this)->getXMin(); } + + inline DbU::Unit GCell::getYMax () const + { return _northEdges.empty() ? getCell()->getAbutmentBox().getYMax() + : _northEdges[0]->getOpposite(this)->getYMin(); } + + inline Point GCell::getCenter () const + { return Point( (getXMin()+getXMax())/2, (getYMin()+getYMax())/2); } + + inline Interval GCell::getSide ( Flags direction ) const + { + if (direction.isset(Flags::Vertical)) return Interval( getYMin(), getYMax() ); + return Interval( getXMin(), getXMax() ); + } + + +} // Anabatic namespace. + + +INSPECTOR_P_SUPPORT(Anabatic::GCell); + +#endif // ANABATIC_GCELL_H diff --git a/anabatic/src/anabatic/GraphicAnabaticEngine.h b/anabatic/src/anabatic/GraphicAnabaticEngine.h new file mode 100644 index 00000000..2bcc391e --- /dev/null +++ b/anabatic/src/anabatic/GraphicAnabaticEngine.h @@ -0,0 +1,90 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./anabatic/GraphicAnabaticEngine.h" | +// +-----------------------------------------------------------------+ + + +#ifndef ANABATIC_GRAPHIC_ANABATIC_ENGINE_H +#define ANABATIC_GRAPHIC_ANABATIC_ENGINE_H + +#include +#include + +namespace Hurricane { + class Go; + class BasicLayer; + class Transformation; + class CellWidget; + class CellViewer; +} + +#include "crlcore/GraphicToolEngine.h" +#include "anabatic/AnabaticEngine.h" + + +namespace Anabatic { + + using Hurricane::Go; + using Hurricane::Box; + using Hurricane::BasicLayer; + using Hurricane::Transformation; + using Hurricane::CellWidget; + using Hurricane::CellViewer; + using CRL::GraphicTool; + + +// ------------------------------------------------------------------- +// Class : "Anabatic::GraphicAnabaticEngine". + + class GraphicAnabaticEngine : public GraphicTool { + Q_OBJECT; + + public: + enum Flags { NoFlags=0x0000, CreateEngine=0x0001 }; + public: + AnabaticEngine* createEngine (); + AnabaticEngine* getForFramework ( unsigned int flags ); + static void initGCell ( CellWidget* ); + static void drawGCell ( CellWidget* + , const Go* + , const BasicLayer* + , const Box& + , const Transformation& + ); + static void initEdge ( CellWidget* ); + static void drawEdge ( CellWidget* + , const Go* + , const BasicLayer* + , const Box& + , const Transformation& + ); + static GraphicAnabaticEngine* grab (); + virtual const Name& getName () const; + Cell* getCell (); + virtual size_t release (); + virtual void addToMenu ( CellViewer* ); + + protected: + static size_t _references; + static GraphicAnabaticEngine* _singleton; + CellViewer* _viewer; + protected: + GraphicAnabaticEngine (); + virtual ~GraphicAnabaticEngine (); + void _runTest (); + }; + + +} // Anabatic namespace. + +#endif // ANABATIC_GRAPHIC_ANABATIC_ENGINE_H diff --git a/anabatic/src/anabatic/Matrix.h b/anabatic/src/anabatic/Matrix.h new file mode 100644 index 00000000..4670bef2 --- /dev/null +++ b/anabatic/src/anabatic/Matrix.h @@ -0,0 +1,210 @@ +// -*- mode: C++; explicit-buffer-name: "Matrix.h" -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./anabatic/Matrix.h" | +// +-----------------------------------------------------------------+ + + +#ifndef ANABATIC_MATRIX_H +#define ANABATIC_MATRIX_H + +#include +#include +#include +#include "hurricane/Box.h" +namespace Hurricane { + class Cell; +} + + +namespace Anabatic { + + using std::string; + using std::vector; + using std::ostream; + using Hurricane::Record; + using Hurricane::DbU; + using Hurricane::Point; + using Hurricane::Box; + using Hurricane::Cell; + + class GCell; + + + class Matrix { + public: + class Index { + public: + inline Index ( Matrix*, int index ); + inline Index ( Matrix*, int i, int j ); + inline Index ( Matrix*, DbU::Unit x, DbU::Unit y ); + inline Index ( Matrix*, Point position ); + inline Matrix* matrix () const; + inline const int& index () const; + inline int& index (); + inline bool valid () const; + inline int i () const; + inline int j () const; + inline Index& west (); + inline Index& east (); + inline Index& south (); + inline Index& north (); + private: + Matrix* _matrix; + int _index; + }; + public: + Matrix (); + Matrix ( Box area, DbU::Unit side ); + ~Matrix (); + inline Box getArea () const; + inline DbU::Unit getSide () const; + inline int getIMax () const; + inline int getJMax () const; + inline int index2i ( int ) const; + inline int index2j ( int ) const; + inline int index2i ( const Index& ) const; + inline int index2j ( const Index& ) const; + inline int ij2index ( int i, int j ) const; + inline int xy2index ( DbU::Unit x, DbU::Unit y ) const; + inline int xy2index ( Point ) const; + inline Index& west ( Index& ) const; + inline Index& east ( Index& ) const; + inline Index& south ( Index& ) const; + inline Index& north ( Index& ) const; + inline GCell* getUnder ( DbU::Unit x, DbU::Unit y ) const; + inline GCell* getUnder ( Point ) const; + void setCell ( Cell*, DbU::Unit side ); + void updateLookup ( GCell* ); + // Inspector support. + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + private: + Matrix ( const Matrix& ); + Matrix& operator= ( const Matrix& ); + private: + Box _area; + DbU::Unit _side; + vector _gcells; + int _imax; + int _jmax; + }; + + + +// Matrix inline functions. + inline Box Matrix::getArea () const { return _area; } + inline DbU::Unit Matrix::getSide () const { return _side; } + inline int Matrix::getIMax () const { return _imax; } + inline int Matrix::getJMax () const { return _jmax; } + + inline int Matrix::index2i ( int index ) const + { return ((index >= 0) and (index < _imax*_jmax+1)) ? index % _imax : -1; } + + inline int Matrix::index2i ( const Index& index ) const + { return (index.valid()) ? index.index() % _imax : -1; } + + inline int Matrix::index2j ( int index ) const + { return ((index >= 0) and (index < _imax*_jmax+1)) ? index / _imax : -1; } + + inline int Matrix::index2j ( const Index& index ) const + { return (index.valid()) ? index.index() / _imax : -1; } + + inline int Matrix::ij2index ( int i, int j ) const + { + if ((i < 0) or (i >= _imax)) return -1; + if ((j < 0) or (j >= _jmax)) return -1; + return j*_jmax + i; + } + + inline int Matrix::xy2index ( DbU::Unit x, DbU::Unit y ) const + { return ij2index( (x - _area.getXMin()) / _side, (y - _area.getYMin()) / _side ); } + + inline int Matrix::xy2index ( Point p ) const + { return xy2index( p.getX(), p.getY() ); } + + inline Matrix::Index& Matrix::west ( Matrix::Index& index ) const + { + if (index.valid()) { + if (index.index() % _imax) index.index() -= 1; + else index.index() = -1; + } + return index; + } + + inline Matrix::Index& Matrix::east ( Matrix::Index& index ) const + { + if (index.valid()) { + if ((index.index() % _imax) < _imax-1) index.index() += 1; + else index.index() = -1; + } + return index; + } + + inline Matrix::Index& Matrix::south ( Matrix::Index& index ) const + { + if (index.valid()) { + if (index.index() >= _imax) index.index() -= _imax; + else index.index() = -1; + } + return index; + } + + inline Matrix::Index& Matrix::north ( Matrix::Index& index ) const + { + if (index.valid()) { + if (index.index() >= _imax*(_jmax-1)) index.index() += _imax; + else index.index() = -1; + } + return index; + } + + inline GCell* Matrix::getUnder ( DbU::Unit x, DbU::Unit y ) const + { int index = xy2index(x,y); return (index < 0) ? NULL : _gcells[index]; } + + inline GCell* Matrix::getUnder ( Point p ) const + { return getUnder( p.getX(), p.getY() ); } + + +// Matrix::Index inline functions. + + inline Matrix::Index::Index ( Matrix* m, int index ) : _matrix(m), _index(index) { } + inline Matrix::Index::Index ( Matrix* m, int i, int j ) : _matrix(m), _index(m->ij2index(i,j)) { } + inline Matrix::Index::Index ( Matrix* m, DbU::Unit x, DbU::Unit y ) : _matrix(m), _index(m->xy2index(x,y)) { } + inline Matrix::Index::Index ( Matrix* m, Point position ) : _matrix(m), _index(m->xy2index(position)) { } + + inline Matrix* Matrix::Index::matrix () const { return _matrix; } + inline const int& Matrix::Index::index () const { return _index; } + inline int& Matrix::Index::index () { return _index; } + inline bool Matrix::Index::valid () const { return _index >= 0; } + inline int Matrix::Index::i () const { return _matrix->index2i(*this); } + inline int Matrix::Index::j () const { return _matrix->index2j(*this); } + inline Matrix::Index& Matrix::Index::west () { return _matrix->west (*this); } + inline Matrix::Index& Matrix::Index::east () { return _matrix->east (*this); } + inline Matrix::Index& Matrix::Index::south () { return _matrix->south (*this); } + inline Matrix::Index& Matrix::Index::north () { return _matrix->north (*this); } + + +} // Anabatic namespace. + + +inline std::ostream& operator<< ( std::ostream& o, const Anabatic::Matrix::Index& index ) +{ + o << "(" << index.index() << "|" << index.i() << "," << index.j() << ")"; + return o; +} + + +INSPECTOR_P_SUPPORT(Anabatic::Matrix); + +#endif // ANABATIC_MATRIX_H diff --git a/anabatic/src/anabatic/PyAnabaticEngine.h b/anabatic/src/anabatic/PyAnabaticEngine.h new file mode 100644 index 00000000..4948c01b --- /dev/null +++ b/anabatic/src/anabatic/PyAnabaticEngine.h @@ -0,0 +1,55 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./anabatic/PyAnabaticEngine.h" | +// +-----------------------------------------------------------------+ + + +#ifndef PY_ANABATIC_ENGINE_H +#define PY_ANABATIC_ENGINE_H + +#include "hurricane/isobar/PyHurricane.h" +#include "crlcore/PyToolEngine.h" +#include "anabatic/AnabaticEngine.h" + + +namespace Anabatic { + + extern "C" { + +// ------------------------------------------------------------------- +// Python Object : "PyAnabaticEngine". + + typedef struct { + CRL::PyToolEngine _baseObject; + } PyAnabaticEngine; + + +// ------------------------------------------------------------------- +// Functions & Types exported to "PyAnabatic.ccp". + + extern PyTypeObject PyTypeAnabaticEngine; + extern PyMethodDef PyAnabaticEngine_Methods[]; + extern PyObject* PyAnabaticEngine_Link ( Anabatic::AnabaticEngine* ); + extern void PyAnabaticEngine_LinkPyType (); + + +#define IsPyAnabaticEngine(v) ( (v)->ob_type == &PyTypeAnabaticEngine ) +#define PYANABATICENGINE(v) ( (PyAnabaticEngine*)(v) ) +#define PYANABATICENGINE_O(v) ( PYANABATICENGINE(v)->_baseObject._object ) + + + } // extern "C". + +} // Anabatic namespace. + +#endif // PY_ANABATIC_ENGINE_H diff --git a/anabatic/src/anabatic/PyGraphicAnabaticEngine.h b/anabatic/src/anabatic/PyGraphicAnabaticEngine.h new file mode 100644 index 00000000..dd91b697 --- /dev/null +++ b/anabatic/src/anabatic/PyGraphicAnabaticEngine.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./anabatic/PyGraphicAnabaticEngine.h" | +// +-----------------------------------------------------------------+ + + +#ifndef ANABATIC_PY_GRAPHIC_ANABATIC_ENGINE_H +#define ANABATIC_PY_GRAPHIC_ANABATIC_ENGINE_H + +#include "crlcore/PyGraphicToolEngine.h" +#include "anabatic/GraphicAnabaticEngine.h" + + +namespace Anabatic { + + extern "C" { + +// ------------------------------------------------------------------- +// Python Object : "PyGraphicAnabaticEngine". + + typedef struct { + CRL::PyGraphicTool _baseObject; + } PyGraphicAnabaticEngine; + + +// ------------------------------------------------------------------- +// Functions & Types exported to "PyAnabatic.ccp". + + extern PyTypeObject PyTypeGraphicAnabaticEngine; + extern PyMethodDef PyGraphicAnabaticEngine_Methods[]; + extern void PyGraphicAnabaticEngine_LinkPyType (); + + +#define IsPyGraphicAnabaticEngine(v) ( (v)->ob_type == &PyTypeGraphicAnabaticEngine ) +#define PY_GRAPHIC_ANABATIC_ENGINE(v) ( (PyGraphicAnabaticEngine*)(v) ) +#define PY_GRAPHIC_ANABATIC_ENGINE_O(v) ( PY_GRAPHIC_ANABATIC_ENGINE(v)->_baseObject._object ) + + + } // extern "C". + +} // Anabatic namespace. + +#endif // ANABATIC_PY_GRAPHIC_ANABATIC_ENGINE_H diff --git a/bootstrap/build.conf b/bootstrap/build.conf index b29b7b1e..8c4d6428 100644 --- a/bootstrap/build.conf +++ b/bootstrap/build.conf @@ -19,6 +19,7 @@ projects = [ #, "nimbus" #, "metis" #, "mauka" + , "anabatic" , "knik" , "katabatic" , "kite" diff --git a/unicorn/src/cgt.py b/unicorn/src/cgt.py index c8ac6c22..ba945c1a 100755 --- a/unicorn/src/cgt.py +++ b/unicorn/src/cgt.py @@ -9,7 +9,7 @@ try: import Hurricane import Viewer import CRL - #import Anabatic + import Anabatic import Etesian import Katabatic import Kite