parent
2332fe6ca6
commit
13357159f0
|
@ -0,0 +1,62 @@
|
||||||
|
PROJECT(METIS)
|
||||||
|
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.0)
|
||||||
|
|
||||||
|
SET(CMAKE_C_FLAGS_DEBUG "-g -Wall" CACHE STRING "Debug options." FORCE)
|
||||||
|
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall" CACHE STRING "Debug options." FORCE)
|
||||||
|
#SET(CMAKE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE)
|
||||||
|
#SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE)
|
||||||
|
#SET(CMAKE_MODULE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE)
|
||||||
|
#SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE)
|
||||||
|
|
||||||
|
IF(COMMAND CMAKE_POLICY)
|
||||||
|
CMAKE_POLICY(SET CMP0003 NEW)
|
||||||
|
ENDIF(COMMAND CMAKE_POLICY)
|
||||||
|
|
||||||
|
# This macro has to be included in all the tools CMakeLists.txt as it's
|
||||||
|
# the sole means of localizing other tools/projects.
|
||||||
|
MACRO(SETUP_PROJECT_PATHS project)
|
||||||
|
IF( NOT("$ENV{${project}_TOP}" STREQUAL "") )
|
||||||
|
MESSAGE("-- ${project}_TOP is set to $ENV{${project}_TOP}")
|
||||||
|
SET(PROJECT_MODULE_PATH "${DESTDIR}$ENV{${project}_TOP}/share/cmake/Modules/")
|
||||||
|
LIST(INSERT CMAKE_MODULE_PATH 0 "${PROJECT_MODULE_PATH}")
|
||||||
|
ENDIF( NOT("$ENV{${project}_TOP}" STREQUAL "") )
|
||||||
|
|
||||||
|
IF( NOT("$ENV{${project}_USER_TOP}" STREQUAL "") )
|
||||||
|
MESSAGE("-- ${project}_USER_TOP is set to $ENV{${project}_USER_TOP}")
|
||||||
|
SET(PROJECT_MODULE_PATH "${DESTDIR}$ENV{${project}_USER_TOP}/share/cmake/Modules/")
|
||||||
|
LIST(INSERT CMAKE_MODULE_PATH 0 "${PROJECT_MODULE_PATH}")
|
||||||
|
ENDIF( NOT("$ENV{${project}_USER_TOP}" STREQUAL "") )
|
||||||
|
|
||||||
|
LIST(REMOVE_DUPLICATES CMAKE_MODULE_PATH)
|
||||||
|
ENDMACRO(SETUP_PROJECT_PATHS project)
|
||||||
|
|
||||||
|
SETUP_PROJECT_PATHS(VLSISAPD)
|
||||||
|
SETUP_PROJECT_PATHS(CORIOLIS)
|
||||||
|
|
||||||
|
MESSAGE("-- Components of CMAKE_MODULE_PATH:")
|
||||||
|
FOREACH(PATH IN LISTS CMAKE_MODULE_PATH)
|
||||||
|
MESSAGE("-- ${PATH}")
|
||||||
|
ENDFOREACH(PATH)
|
||||||
|
|
||||||
|
SET(QT_USE_QTXML "true")
|
||||||
|
|
||||||
|
FIND_PACKAGE(Qt4 REQUIRED) # find and setup Qt4 for this project
|
||||||
|
FIND_PACKAGE(HURRICANE REQUIRED)
|
||||||
|
FIND_PACKAGE(CORIOLIS REQUIRED)
|
||||||
|
FIND_PACKAGE(NIMBUS REQUIRED)
|
||||||
|
|
||||||
|
SET(HMETIS_INCLUDE_PATH METIS_INCLUDE_PATH)
|
||||||
|
FIND_LIBRARY(HMETIS_LIBRARY_PATH
|
||||||
|
NAMES hmetis
|
||||||
|
PATHS ${CORIOLIS_DIR_SEARCH} /opt/coriolis
|
||||||
|
PATH_SUFFIXES lib${LIB_SUFFIX}
|
||||||
|
# Help the user find it if we cannot.
|
||||||
|
DOC "The hmetis static library"
|
||||||
|
)
|
||||||
|
SET_LIBRARIES_PATH(HMETIS HMETIS)
|
||||||
|
|
||||||
|
SET_LIB_LINK_MODE()
|
||||||
|
|
||||||
|
ADD_SUBDIRECTORY(src)
|
||||||
|
ADD_SUBDIRECTORY(cmake_modules)
|
|
@ -0,0 +1 @@
|
||||||
|
install ( FILES FindMETIS.cmake DESTINATION share/cmake/Modules )
|
|
@ -0,0 +1,48 @@
|
||||||
|
# - Find the Metis includes and libraries.
|
||||||
|
# The following variables are set if Coriolis is found. If METIS is not
|
||||||
|
# found, METIS_FOUND is set to false.
|
||||||
|
# METIS_FOUND - True when the Coriolis include directory is found.
|
||||||
|
# METIS_INCLUDE_DIR - the path to where the Coriolis include files are.
|
||||||
|
# METIS_LIBRARIES - The path to where the Coriolis library files are.
|
||||||
|
|
||||||
|
|
||||||
|
SET(METIS_INCLUDE_PATH_DESCRIPTION "directory containing the Metis/hmetis include files. E.g /usr/local/include/coriolis or /asim/coriolis/include/coriolis")
|
||||||
|
|
||||||
|
SET(METIS_DIR_MESSAGE "Set the METIS_INCLUDE_DIR cmake cache entry to the ${METIS_INCLUDE_PATH_DESCRIPTION}")
|
||||||
|
|
||||||
|
# don't even bother under WIN32
|
||||||
|
IF(UNIX)
|
||||||
|
#
|
||||||
|
# Look for an installation.
|
||||||
|
#
|
||||||
|
FIND_PATH(METIS_INCLUDE_PATH NAMES metis/MetisEngine.h PATHS
|
||||||
|
# Look in other places.
|
||||||
|
${CORIOLIS_DIR_SEARCH}
|
||||||
|
PATH_SUFFIXES include/coriolis2
|
||||||
|
# Help the user find it if we cannot.
|
||||||
|
DOC "The ${METIS_INCLUDE_PATH_DESCRIPTION}"
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(METIS_LIBRARY_PATH
|
||||||
|
NAMES metis
|
||||||
|
PATHS ${CORIOLIS_DIR_SEARCH}
|
||||||
|
PATH_SUFFIXES lib${LIB_SUFFIX}
|
||||||
|
# Help the user find it if we cannot.
|
||||||
|
DOC "The ${METIS_INCLUDE_PATH_DESCRIPTION}"
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(HMETIS_INCLUDE_PATH METIS_INCLUDE_PATH)
|
||||||
|
|
||||||
|
FIND_LIBRARY(HMETIS_LIBRARY_PATH
|
||||||
|
NAMES hmetis
|
||||||
|
PATHS ${CORIOLIS_DIR_SEARCH} /opt/coriolis
|
||||||
|
PATH_SUFFIXES lib${LIB_SUFFIX}
|
||||||
|
# Help the user find it if we cannot.
|
||||||
|
DOC "The ${METIS_INCLUDE_PATH_DESCRIPTION}"
|
||||||
|
)
|
||||||
|
|
||||||
|
SET_LIBRARIES_PATH(METIS METIS)
|
||||||
|
SET_LIBRARIES_PATH(HMETIS HMETIS)
|
||||||
|
HURRICANE_CHECK_LIBRARIES(METIS)
|
||||||
|
|
||||||
|
ENDIF(UNIX)
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
if ( HMETIS_FOUND )
|
||||||
|
add_definitions ( -DHAVE_HMETIS_LIB )
|
||||||
|
endif ( HMETIS_FOUND )
|
||||||
|
|
||||||
|
include ( ${QT_USE_FILE} )
|
||||||
|
|
||||||
|
include_directories ( ${METIS_SOURCE_DIR}/src
|
||||||
|
${HURRICANE_INCLUDE_DIR}
|
||||||
|
${CORIOLIS_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
set ( includes metis/hmetis.h
|
||||||
|
metis/MetisGraph.h
|
||||||
|
metis/Configuration.h
|
||||||
|
metis/MetisEngine.h
|
||||||
|
)
|
||||||
|
# set ( mocIncludes metis/ConfigurationWidget.h
|
||||||
|
# metis/GraphicMaukaEngine.h )
|
||||||
|
set ( cpps MetisGraph.cpp
|
||||||
|
Configuration.cpp
|
||||||
|
MetisEngine.cpp
|
||||||
|
)
|
||||||
|
# qt4_wrap_cpp ( mocCpps ${mocIncludes} )
|
||||||
|
|
||||||
|
|
||||||
|
add_library ( metis ${cpps} ${mocCpps} )
|
||||||
|
target_link_libraries ( metis ${HMETIS_LIBRARIES}
|
||||||
|
${NIMBUS_LIBRARIES}
|
||||||
|
${CORIOLIS_LIBRARIES}
|
||||||
|
${HURRICANE_LIBRARIES}
|
||||||
|
${HURRICANE_GRAPHICAL_LIBRARIES}
|
||||||
|
${QT_LIBRARIES}
|
||||||
|
${LEFDEF_LIBRARIES}
|
||||||
|
${OA_LIBRARIES}
|
||||||
|
)
|
||||||
|
install ( TARGETS metis DESTINATION lib${LIB_SUFFIX} )
|
||||||
|
install ( FILES ${includes} ${mocIncludes} DESTINATION include/coriolis2/metis )
|
|
@ -0,0 +1,161 @@
|
||||||
|
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved
|
||||||
|
//
|
||||||
|
// ===================================================================
|
||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// x-----------------------------------------------------------------x
|
||||||
|
// | |
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | M e t i s - h M e t i s W r a p p e r |
|
||||||
|
// | |
|
||||||
|
// | Author : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./Configuration.cpp" |
|
||||||
|
// | *************************************************************** |
|
||||||
|
// | U p d a t e s |
|
||||||
|
// | |
|
||||||
|
// x-----------------------------------------------------------------x
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
#include "crlcore/Utilities.h"
|
||||||
|
#include "metis/Configuration.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Metis {
|
||||||
|
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::setprecision;
|
||||||
|
using std::ostringstream;
|
||||||
|
using std::string;
|
||||||
|
using Hurricane::tab;
|
||||||
|
using Hurricane::inltrace;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Metis::Configuration".
|
||||||
|
|
||||||
|
|
||||||
|
Configuration* Configuration::_default = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
Configuration* Configuration::getDefault ()
|
||||||
|
{
|
||||||
|
if ( _default == NULL ) {
|
||||||
|
_default = new Configuration ();
|
||||||
|
}
|
||||||
|
return _default;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Configuration::Configuration ()
|
||||||
|
: _refreshCb ()
|
||||||
|
, _partOrKWayHMetis (true)
|
||||||
|
, _numberOfInstancesStopCriterion(45)
|
||||||
|
, _globalConnectionsWeightRatio (1)
|
||||||
|
, _ubFactor (0)
|
||||||
|
, _hmetisOptions ()
|
||||||
|
{
|
||||||
|
_hmetisOptions[CustomOptions ] = 1;
|
||||||
|
_hmetisOptions[HMetisNRuns ] = 10;
|
||||||
|
_hmetisOptions[HMetisCType ] = CTypeHFC;
|
||||||
|
_hmetisOptions[HMetisRType ] = RTypeFM;
|
||||||
|
_hmetisOptions[HMetisVCycle ] = VCycleDisable;
|
||||||
|
_hmetisOptions[HMetisReconst ] = ReconstRemoveCutHE;
|
||||||
|
_hmetisOptions[HMetisPreAssign ] = 1;
|
||||||
|
_hmetisOptions[HMetisRandom ] = -1;
|
||||||
|
_hmetisOptions[HMetisDebugLevel] = DebugDisable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Configuration::Configuration ( const Configuration& other )
|
||||||
|
: _refreshCb (other._refreshCb)
|
||||||
|
, _partOrKWayHMetis (other._partOrKWayHMetis)
|
||||||
|
, _numberOfInstancesStopCriterion(other._numberOfInstancesStopCriterion)
|
||||||
|
, _globalConnectionsWeightRatio (other._globalConnectionsWeightRatio)
|
||||||
|
, _ubFactor (other._ubFactor)
|
||||||
|
, _hmetisOptions ()
|
||||||
|
{
|
||||||
|
for ( unsigned int option=0 ; option<HMetisOptionsSize ; ++option )
|
||||||
|
_hmetisOptions[option] = other._hmetisOptions[option];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Configuration::~Configuration ()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
Configuration* Configuration::clone () const
|
||||||
|
{ return new Configuration(*this); }
|
||||||
|
|
||||||
|
|
||||||
|
void Configuration::print ( Cell* cell ) const
|
||||||
|
{
|
||||||
|
cout << " o Configuration of ToolEngine<Metis> for Cell <" << cell->getName() << ">" << endl;
|
||||||
|
cout << Dots::asBool(" - Part / KWay hMETIS" ,_partOrKWayHMetis) << endl;
|
||||||
|
cout << Dots::asUInt(" - Instances stop criterion" ,_numberOfInstancesStopCriterion) << endl;
|
||||||
|
cout << Dots::asInt (" - Global connections weight ratio" ,_globalConnectionsWeightRatio) << endl;
|
||||||
|
cout << Dots::asInt (" - UB factor" ,_ubFactor) << endl;
|
||||||
|
cout << Dots::asInt (" - hMETIS Custom options" ,_hmetisOptions[CustomOptions]) << endl;
|
||||||
|
cout << Dots::asInt (" - hMETIS NRuns" ,_hmetisOptions[HMetisNRuns]) << endl;
|
||||||
|
cout << Dots::asInt (" - hMETIS CType" ,_hmetisOptions[HMetisCType]) << endl;
|
||||||
|
cout << Dots::asInt (" - hMETIS RType" ,_hmetisOptions[HMetisRType]) << endl;
|
||||||
|
cout << Dots::asInt (" - hMETIS V-Cycle" ,_hmetisOptions[HMetisVCycle]) << endl;
|
||||||
|
cout << Dots::asInt (" - hMETIS Reconstruct Edges" ,_hmetisOptions[HMetisReconst]) << endl;
|
||||||
|
cout << Dots::asInt (" - hMETIS Pre-Assignment" ,_hmetisOptions[HMetisPreAssign]) << endl;
|
||||||
|
cout << Dots::asInt (" - hMETIS Random" ,_hmetisOptions[HMetisRandom]) << endl;
|
||||||
|
cout << Dots::asInt (" - hMETIS Debug Level" ,_hmetisOptions[HMetisDebugLevel]) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string Configuration::_getTypeName () const
|
||||||
|
{
|
||||||
|
return "Metis::Configuration";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string Configuration::_getString () const
|
||||||
|
{
|
||||||
|
ostringstream os;
|
||||||
|
|
||||||
|
os << "<" << _getTypeName() << ">";
|
||||||
|
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Record* Configuration::_getRecord () const
|
||||||
|
{
|
||||||
|
Record* record = new Record ( _getString() );
|
||||||
|
record->add ( getSlot("_partOrKWayHMetis" , _partOrKWayHMetis ) );
|
||||||
|
record->add ( getSlot("_numberOfInstancesStopCriterion" , _numberOfInstancesStopCriterion ) );
|
||||||
|
record->add ( getSlot("_globalConnectionsWeightRatio" , _globalConnectionsWeightRatio ) );
|
||||||
|
record->add ( getSlot("_ubFactor" , _ubFactor ) );
|
||||||
|
record->add ( getSlot("_hmetisOptions[CustomOptions]" , _hmetisOptions[CustomOptions] ) );
|
||||||
|
record->add ( getSlot("_hmetisOptions[HMetisNRuns]" , _hmetisOptions[HMetisNRuns ] ) );
|
||||||
|
record->add ( getSlot("_hmetisOptions[HMetisCType]" , _hmetisOptions[HMetisCType ] ) );
|
||||||
|
record->add ( getSlot("_hmetisOptions[HMetisRType]" , _hmetisOptions[HMetisRType ] ) );
|
||||||
|
record->add ( getSlot("_hmetisOptions[HMetisVCycle]" , _hmetisOptions[HMetisVCycle ] ) );
|
||||||
|
record->add ( getSlot("_hmetisOptions[HMetisReconst]" , _hmetisOptions[HMetisReconst] ) );
|
||||||
|
record->add ( getSlot("_hmetisOptions[HMetisPreAssign]" , _hmetisOptions[HMetisPreAssign] ) );
|
||||||
|
record->add ( getSlot("_hmetisOptions[HMetisRandom]" , _hmetisOptions[HMetisRandom ] ) );
|
||||||
|
record->add ( getSlot("_hmetisOptions[HMetisDebugLevel]", _hmetisOptions[HMetisDebugLevel]) );
|
||||||
|
|
||||||
|
return ( record );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // End of Metis namespace.
|
|
@ -0,0 +1,318 @@
|
||||||
|
|
||||||
|
// This file is part of the Coriolis Project.
|
||||||
|
// Copyright (C) Laboratoire LIP6 - Departement ASIM
|
||||||
|
// Universite Pierre et Marie Curie
|
||||||
|
//
|
||||||
|
// Main contributors :
|
||||||
|
// Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
||||||
|
// Hugo Clément <Hugo.Clement@lip6.fr>
|
||||||
|
// Jean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
|
||||||
|
// Christian Masson <Christian.Masson@lip6.fr>
|
||||||
|
//
|
||||||
|
// The Coriolis Project is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The Coriolis Project is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Coriolis Project; if not, write to the Free Software
|
||||||
|
// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// License-Tag
|
||||||
|
//
|
||||||
|
// Date : 29/01/2004
|
||||||
|
// Author : Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
||||||
|
//
|
||||||
|
// Authors-Tag
|
||||||
|
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include "hurricane/Warning.h"
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
#include "hurricane/Instance.h"
|
||||||
|
#include "hurricane/Plug.h"
|
||||||
|
#include "hurricane/Timer.h"
|
||||||
|
#include "crlcore/ToolBox.h"
|
||||||
|
#include "crlcore/AllianceFramework.h"
|
||||||
|
using namespace CRL;
|
||||||
|
|
||||||
|
#include "nimbus/NimbusEngine.h"
|
||||||
|
using namespace Nimbus;
|
||||||
|
|
||||||
|
#ifdef HAVE_HMETIS_LIB
|
||||||
|
#include "metis/MetisGraph.h"
|
||||||
|
#endif
|
||||||
|
#include "metis/MetisEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Metis {
|
||||||
|
|
||||||
|
|
||||||
|
const Name MetisEngine::_toolName = "Metis";
|
||||||
|
|
||||||
|
|
||||||
|
MetisEngine::MetisEngine ( Cell* cell )
|
||||||
|
: Inherit (cell)
|
||||||
|
, _configuration(Configuration::getDefault()->clone())
|
||||||
|
, _step (0)
|
||||||
|
, _actualGraphs ()
|
||||||
|
, _newGraphs ()
|
||||||
|
, _globalEdgeCut(0)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_HMETIS_LIB
|
||||||
|
|
||||||
|
NimbusEngine* nimbus = NimbusEngine::get ( getCell() );
|
||||||
|
if ( nimbus == NULL )
|
||||||
|
throw Error ("Nimbus must be created before Metis, on cell <%s>"
|
||||||
|
,getString(getCell()->getName()).c_str());
|
||||||
|
|
||||||
|
_actualGraphs = new MetisGraphs();
|
||||||
|
_newGraphs = new MetisGraphs();
|
||||||
|
_actualGraphs->push_back ( new MetisGraph(this,nimbus->getGrid()->getRoot()) );
|
||||||
|
|
||||||
|
// What the fuck does this loop do?
|
||||||
|
// forEach ( Net*, inet, getCell()->getNets() ) {
|
||||||
|
// if ( inet->isGlobal() ) continue;
|
||||||
|
// if ( inet->isSupply() ) continue;
|
||||||
|
// }
|
||||||
|
#endif // HAVE_HMETIS_LIB
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MetisEngine::~MetisEngine ()
|
||||||
|
{ delete _configuration; }
|
||||||
|
|
||||||
|
|
||||||
|
MetisEngine* MetisEngine::create ( Cell* cell )
|
||||||
|
{
|
||||||
|
MetisEngine* metis = new MetisEngine(cell);
|
||||||
|
|
||||||
|
metis->_postCreate();
|
||||||
|
return metis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MetisEngine::_preDestroy ()
|
||||||
|
{
|
||||||
|
#ifdef HAVE_HMETIS_LIB
|
||||||
|
for (MetisGraphs::iterator mgit = _actualGraphs->begin(); mgit != _actualGraphs->end(); ++mgit)
|
||||||
|
delete *mgit;
|
||||||
|
for (MetisGraphs::iterator mgit = _newGraphs->begin(); mgit != _newGraphs->end(); ++mgit)
|
||||||
|
delete *mgit;
|
||||||
|
|
||||||
|
delete _actualGraphs;
|
||||||
|
delete _newGraphs;
|
||||||
|
#endif // HAVE_HMETIS_LIB
|
||||||
|
Inherit::_preDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MetisEngine::isHMetisCapable ()
|
||||||
|
{
|
||||||
|
#ifdef HAVE_HMETIS_LIB
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif // HAVE_HMETIS_LIB
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Record* MetisEngine::_getRecord () const
|
||||||
|
{
|
||||||
|
Record* record = Inherit::_getRecord();
|
||||||
|
if (record) {
|
||||||
|
record->add ( getSlot("step", _step) );
|
||||||
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MetisEngine::run ()
|
||||||
|
{
|
||||||
|
#ifdef HAVE_HMETIS_LIB
|
||||||
|
cmess2 << " o hMetis quadri-partition step." << endl;
|
||||||
|
|
||||||
|
Timer timer;
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
NimbusEngine* nimbus = NimbusEngine::get ( getCell() );
|
||||||
|
|
||||||
|
forEach ( GCell*, igcell, nimbus->getPlacementLeaves() ) {
|
||||||
|
if ( not igcell->hasSubGCells() )
|
||||||
|
throw Warning("You must first progress in Nimbus before calling Metis");
|
||||||
|
|
||||||
|
if ( igcell->getSubGCells().getSize() < 2 )
|
||||||
|
throw Error("Metis needs at least 2 Nimbus subboxes");
|
||||||
|
}
|
||||||
|
|
||||||
|
_globalEdgeCut = 0;
|
||||||
|
|
||||||
|
linefill output (" ",cmess2);
|
||||||
|
|
||||||
|
for ( MetisGraphs::iterator mgit = _actualGraphs->begin(); mgit != _actualGraphs->end(); ++mgit ) {
|
||||||
|
MetisGraph* graph = *mgit;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_globalEdgeCut += graph->part ( output );
|
||||||
|
}
|
||||||
|
catch ( MetisGraph::TooLowNVTXSException& e ) {
|
||||||
|
cerr << Warning("Impossible to part graph, only %d nodes",e._nvtxs);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( size_t id=0; id < graph->_partResultVector.size(); ++id ) {
|
||||||
|
_newGraphs->push_back
|
||||||
|
( new MetisGraph(this
|
||||||
|
,graph
|
||||||
|
,graph->_partResultVector[id]->first
|
||||||
|
,graph->_partResultVector[id]->second
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output << endl;
|
||||||
|
|
||||||
|
for ( MetisGraphs::iterator mgit=_actualGraphs->begin(); mgit != _actualGraphs->end(); ++mgit )
|
||||||
|
delete *mgit;
|
||||||
|
delete _actualGraphs;
|
||||||
|
|
||||||
|
_actualGraphs = _newGraphs;
|
||||||
|
_newGraphs = new MetisGraphs ();
|
||||||
|
|
||||||
|
save ( ++_step );
|
||||||
|
|
||||||
|
timer.stop();
|
||||||
|
cmess2 << " - Refine placement done in " << getString(timer.getUserTime()) << "s." << endl;
|
||||||
|
|
||||||
|
if ( getRefreshCb() != NULL ) getRefreshCb() ();
|
||||||
|
#else
|
||||||
|
throw Warning ( "hmetis library is needed to use Metis ToolEngine" );
|
||||||
|
#endif // HAVE_HMETIS_LIB
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MetisEngine::save ( unsigned step )
|
||||||
|
{
|
||||||
|
#ifdef HAVE_HMETIS_LIB
|
||||||
|
//for ( MetisGraphs::iterator mgit=_actualGraphs->begin(); mgit != _actualGraphs->end(); ++mgit)
|
||||||
|
// (*mgit)->save ( step );
|
||||||
|
grabPlacementModificationFlag ();
|
||||||
|
#else
|
||||||
|
throw Warning ( "hmetis library is needed to use Metis ToolEngine" );
|
||||||
|
#endif /* HAVE_HMETIS_LIB */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int MetisEngine::getGlobalEdgeCut () const
|
||||||
|
{ return _globalEdgeCut; }
|
||||||
|
|
||||||
|
|
||||||
|
const Name& MetisEngine::staticGetName ()
|
||||||
|
{ return _toolName; }
|
||||||
|
|
||||||
|
|
||||||
|
const Name& MetisEngine::getName () const
|
||||||
|
{ return _toolName; }
|
||||||
|
|
||||||
|
|
||||||
|
MetisEngine* MetisEngine::get ( Cell* cell )
|
||||||
|
{ return dynamic_cast<MetisEngine*> ( ToolEngine::get(cell,_toolName) ); }
|
||||||
|
|
||||||
|
|
||||||
|
bool MetisEngine::_reInit()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
#ifdef HAVE_HMETIS_LIB
|
||||||
|
for (MetisGraphs::iterator mgit=_actualGraphs->begin(); mgit != _actualGraphs->end(); ++mgit)
|
||||||
|
delete *mgit;
|
||||||
|
for (MetisGraphs::iterator mgit=_newGraphs->begin(); mgit != _newGraphs->end(); ++mgit)
|
||||||
|
delete *mgit;
|
||||||
|
|
||||||
|
delete _actualGraphs;
|
||||||
|
delete _newGraphs;
|
||||||
|
|
||||||
|
_actualGraphs = new MetisGraphs();
|
||||||
|
_newGraphs = new MetisGraphs();
|
||||||
|
|
||||||
|
NimbusEngine* nimbus = NimbusEngine::get ( getCell() );
|
||||||
|
bool partToBeDone = false;
|
||||||
|
|
||||||
|
forEach ( GCell*, igcell, nimbus->getPlacementLeaves() ) {
|
||||||
|
Instances instances = getCell()->getInstancesUnder(**igcell);
|
||||||
|
|
||||||
|
if ( instances.getSize() >= getNumberOfInstancesStopCriterion() ) {
|
||||||
|
if ( not partToBeDone ) {
|
||||||
|
partToBeDone = true;
|
||||||
|
++_step;
|
||||||
|
}
|
||||||
|
_actualGraphs->push_back ( new MetisGraph(this,instances,igcell) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( not partToBeDone )
|
||||||
|
throw Warning("Not enough instances to part, minimum is %d",getNumberOfInstancesStopCriterion());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
throw Warning ( "hmetis library is needed to use Metis ToolEngine" );
|
||||||
|
#endif // HAVE_HMETIS_LIB
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int MetisEngine::computeQuadriPartitions ( Cell* cell )
|
||||||
|
{
|
||||||
|
size_t gates = getInstancesCount ( cell );
|
||||||
|
|
||||||
|
double partitions = log((double)gates / (double)Configuration::getDefault()
|
||||||
|
->getNumberOfInstancesStopCriterion() ) / log(4.0) + 1.0;
|
||||||
|
|
||||||
|
return (unsigned int)(partitions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MetisEngine::doQuadriPart ( Cell* cell )
|
||||||
|
{
|
||||||
|
if ( not isHMetisCapable() )
|
||||||
|
throw Error ("Metis::doQuadriPart(): HMetis wasn't found at compile time <%s>"
|
||||||
|
,getString(cell->getName()).c_str());
|
||||||
|
|
||||||
|
// MetisEngine* metis = MetisEngine::get ( cell );
|
||||||
|
// if ( metis != NULL )
|
||||||
|
// throw Error ("Metis::doQuadriPart(): Metis already exists on <%s>"
|
||||||
|
// ,getString(cell->getName()).c_str());
|
||||||
|
|
||||||
|
// NimbusEngine* nimbus = NimbusEngine::get ( cell );
|
||||||
|
// if ( nimbus != NULL )
|
||||||
|
// throw Error ("Metis::doQuadriPart(): Nimbus already exists on <%s>"
|
||||||
|
// ,getString(cell->getName()).c_str());
|
||||||
|
|
||||||
|
// nimbus = NimbusEngine::create ( cell, AllianceFramework::get()->getLibrary(1) );
|
||||||
|
// metis = MetisEngine ::create ( cell );
|
||||||
|
|
||||||
|
NimbusEngine* nimbus = NimbusEngine::get ( cell );
|
||||||
|
if ( nimbus == NULL )
|
||||||
|
nimbus = NimbusEngine::create ( cell );
|
||||||
|
|
||||||
|
MetisEngine* metis = MetisEngine::get ( cell );
|
||||||
|
if ( metis == NULL )
|
||||||
|
metis = MetisEngine ::create ( cell );
|
||||||
|
|
||||||
|
size_t partitions = computeQuadriPartitions ( cell );
|
||||||
|
for ( size_t part=0 ; part<partitions ; ++part ) {
|
||||||
|
nimbus->progress ();
|
||||||
|
metis-> run ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // End of Metis namespace.
|
|
@ -0,0 +1,621 @@
|
||||||
|
|
||||||
|
// This file is part of the Coriolis Project.
|
||||||
|
// Copyright (C) Laboratoire LIP6 - Departement ASIM
|
||||||
|
// Universite Pierre et Marie Curie
|
||||||
|
//
|
||||||
|
// Main contributors :
|
||||||
|
// Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
||||||
|
// Hugo Clément <Hugo.Clement@lip6.fr>
|
||||||
|
// Jean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
|
||||||
|
// Christian Masson <Christian.Masson@lip6.fr>
|
||||||
|
//
|
||||||
|
// The Coriolis Project is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The Coriolis Project is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Coriolis Project; if not, write to the Free Software
|
||||||
|
// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// License-Tag
|
||||||
|
//
|
||||||
|
// Date : 29/01/2004
|
||||||
|
// Author : Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
||||||
|
//
|
||||||
|
// Authors-Tag
|
||||||
|
|
||||||
|
#ifdef HAVE_HMETIS_LIB
|
||||||
|
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
#include "hurricane/Instance.h"
|
||||||
|
#include "hurricane/Plug.h"
|
||||||
|
#include "hurricane/Pin.h"
|
||||||
|
#include "hurricane/UpdateSession.h"
|
||||||
|
using namespace Hurricane;
|
||||||
|
|
||||||
|
#include "crlcore/Utilities.h"
|
||||||
|
#include "crlcore/ToolBox.h"
|
||||||
|
using namespace CRL;
|
||||||
|
|
||||||
|
#include "nimbus/Splitter.h"
|
||||||
|
#include "nimbus/GCell.h"
|
||||||
|
#include "nimbus/SplitterContact.h"
|
||||||
|
#include "nimbus/StepProperty.h"
|
||||||
|
#include "nimbus/NimbusEngine.h"
|
||||||
|
using namespace Nimbus;
|
||||||
|
|
||||||
|
#include "metis/hmetis.h"
|
||||||
|
#include "metis/MetisGraph.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace Metis;
|
||||||
|
|
||||||
|
typedef map<unsigned, Occurrence> Id2OccurrencesMap;
|
||||||
|
|
||||||
|
struct removeEmptyPartResult
|
||||||
|
{
|
||||||
|
removeEmptyPartResult() {}
|
||||||
|
bool operator()(MetisGraph::PartResult* partresult)
|
||||||
|
{
|
||||||
|
if (partresult->second.size() == 0)
|
||||||
|
{
|
||||||
|
delete partresult;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void VerifyHGraph(int nvtxs, int nhedges, int* vwgts, int* eptr
|
||||||
|
, int* eind, int* hewgts, int nparts, int* part
|
||||||
|
, Id2OccurrencesMap& hypernetidmap)
|
||||||
|
{
|
||||||
|
cerr << "nparts = " << nparts << endl;
|
||||||
|
cerr << "nvtxs = " << nvtxs << endl;
|
||||||
|
|
||||||
|
cerr << "vwgts" << endl;
|
||||||
|
for (int i=0; i < nvtxs; i++)
|
||||||
|
{
|
||||||
|
cerr << vwgts[i] << " ";
|
||||||
|
}
|
||||||
|
cerr << endl;
|
||||||
|
|
||||||
|
cerr << "nhedges = " << nhedges << endl;
|
||||||
|
|
||||||
|
cerr << "eptr" << endl;
|
||||||
|
for (int i=0; i <= nhedges; i++)
|
||||||
|
{
|
||||||
|
cerr << eptr[i] << " ";
|
||||||
|
}
|
||||||
|
cerr << endl;
|
||||||
|
|
||||||
|
cerr << "eind" << endl;
|
||||||
|
for (int i=0; i < eptr[nhedges]; i++)
|
||||||
|
{
|
||||||
|
cerr << eind[i] << " ";
|
||||||
|
}
|
||||||
|
cerr << endl;
|
||||||
|
|
||||||
|
if (hewgts)
|
||||||
|
{
|
||||||
|
cerr << "hewgts" << endl;
|
||||||
|
for (int i=0; i < nhedges; i++)
|
||||||
|
{
|
||||||
|
cerr << hewgts[i] << " ";
|
||||||
|
}
|
||||||
|
cerr << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
cerr << "part" << endl;
|
||||||
|
for (int i=0; i < nvtxs; i++)
|
||||||
|
{
|
||||||
|
cerr << part[i] << " ";
|
||||||
|
}
|
||||||
|
cerr << endl;
|
||||||
|
|
||||||
|
cerr << "nets" << endl;
|
||||||
|
for (int i=0; i < nhedges; i++)
|
||||||
|
{
|
||||||
|
cerr << hypernetidmap[i] << " ";
|
||||||
|
if (hewgts)
|
||||||
|
{
|
||||||
|
cerr << "(" << hewgts[i] << ") : ";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << ": " << endl;
|
||||||
|
}
|
||||||
|
for (int j=eptr[i]; j < eptr[i+1]; j++)
|
||||||
|
{
|
||||||
|
cerr << "(" << eind[j] << "," << vwgts[eind[j]] << ") " ;
|
||||||
|
}
|
||||||
|
cerr << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // End of anonymous namespace.
|
||||||
|
|
||||||
|
|
||||||
|
namespace Metis {
|
||||||
|
|
||||||
|
MetisGraph::MetisGraph ( MetisEngine* metis, GCell* gcell )
|
||||||
|
: _metis(metis)
|
||||||
|
, _cell(_metis->getCell())
|
||||||
|
, _gcell(gcell)
|
||||||
|
, _toPlaceInstanceOccurrencesSet()
|
||||||
|
, _rootNetOccurrencesSet()
|
||||||
|
, _partResultVector()
|
||||||
|
, _edgeCut(INT_MAX)
|
||||||
|
{
|
||||||
|
typedef set<Instance*> InstanceSet;
|
||||||
|
InstanceSet instanceSet;
|
||||||
|
|
||||||
|
for_each_occurrence(occurrence, _cell->getLeafInstanceOccurrences())
|
||||||
|
{
|
||||||
|
Instance* instance = static_cast<Instance*>(occurrence.getEntity());
|
||||||
|
if (!instance->isFixed())
|
||||||
|
{
|
||||||
|
if (instanceSet.find(instance) != instanceSet.end())
|
||||||
|
throw Error("MetisEngine limitation : only one occurrence of unplaced instance");
|
||||||
|
instanceSet.insert(instance);
|
||||||
|
_toPlaceInstanceOccurrencesSet.insert(occurrence); //treat this later
|
||||||
|
}
|
||||||
|
end_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_occurrence(occurrence, _cell->getHyperNetRootNetOccurrences())
|
||||||
|
{
|
||||||
|
Net* net = static_cast<Net*>(occurrence.getEntity());
|
||||||
|
if (net->isGlobal() || net->isPower() || net->isGround())
|
||||||
|
continue;
|
||||||
|
if (net->getCell()->isLeaf())
|
||||||
|
continue;
|
||||||
|
_rootNetOccurrencesSet.insert(occurrence);
|
||||||
|
end_for;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MetisGraph::MetisGraph(MetisEngine* metis, MetisGraph* previous, GCell* gcell, OccurrenceSet& toplaceinstanceoccurrences)
|
||||||
|
: _metis(metis)
|
||||||
|
, _cell(_metis->getCell())
|
||||||
|
, _gcell(gcell)
|
||||||
|
, _toPlaceInstanceOccurrencesSet(toplaceinstanceoccurrences)
|
||||||
|
, _rootNetOccurrencesSet()
|
||||||
|
, _partResultVector()
|
||||||
|
{
|
||||||
|
for (OccurrenceSet::iterator osit = previous->_rootNetOccurrencesSet.begin();
|
||||||
|
osit != previous->_rootNetOccurrencesSet.end();
|
||||||
|
osit++)
|
||||||
|
{
|
||||||
|
HyperNet hyperNet(*osit);
|
||||||
|
for_each_occurrence(leafPlugOccurrence, hyperNet.getLeafPlugOccurrences())
|
||||||
|
{
|
||||||
|
Path path = leafPlugOccurrence.getPath();
|
||||||
|
Instance* instance = (static_cast<Plug*>(leafPlugOccurrence.getEntity()))->getInstance();
|
||||||
|
Occurrence instanceOccurrence(instance, path);
|
||||||
|
OccurrenceSet::const_iterator iosit = _toPlaceInstanceOccurrencesSet.find(instanceOccurrence);
|
||||||
|
if (iosit != _toPlaceInstanceOccurrencesSet.end())
|
||||||
|
{
|
||||||
|
_rootNetOccurrencesSet.insert(*osit); //treat later fixed points.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
end_for;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//treat fixed points in Part method
|
||||||
|
}
|
||||||
|
|
||||||
|
MetisGraph::~MetisGraph()
|
||||||
|
{
|
||||||
|
for (PartResultVector::iterator prvit = _partResultVector.begin();
|
||||||
|
prvit != _partResultVector.end();
|
||||||
|
prvit++)
|
||||||
|
{
|
||||||
|
delete (*prvit);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int MetisGraph::part ( linefill& output )
|
||||||
|
{
|
||||||
|
typedef vector<GCell*> GCellVector;
|
||||||
|
GCellVector subGCells;
|
||||||
|
|
||||||
|
if (not _gcell->hasSubGCells())
|
||||||
|
throw Error("Metis: GCell doesn't have any sub-GCells");
|
||||||
|
for_each_gcell(gcell, _gcell->getSubGCells())
|
||||||
|
{
|
||||||
|
subGCells.push_back(gcell);
|
||||||
|
end_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned subGCellsCount = subGCells.size();
|
||||||
|
|
||||||
|
if (subGCellsCount < 2)
|
||||||
|
throw Error("Metis, Less than 2 sub-GCells (%d)",subGCellsCount);
|
||||||
|
|
||||||
|
vector<double> subGCellsCountOccupation(subGCellsCount, 0.0);
|
||||||
|
typedef list<Occurrence> InstanceOccurrencesList;
|
||||||
|
typedef vector<InstanceOccurrencesList> BoxesInstanceOccurrencesVector;
|
||||||
|
typedef vector<list<double> > BoxesInstanceOccurrencesWeights;
|
||||||
|
BoxesInstanceOccurrencesVector subGCellsFixedInstanceOccurrences(subGCellsCount, InstanceOccurrencesList());
|
||||||
|
BoxesInstanceOccurrencesWeights subGCellsFixedInstanceOccurrenceWeights(subGCellsCount, list<double>());
|
||||||
|
|
||||||
|
vector<int> vwgts_vector;
|
||||||
|
vector<int> hewgts_vector;
|
||||||
|
vector<int> part_vector;
|
||||||
|
|
||||||
|
typedef map<Occurrence, unsigned> Occurrences2IdMap;
|
||||||
|
Occurrences2IdMap instanceOccurrencesMap;
|
||||||
|
|
||||||
|
Id2OccurrencesMap toPlaceInstanceOccurrencesMap;
|
||||||
|
|
||||||
|
for (unsigned gcellCount = 0; gcellCount != subGCells.size(); gcellCount++)
|
||||||
|
{
|
||||||
|
GCell* gcell = subGCells[gcellCount];
|
||||||
|
for_each_occurrence(instanceOccurrence, _cell->getLeafInstanceOccurrencesUnder(gcell->getBox()))
|
||||||
|
{
|
||||||
|
Instance* instance = static_cast<Instance*>(instanceOccurrence.getEntity());
|
||||||
|
if (instance->isFixed())
|
||||||
|
{
|
||||||
|
Box instanceOccurrenceABox = instance->getAbutmentBox();
|
||||||
|
instanceOccurrence.getPath().getTransformation().applyOn(instanceOccurrenceABox);
|
||||||
|
if (gcell->contains(instanceOccurrenceABox))
|
||||||
|
{
|
||||||
|
double instanceWeight =
|
||||||
|
DbU::getLambda(instance->getMasterCell()->getAbutmentBox().getWidth())
|
||||||
|
* DbU::getLambda(instance->getMasterCell()->getAbutmentBox().getHeight());
|
||||||
|
subGCellsCountOccupation[gcellCount] += instanceWeight;
|
||||||
|
subGCellsFixedInstanceOccurrenceWeights[gcellCount].push_back(instanceWeight);
|
||||||
|
subGCellsFixedInstanceOccurrences[gcellCount].push_back(instanceOccurrence);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Box intersection = gcell->getIntersection(instanceOccurrenceABox);
|
||||||
|
if (!intersection.isEmpty())
|
||||||
|
{
|
||||||
|
double intersectionWeight =
|
||||||
|
DbU::getLambda(intersection.getWidth()) * DbU::getLambda(intersection.getHeight());
|
||||||
|
|
||||||
|
subGCellsCountOccupation[gcellCount] += intersectionWeight;
|
||||||
|
subGCellsFixedInstanceOccurrenceWeights[gcellCount].push_back(intersectionWeight);
|
||||||
|
subGCellsFixedInstanceOccurrences[gcellCount].push_back(instanceOccurrence);
|
||||||
|
//FIXME only the last part of the fixed point will be taken into account
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end_for;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned nodeId = 0;
|
||||||
|
|
||||||
|
//treat fixed instances occurrences
|
||||||
|
for (unsigned gcellCount = 0; gcellCount != subGCells.size(); gcellCount++)
|
||||||
|
{
|
||||||
|
GCell* gcell = subGCells[gcellCount];
|
||||||
|
double gcellArea = DbU::getLambda(gcell->getWidth()) * DbU::getLambda(gcell->getHeight());
|
||||||
|
if (((gcellArea - subGCellsCountOccupation[gcellCount])/gcellArea) < 0.10)
|
||||||
|
{
|
||||||
|
cerr << "surOccupied gcell : " << gcell << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_partResultVector.push_back(new PartResult(gcell, OccurrenceSet()));
|
||||||
|
unsigned gcellId = _partResultVector.size() - 1;
|
||||||
|
unsigned fixedNodesCount = subGCellsFixedInstanceOccurrences[gcellCount].size();
|
||||||
|
list<double>::const_iterator dlit =
|
||||||
|
subGCellsFixedInstanceOccurrenceWeights[gcellCount].begin();
|
||||||
|
InstanceOccurrencesList::const_iterator iolit =
|
||||||
|
subGCellsFixedInstanceOccurrences[gcellCount].begin();
|
||||||
|
for (unsigned id = 0; id != fixedNodesCount; id++)
|
||||||
|
{
|
||||||
|
vwgts_vector.push_back((int)*dlit);
|
||||||
|
instanceOccurrencesMap[*iolit] = nodeId++;
|
||||||
|
++dlit; ++iolit;
|
||||||
|
}
|
||||||
|
part_vector.insert(part_vector.end(), fixedNodesCount, gcellId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//now treat instance occurrences to place
|
||||||
|
|
||||||
|
typedef vector<Occurrence> OccurrenceVector;
|
||||||
|
OccurrenceVector instanceOccurrenceVector(_toPlaceInstanceOccurrencesSet.begin(), _toPlaceInstanceOccurrencesSet.end());
|
||||||
|
random_shuffle(instanceOccurrenceVector.begin(), instanceOccurrenceVector.end());
|
||||||
|
|
||||||
|
for (OccurrenceVector::const_iterator ovit = instanceOccurrenceVector.begin();
|
||||||
|
ovit != instanceOccurrenceVector.end();
|
||||||
|
ovit++)
|
||||||
|
{
|
||||||
|
Instance* instance = static_cast<Instance*>(ovit->getEntity());
|
||||||
|
double instanceWeight =
|
||||||
|
DbU::getLambda(instance->getMasterCell()->getAbutmentBox().getWidth())
|
||||||
|
* DbU::getLambda(instance->getMasterCell()->getAbutmentBox().getHeight());
|
||||||
|
vwgts_vector.push_back((int)instanceWeight);
|
||||||
|
part_vector.push_back(-1);
|
||||||
|
toPlaceInstanceOccurrencesMap[nodeId] = *ovit;
|
||||||
|
instanceOccurrencesMap[*ovit] = nodeId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
output << _toPlaceInstanceOccurrencesSet.size();
|
||||||
|
|
||||||
|
// constructing edges from hypernets
|
||||||
|
vector<int> eptr_vector;
|
||||||
|
vector<int> eind_vector;
|
||||||
|
eptr_vector.push_back(0);
|
||||||
|
int hyperEdgesCount = 0;
|
||||||
|
|
||||||
|
#ifdef METISSE_DEBUG
|
||||||
|
Id2OccurrencesMap hyperNetIdMap;
|
||||||
|
Id2OccurrencesMap nodesIdMap;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OccurrenceVector netOccurrenceVector(_rootNetOccurrencesSet.begin(), _rootNetOccurrencesSet.end());
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for (OccurrenceSet::iterator osit = _rootNetOccurrencesSet.begin();
|
||||||
|
osit != _rootNetOccurrencesSet.end();
|
||||||
|
osit++)
|
||||||
|
#endif
|
||||||
|
for (OccurrenceVector::iterator ovit = netOccurrenceVector.begin();
|
||||||
|
ovit != netOccurrenceVector.end();
|
||||||
|
ovit++)
|
||||||
|
{
|
||||||
|
HyperNet hyperNet(*ovit);
|
||||||
|
list<unsigned> hyperNetNodes;
|
||||||
|
typedef list<Occurrence> OccurrenceList;
|
||||||
|
OccurrenceList terminals;
|
||||||
|
unsigned nodesToPlace = 0;
|
||||||
|
|
||||||
|
//look for pins, pins are on the root net
|
||||||
|
Net* rootNet = static_cast<Net*>(ovit->getEntity());
|
||||||
|
for_each_pin(pin, rootNet->getPins())
|
||||||
|
{
|
||||||
|
Path path = ovit->getPath();
|
||||||
|
Occurrence pinOccurrence(pin, path);
|
||||||
|
terminals.push_back(pinOccurrence);
|
||||||
|
end_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
OccurrenceSet instanceOccurrencesSet; //to detect multi connection of a single instance
|
||||||
|
for_each_occurrence(leafPlugOccurrence, hyperNet.getLeafPlugOccurrences())
|
||||||
|
{
|
||||||
|
Path path = leafPlugOccurrence.getPath();
|
||||||
|
Instance* instance = (static_cast<Plug*>(leafPlugOccurrence.getEntity()))->getInstance();
|
||||||
|
Occurrence instanceOccurrence(instance, path);
|
||||||
|
OccurrenceSet::const_iterator iosit = instanceOccurrencesSet.find(instanceOccurrence);
|
||||||
|
if (iosit != instanceOccurrencesSet.end())
|
||||||
|
continue;
|
||||||
|
instanceOccurrencesSet.insert(instanceOccurrence);
|
||||||
|
Occurrences2IdMap::const_iterator imit = instanceOccurrencesMap.find(instanceOccurrence);
|
||||||
|
if (imit == instanceOccurrencesMap.end())
|
||||||
|
{
|
||||||
|
terminals.push_back(instanceOccurrence);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned nodeId = imit->second;
|
||||||
|
hyperNetNodes.push_back(nodeId);
|
||||||
|
if (part_vector[nodeId] == -1)
|
||||||
|
++nodesToPlace;
|
||||||
|
}
|
||||||
|
end_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned terminalsCount = terminals.size();
|
||||||
|
|
||||||
|
if (nodesToPlace > 1 || ((nodesToPlace > 0) && (terminalsCount > 0)))
|
||||||
|
{
|
||||||
|
#ifdef METISSE_DEBUG
|
||||||
|
hyperNetIdMap[hyperEdgesCount] = *ovit;
|
||||||
|
#endif
|
||||||
|
++hyperEdgesCount;
|
||||||
|
if (terminalsCount > 0)
|
||||||
|
{
|
||||||
|
DbU::Unit x = 0;
|
||||||
|
DbU::Unit y = 0;
|
||||||
|
for (OccurrenceList::iterator olit = terminals.begin();
|
||||||
|
olit != terminals.end();
|
||||||
|
olit++)
|
||||||
|
{
|
||||||
|
Point center = olit->getBoundingBox().getCenter();
|
||||||
|
x += center.getX() / terminalsCount;
|
||||||
|
y += center.getY() / terminalsCount;
|
||||||
|
}
|
||||||
|
Point barycenter(x,y);
|
||||||
|
//recherche brute force de la meilleure gcell
|
||||||
|
GCell* targetGCell = NULL;
|
||||||
|
unsigned targetGCellId = 0;
|
||||||
|
DbU::Unit bestDistance = LONG_MAX;
|
||||||
|
for (unsigned gcellid = 0; gcellid < _partResultVector.size(); gcellid++)
|
||||||
|
{
|
||||||
|
GCell* gcell = _partResultVector[gcellid]->first;
|
||||||
|
DbU::Unit distance = gcell->manhattanDistance(barycenter);
|
||||||
|
if (distance < bestDistance)
|
||||||
|
{
|
||||||
|
bestDistance = distance;
|
||||||
|
targetGCell = gcell;
|
||||||
|
targetGCellId = gcellid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(targetGCell);
|
||||||
|
//insert fixed point
|
||||||
|
hyperNetNodes.push_back(nodeId++);
|
||||||
|
vwgts_vector.push_back(0);
|
||||||
|
part_vector.push_back(targetGCellId);
|
||||||
|
assert(_metis->getGlobalConnectionsWeightRatio());
|
||||||
|
if (_metis->getGlobalConnectionsWeightRatio() > 0)
|
||||||
|
hewgts_vector.push_back(_metis->getGlobalConnectionsWeightRatio());
|
||||||
|
else
|
||||||
|
hewgts_vector.push_back(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(_metis->getGlobalConnectionsWeightRatio());
|
||||||
|
if (_metis->getGlobalConnectionsWeightRatio() < 0)
|
||||||
|
hewgts_vector.push_back(-_metis->getGlobalConnectionsWeightRatio());
|
||||||
|
else
|
||||||
|
hewgts_vector.push_back(1);
|
||||||
|
}
|
||||||
|
assert(hyperNetNodes.size() > 1);
|
||||||
|
eind_vector.insert(eind_vector.end(), hyperNetNodes.begin(), hyperNetNodes.end());
|
||||||
|
eptr_vector.push_back(eptr_vector.back() + hyperNetNodes.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//OK now the real thing ... call hmetis
|
||||||
|
|
||||||
|
size_t nvtxs = part_vector.size();
|
||||||
|
if (nvtxs < _metis->getNumberOfInstancesStopCriterion())
|
||||||
|
throw TooLowNVTXSException(nvtxs);
|
||||||
|
|
||||||
|
size_t nhedges = eptr_vector.size() - 1;
|
||||||
|
size_t nparts = _partResultVector.size();
|
||||||
|
|
||||||
|
assert(part_vector.size() == vwgts_vector.size());
|
||||||
|
assert (nhedges == (size_t)hyperEdgesCount);
|
||||||
|
assert (nhedges == static_cast<size_t>(hewgts_vector.size()));
|
||||||
|
|
||||||
|
int* eind = new int[eind_vector.size()];
|
||||||
|
for (unsigned id = 0; id < eind_vector.size(); id++)
|
||||||
|
{
|
||||||
|
eind[id] = eind_vector[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
int* eptr = new int[eptr_vector.size()];
|
||||||
|
for (unsigned id = 0; id < eptr_vector.size(); id++)
|
||||||
|
{
|
||||||
|
eptr[id] = eptr_vector[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
int* vwgts = new int[vwgts_vector.size()];
|
||||||
|
for (unsigned id = 0; id < vwgts_vector.size(); id++)
|
||||||
|
{
|
||||||
|
vwgts[id] = vwgts_vector[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
int* hewgts = new int[hewgts_vector.size()];
|
||||||
|
for (unsigned id = 0; id < hewgts_vector.size(); id++)
|
||||||
|
{
|
||||||
|
hewgts[id] = hewgts_vector[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool preAssignment = false;
|
||||||
|
int* part = new int[nvtxs];
|
||||||
|
for (unsigned id = 0; id < part_vector.size(); id++)
|
||||||
|
{
|
||||||
|
part[id] = part_vector[id];
|
||||||
|
if (part_vector[id] != -1)
|
||||||
|
preAssignment = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//verification
|
||||||
|
|
||||||
|
for (int id = 0; id < eptr[nhedges] ; id++)
|
||||||
|
{
|
||||||
|
assert(eind[id] < (int)nvtxs);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t id = 0; id < nvtxs ; id++)
|
||||||
|
{
|
||||||
|
assert((part[id] == -1) || (part[id] < (int)nparts));
|
||||||
|
}
|
||||||
|
|
||||||
|
_metis->setHMetisOption ( Configuration::HMetisRandom, -1 ); //use random
|
||||||
|
|
||||||
|
|
||||||
|
if (preAssignment)
|
||||||
|
_metis->setHMetisOption ( Configuration::HMetisPreAssign, 1 );
|
||||||
|
else
|
||||||
|
_metis->setHMetisOption ( Configuration::HMetisPreAssign, 0 );
|
||||||
|
|
||||||
|
#ifdef METISSE_DEBUG
|
||||||
|
VerifyHGraph(nvtxs, nhedges, vwgts, eptr, eind, hewgts, nparts, part, hyperNetIdMap);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_metis->getPartOrKWayHMetis())
|
||||||
|
{
|
||||||
|
int ubFactor = _metis->getUbFactor();
|
||||||
|
if (!ubFactor)
|
||||||
|
ubFactor = 2; // the minimal value is 1, but let's try a bit of amplitude.
|
||||||
|
HMETIS_PartRecursive(nvtxs, nhedges, vwgts
|
||||||
|
, eptr, eind, hewgts, nparts
|
||||||
|
, ubFactor
|
||||||
|
, _metis->getHMetisOptions()
|
||||||
|
, part, &_edgeCut);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int ubFactor = _metis->getUbFactor();
|
||||||
|
if (!ubFactor)
|
||||||
|
ubFactor = 5; //minimal value
|
||||||
|
HMETIS_PartKway(nvtxs, nhedges, vwgts
|
||||||
|
, eptr, eind, hewgts, nparts
|
||||||
|
, ubFactor, _metis->getHMetisOptions(), part, &_edgeCut);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateSession::open();
|
||||||
|
for (Id2OccurrencesMap::const_iterator omit = toPlaceInstanceOccurrencesMap.begin();
|
||||||
|
omit != toPlaceInstanceOccurrencesMap.end();
|
||||||
|
omit++)
|
||||||
|
{
|
||||||
|
unsigned instanceId = omit->first;
|
||||||
|
unsigned gcellId = part[instanceId];
|
||||||
|
Occurrence instanceOccurrence = omit->second;
|
||||||
|
Instance* instance = static_cast<Instance*>(instanceOccurrence.getEntity());
|
||||||
|
GCell* gcell = _partResultVector[gcellId]->first;
|
||||||
|
|
||||||
|
_partResultVector[gcellId]->second.insert(instanceOccurrence);
|
||||||
|
|
||||||
|
DbU::Unit xPos = gcell->getCenter().getX();
|
||||||
|
DbU::Unit yPos = gcell->getCenter().getY();
|
||||||
|
Box masterABox = instance->getMasterCell()->getAbutmentBox();
|
||||||
|
Transformation instanceTransformation = getTransformation(masterABox
|
||||||
|
, xPos - masterABox.getHalfWidth()
|
||||||
|
, yPos - masterABox.getHalfHeight()
|
||||||
|
, Transformation::Orientation::ID);
|
||||||
|
instanceOccurrence.getPath().getTransformation().invert().applyOn(instanceTransformation);
|
||||||
|
instance->setTransformation(instanceTransformation);
|
||||||
|
instance->setPlacementStatus(Instance::PlacementStatus::PLACED);
|
||||||
|
}
|
||||||
|
|
||||||
|
_partResultVector.erase(
|
||||||
|
remove_if(_partResultVector.begin(), _partResultVector.end(), removeEmptyPartResult())
|
||||||
|
, _partResultVector.end()
|
||||||
|
);
|
||||||
|
|
||||||
|
for (PartResultVector::iterator prvit = _partResultVector.begin();
|
||||||
|
prvit != _partResultVector.end();
|
||||||
|
prvit++)
|
||||||
|
{
|
||||||
|
(*prvit)->first->setAsPlacementLeaf();
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateSession::close();
|
||||||
|
|
||||||
|
delete[] eind;
|
||||||
|
delete[] eptr;
|
||||||
|
delete[] hewgts;
|
||||||
|
delete[] vwgts;
|
||||||
|
delete[] part;
|
||||||
|
|
||||||
|
return _edgeCut;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_HMETIS_LIB */
|
|
@ -0,0 +1,152 @@
|
||||||
|
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved
|
||||||
|
//
|
||||||
|
// ===================================================================
|
||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// x-----------------------------------------------------------------x
|
||||||
|
// | |
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | M e t i s - h M e t i s W r a p p e r |
|
||||||
|
// | |
|
||||||
|
// | Author : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./Configuration.h" |
|
||||||
|
// | *************************************************************** |
|
||||||
|
// | U p d a t e s |
|
||||||
|
// | |
|
||||||
|
// x-----------------------------------------------------------------x
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __METIS_CONFIGURATION__
|
||||||
|
#define __METIS_CONFIGURATION__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
|
||||||
|
namespace Hurricane {
|
||||||
|
class Record;
|
||||||
|
class Cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace Metis {
|
||||||
|
|
||||||
|
using Hurricane::Record;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Metis::Configuration".
|
||||||
|
|
||||||
|
|
||||||
|
class Configuration {
|
||||||
|
public:
|
||||||
|
typedef boost::function< void(void) > RefreshCb_t;
|
||||||
|
public:
|
||||||
|
enum MetisOption { CustomOptions =0
|
||||||
|
, HMetisNRuns =1
|
||||||
|
, HMetisCType =2
|
||||||
|
, HMetisRType =3
|
||||||
|
, HMetisVCycle =4
|
||||||
|
, HMetisReconst =5
|
||||||
|
, HMetisPreAssign =6
|
||||||
|
, HMetisRandom =7
|
||||||
|
, HMetisDebugLevel =8
|
||||||
|
, HMetisOptionsSize=9
|
||||||
|
};
|
||||||
|
enum HMetisCTypeValues { CTypeHFC =1 // Hybrid First Choice Scheme.
|
||||||
|
, CTypeFC =2 // First Choice Scheme.
|
||||||
|
, CTypeGFC =3 // Greedy First Choice Scheme.
|
||||||
|
, CTypeHyperEdge =4 // Hyper-Edge Scheme.
|
||||||
|
, CTypeEdge =5 // Edge Scheme.
|
||||||
|
};
|
||||||
|
enum HMetisRTypeValues { RTypeFM =1 // Uncoarsening Fiduccia-Mattheyses.
|
||||||
|
, RTypeOneWayFM =2 // Uncoarsening One Way Fiduccia-Mattheyses.
|
||||||
|
, RTypeEarlyExitFM =3 // Uncoarsening Early Exit Fiduccia-Mattheyses.
|
||||||
|
};
|
||||||
|
enum HMetisVCycleValues { VCycleDisable =0 // Do not perform any V-Cycle Reffinment.
|
||||||
|
, VCycleFinal =1 // Perform V-Cycle on each final bisection step.
|
||||||
|
, VCycleBestIntermed =2 // Perform V-Cycle on each intermediate solution.
|
||||||
|
, VCycleAllIntermed =3 // Perform V-Cycle on all intermediate solution.
|
||||||
|
};
|
||||||
|
enum HMetisReconstValues { ReconstRemoveCutHE =0 // Remove cut hyperedges.
|
||||||
|
, ReconstKeepCutHE =1 // Keep each part of the cuts hyperedges.
|
||||||
|
};
|
||||||
|
enum HMetisDebugValues { DebugDisable =0 // Disable debugging.
|
||||||
|
, DebugCoarseningStage=1 // Debug coarsening stage.
|
||||||
|
, DebugInitialPart =2 // Debug initial partition stage.
|
||||||
|
, DebugRefinement =4 // Debug refinement stage.
|
||||||
|
, DebugMultRuns =8 // Debug multiple runs stage.
|
||||||
|
, DebugMoreMultRuns =16 // More debug of the multiple runs stage.
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
static Configuration* getDefault ();
|
||||||
|
public:
|
||||||
|
// Constructor & Destructor.
|
||||||
|
Configuration ();
|
||||||
|
~Configuration ();
|
||||||
|
Configuration* clone () const;
|
||||||
|
// Methods.
|
||||||
|
void print ( Cell* ) const;
|
||||||
|
inline RefreshCb_t& getRefreshCb ();
|
||||||
|
inline bool getPartOrKWayHMetis () const;
|
||||||
|
inline unsigned int getNumberOfInstancesStopCriterion () const;
|
||||||
|
inline int getGlobalConnectionsWeightRatio () const;
|
||||||
|
inline int getUbFactor () const;
|
||||||
|
inline int* getHMetisOptions ();
|
||||||
|
inline int getHMetisOption ( MetisOption );
|
||||||
|
inline void setRefreshCb ( Configuration::RefreshCb_t );
|
||||||
|
inline void setPartOrKWayHMetis ( bool usePart );
|
||||||
|
inline void setNumberOfInstancesStopCriterion ( unsigned int );
|
||||||
|
inline void setGlobalConnectionsWeightRatio ( int );
|
||||||
|
inline void setUbFactor ( int );
|
||||||
|
inline void setHMetisOption ( MetisOption, int value );
|
||||||
|
Record* _getRecord () const;
|
||||||
|
std::string _getString () const;
|
||||||
|
std::string _getTypeName () const;
|
||||||
|
private:
|
||||||
|
// Attributes.
|
||||||
|
static Configuration* _default;
|
||||||
|
RefreshCb_t _refreshCb;
|
||||||
|
bool _partOrKWayHMetis; // True for Recursive 2-part, false for KWay.
|
||||||
|
unsigned int _numberOfInstancesStopCriterion; // Minimal number of instances to partition.
|
||||||
|
int _globalConnectionsWeightRatio;
|
||||||
|
int _ubFactor;
|
||||||
|
int _hmetisOptions[HMetisOptionsSize];
|
||||||
|
private:
|
||||||
|
Configuration ( const Configuration& );
|
||||||
|
Configuration& operator= ( const Configuration& );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Inline Methods.
|
||||||
|
inline Configuration::RefreshCb_t&
|
||||||
|
Configuration::getRefreshCb () { return _refreshCb; }
|
||||||
|
inline bool Configuration::getPartOrKWayHMetis () const { return _partOrKWayHMetis; }
|
||||||
|
inline unsigned int Configuration::getNumberOfInstancesStopCriterion () const { return _numberOfInstancesStopCriterion; }
|
||||||
|
inline int Configuration::getGlobalConnectionsWeightRatio () const { return _globalConnectionsWeightRatio; }
|
||||||
|
inline int Configuration::getUbFactor () const { return _ubFactor; }
|
||||||
|
inline int* Configuration::getHMetisOptions () { return _hmetisOptions; }
|
||||||
|
inline int Configuration::getHMetisOption ( MetisOption option ) { return (option<HMetisOptionsSize) ? _hmetisOptions[option] : 0; }
|
||||||
|
inline void Configuration::setRefreshCb ( Configuration::RefreshCb_t cb ) { _refreshCb=cb; }
|
||||||
|
inline void Configuration::setPartOrKWayHMetis ( bool usePart ) { _partOrKWayHMetis=usePart; }
|
||||||
|
inline void Configuration::setNumberOfInstancesStopCriterion ( unsigned int value ) { _numberOfInstancesStopCriterion=value; }
|
||||||
|
inline void Configuration::setGlobalConnectionsWeightRatio ( int value ) { _globalConnectionsWeightRatio=value; }
|
||||||
|
inline void Configuration::setUbFactor ( int value ) { _ubFactor=value; }
|
||||||
|
inline void Configuration::setHMetisOption ( MetisOption option, int value )
|
||||||
|
{ if (option<HMetisOptionsSize) _hmetisOptions[option] = value; }
|
||||||
|
|
||||||
|
|
||||||
|
} // End of Metis namespace.
|
||||||
|
|
||||||
|
|
||||||
|
INSPECTOR_P_SUPPORT(Metis::Configuration);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __METIS_CONFIGURATION__
|
|
@ -0,0 +1,119 @@
|
||||||
|
|
||||||
|
// This file is part of the Coriolis Project.
|
||||||
|
// Copyright (C) Laboratoire LIP6 - Departement ASIM
|
||||||
|
// Universite Pierre et Marie Curie
|
||||||
|
//
|
||||||
|
// Main contributors :
|
||||||
|
// Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
||||||
|
// Hugo Clément <Hugo.Clement@lip6.fr>
|
||||||
|
// Jean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
|
||||||
|
// Christian Masson <Christian.Masson@lip6.fr>
|
||||||
|
//
|
||||||
|
// The Coriolis Project is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The Coriolis Project is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Coriolis Project; if not, write to the Free Software
|
||||||
|
// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// License-Tag
|
||||||
|
//
|
||||||
|
// Date : 29/01/2004
|
||||||
|
// Author : Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
||||||
|
//
|
||||||
|
// Authors-Tag
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __METIS_ENGINE_H__
|
||||||
|
#define __METIS_ENGINE_H__
|
||||||
|
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
#include "crlcore/ToolEngine.h"
|
||||||
|
#include "crlcore/ToolEngine.h"
|
||||||
|
|
||||||
|
#include "metis/Configuration.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Metis {
|
||||||
|
|
||||||
|
using Hurricane::Record;
|
||||||
|
using Hurricane::Name;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
|
||||||
|
class MetisGraph;
|
||||||
|
|
||||||
|
class MetisEngine: public CRL::ToolEngine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Types.
|
||||||
|
typedef ToolEngine Inherit;
|
||||||
|
typedef std::vector<MetisGraph*> MetisGraphs;
|
||||||
|
public:
|
||||||
|
// Constructor.
|
||||||
|
static MetisEngine* create ( Cell* );
|
||||||
|
static MetisEngine* get ( Cell* );
|
||||||
|
// Methods.
|
||||||
|
static unsigned int computeQuadriPartitions ( Cell* );
|
||||||
|
static void doQuadriPart ( Cell* );
|
||||||
|
static bool isHMetisCapable ();
|
||||||
|
static const Name& staticGetName ();
|
||||||
|
virtual const Name& getName () const;
|
||||||
|
int getGlobalEdgeCut () const;
|
||||||
|
inline Configuration* getConfiguration ();
|
||||||
|
inline Configuration::RefreshCb_t&
|
||||||
|
getRefreshCb ();
|
||||||
|
inline bool getPartOrKWayHMetis () const;
|
||||||
|
inline unsigned int getNumberOfInstancesStopCriterion () const;
|
||||||
|
inline int getGlobalConnectionsWeightRatio () const;
|
||||||
|
inline int getUbFactor () const;
|
||||||
|
inline int* getHMetisOptions ();
|
||||||
|
inline int getHMetisOption ( Configuration::MetisOption );
|
||||||
|
inline void setHMetisOption ( Configuration::MetisOption, int value );
|
||||||
|
void run ();
|
||||||
|
void save ( unsigned step );
|
||||||
|
inline void setRefreshCb ( Configuration::RefreshCb_t );
|
||||||
|
virtual std::string _getTypeName () const {return "Metis::MetisEngine";};
|
||||||
|
virtual Record* _getRecord () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Attributes.
|
||||||
|
static const Name _toolName;
|
||||||
|
Configuration* _configuration;
|
||||||
|
unsigned _step;
|
||||||
|
MetisGraphs* _actualGraphs;
|
||||||
|
MetisGraphs* _newGraphs;
|
||||||
|
int _globalEdgeCut;
|
||||||
|
private:
|
||||||
|
// Internals.
|
||||||
|
MetisEngine ( Cell* );
|
||||||
|
virtual ~MetisEngine ();
|
||||||
|
virtual void _preDestroy ();
|
||||||
|
bool _reInit ();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Inline Methods.
|
||||||
|
inline Configuration* MetisEngine::getConfiguration () { return _configuration; }
|
||||||
|
inline Configuration::RefreshCb_t& MetisEngine::getRefreshCb () { return _configuration->getRefreshCb(); }
|
||||||
|
inline bool MetisEngine::getPartOrKWayHMetis () const { return _configuration->getPartOrKWayHMetis(); }
|
||||||
|
inline unsigned int MetisEngine::getNumberOfInstancesStopCriterion () const { return _configuration->getNumberOfInstancesStopCriterion(); }
|
||||||
|
inline int MetisEngine::getGlobalConnectionsWeightRatio () const { return _configuration->getGlobalConnectionsWeightRatio(); }
|
||||||
|
inline int MetisEngine::getUbFactor () const { return _configuration->getUbFactor(); }
|
||||||
|
inline int* MetisEngine::getHMetisOptions () { return _configuration->getHMetisOptions(); }
|
||||||
|
inline int MetisEngine::getHMetisOption ( Configuration::MetisOption option ) { return _configuration->getHMetisOption(option); }
|
||||||
|
inline void MetisEngine::setRefreshCb ( Configuration::RefreshCb_t cb ) { _configuration->setRefreshCb(cb); }
|
||||||
|
inline void MetisEngine::setHMetisOption ( Configuration::MetisOption option, int value ) { _configuration->setHMetisOption(option,value); }
|
||||||
|
|
||||||
|
|
||||||
|
} // End of Metis namespace.
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __METIS_ENGINE_H__
|
|
@ -0,0 +1,82 @@
|
||||||
|
|
||||||
|
// This file is part of the Coriolis Project.
|
||||||
|
// Copyright (C) Laboratoire LIP6 - Departement ASIM
|
||||||
|
// Universite Pierre et Marie Curie
|
||||||
|
//
|
||||||
|
// Main contributors :
|
||||||
|
// Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
||||||
|
// Hugo Clément <Hugo.Clement@lip6.fr>
|
||||||
|
// Jean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
|
||||||
|
// Christian Masson <Christian.Masson@lip6.fr>
|
||||||
|
//
|
||||||
|
// The Coriolis Project is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The Coriolis Project is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Coriolis Project; if not, write to the Free Software
|
||||||
|
// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// License-Tag
|
||||||
|
//
|
||||||
|
// Date : 29/01/2004
|
||||||
|
// Author : Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
||||||
|
//
|
||||||
|
// Authors-Tag
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __METISGRAPH_H
|
||||||
|
#define __METISGRAPH_H
|
||||||
|
|
||||||
|
#ifdef HAVE_HMETIS_LIB
|
||||||
|
|
||||||
|
#include "metis/MetisEngine.h"
|
||||||
|
|
||||||
|
namespace Metis {
|
||||||
|
|
||||||
|
class MetisGraph
|
||||||
|
{
|
||||||
|
friend class MetisEngine;
|
||||||
|
public:
|
||||||
|
typedef set<Occurrence> OccurrenceSet;
|
||||||
|
typedef pair<GCell*, OccurrenceSet> PartResult;
|
||||||
|
typedef vector<PartResult*> PartResultVector;
|
||||||
|
public:
|
||||||
|
class TooLowNVTXSException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int _nvtxs;
|
||||||
|
public:
|
||||||
|
TooLowNVTXSException(int nvtxs): _nvtxs(nvtxs) {}
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
MetisEngine* _metis;
|
||||||
|
Cell* _cell;
|
||||||
|
GCell* _gcell; // Placement zone
|
||||||
|
OccurrenceSet _toPlaceInstanceOccurrencesSet;
|
||||||
|
OccurrenceSet _rootNetOccurrencesSet;
|
||||||
|
PartResultVector _partResultVector;
|
||||||
|
int _edgeCut; // EdgeCut from last part
|
||||||
|
public:
|
||||||
|
MetisGraph ( MetisEngine*, GCell* box);
|
||||||
|
MetisGraph ( MetisEngine* metis
|
||||||
|
, MetisGraph* previous
|
||||||
|
, GCell* gcell
|
||||||
|
, OccurrenceSet& toplaceinstanceoccurrences);
|
||||||
|
~MetisGraph ();
|
||||||
|
int part ( linefill& );
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End of Metis namespace.
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HAVE_HMETIS_LIB */
|
||||||
|
|
||||||
|
#endif /* __METISGRAPH_H */
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
#ifndef __HMETIS_H__
|
||||||
|
#define __HMETIS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
void HMETIS_PartRecursive( int nvtxs, int nhedges, int *vwgts, int *eptr
|
||||||
|
, int *eind, int *hewgts, int nparts, int ubfactor
|
||||||
|
, int *options, int *part, int *edgecut );
|
||||||
|
|
||||||
|
void HMETIS_PartKway( int nvtxs, int nhedges, int *vwgts
|
||||||
|
, int *eptr, int *eind, int *hewgts, int nparts
|
||||||
|
, int ubfactor, int *options, int *part, int *edgecut);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif // __HMETIS_H__
|
Loading…
Reference in New Issue