diff --git a/mauka/CMakeLists.txt b/mauka/CMakeLists.txt new file mode 100644 index 00000000..6c687e1f --- /dev/null +++ b/mauka/CMakeLists.txt @@ -0,0 +1,52 @@ +PROJECT(MAUKA) + +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_LIB_LINK_MODE() + +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(cmake_modules) diff --git a/mauka/cmake_modules/CMakeLists.txt b/mauka/cmake_modules/CMakeLists.txt new file mode 100644 index 00000000..3191eecb --- /dev/null +++ b/mauka/cmake_modules/CMakeLists.txt @@ -0,0 +1 @@ +install ( FILES FindMAUKA.cmake DESTINATION share/cmake/Modules ) diff --git a/mauka/cmake_modules/FindMAUKA.cmake b/mauka/cmake_modules/FindMAUKA.cmake new file mode 100644 index 00000000..6928efc1 --- /dev/null +++ b/mauka/cmake_modules/FindMAUKA.cmake @@ -0,0 +1,37 @@ +# - Find the Mauka includes and libraries. +# The following variables are set if Coriolis is found. If MAUKA is not +# found, MAUKA_FOUND is set to false. +# MAUKA_FOUND - True when the Coriolis include directory is found. +# MAUKA_INCLUDE_DIR - the path to where the Coriolis include files are. +# MAUKA_LIBRARIES - The path to where the Coriolis library files are. + + +SET(MAUKA_INCLUDE_PATH_DESCRIPTION "directory containing the Mauka/flute include files. E.g /usr/local/include/coriolis or /asim/coriolis/include/coriolis") + +SET(MAUKA_DIR_MESSAGE "Set the MAUKA_INCLUDE_DIR cmake cache entry to the ${MAUKA_INCLUDE_PATH_DESCRIPTION}") + +# don't even bother under WIN32 +IF(UNIX) + # + # Look for an installation. + # + FIND_PATH(MAUKA_INCLUDE_PATH NAMES mauka/MaukaEngine.h PATHS + # Look in other places. + ${CORIOLIS_DIR_SEARCH} + PATH_SUFFIXES include/coriolis2 + # Help the user find it if we cannot. + DOC "The ${MAUKA_INCLUDE_PATH_DESCRIPTION}" + ) + + FIND_LIBRARY(MAUKA_LIBRARY_PATH + NAMES mauka + PATHS ${CORIOLIS_DIR_SEARCH} + PATH_SUFFIXES lib${LIB_SUFFIX} + # Help the user find it if we cannot. + DOC "The ${MAUKA_INCLUDE_PATH_DESCRIPTION}" + ) + + SET_LIBRARIES_PATH(MAUKA MAUKA) + HURRICANE_CHECK_LIBRARIES(MAUKA) + +ENDIF(UNIX) diff --git a/mauka/src/BBPlacer.cpp b/mauka/src/BBPlacer.cpp new file mode 100644 index 00000000..1a4bc706 --- /dev/null +++ b/mauka/src/BBPlacer.cpp @@ -0,0 +1,735 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// inspired by Andrew Caldwell's BranchSmallPlacer +// Authors-Tag + +/************************************************************************** +*** +*** Copyright (c) 1995-2000 Regents of the University of California, +*** Andrew E. Caldwell, Andrew B. Kahng and Igor L. Markov +*** Copyright (c) 2000-2002 Regents of the University of Michigan, +*** Saurabh N. Adya and Igor L. Markov +*** +*** Contact author(s): abk@cs.ucsd.edu, imarkov@umich.edu +*** Original Affiliation: UCLA, computer Science Department, +*** Los Angeles, CA 90095-1596 USA +*** +*** Permission is hereby granted, free of charge, to any person obtaining +*** a copy of this software and associated documentation files (the +*** "Software"), to deal in the Software without restriction, including +*** without limitation +*** the rights to use, copy, modify, merge, publish, distribute, sublicense, +*** and/or sell copies of the Software, and to permit persons to whom the +*** Software is furnished to do so, subject to the following conditions: +*** +*** The above copyright notice and this permission notice shall be included +*** in all copies or substantial portions of the Software. +*** +*** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +*** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +*** OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +*** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +*** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +*** OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +*** THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*** +*** +***************************************************************************/ + +#include "hurricane/UpdateSession.h" +#include "hurricane/Net.h" +#include "hurricane/Cell.h" +#include "crlcore/ToolBox.h" +#include "crlcore/CellGauge.h" +#include "crlcore/AllianceFramework.h" + +#include "mauka/MaukaEngine.h" +#include "mauka/Surface.h" +#include "mauka/Row.h" +#include "mauka/SubRow.h" +#include "mauka/Bin.h" +#include "mauka/BBPlacer.h" + +namespace { + +using namespace Mauka; + +class CompareInstancePosition +{ + private: BBPlacer* _bbPlacer; + + public: CompareInstancePosition(BBPlacer* bbplacer) + : _bbPlacer(bbplacer) + {} + public: bool operator()(unsigned id1, unsigned id2) const + { + return _bbPlacer->getInstanceIdX(id1) < _bbPlacer->getInstanceIdX(id2); + } +}; + +} // End of anonymous namespace. + +namespace Mauka { + +using namespace std; +using namespace Hurricane; +using namespace CRL; + +//#define PLACE_DEBUG 1 + +BBPlacer::BBPlacer(MaukaEngine* mauka) + : _mauka(mauka) + , _subRowVector() + , _subRowInstances() + , _instanceX() + , _instanceY() + , _instancePlaced() + , _netVector() + , _netBBoxes() + , _netCosts() + , _netCurrCostMark() + , _netFlags() + , _instanceToOptimize() + , _leftEdge(0) + , _rightEdge(0) + , _oldCost(0.0) + , _cost(0.0) + , _bestCost(0.0) + , _costFlag(0) + , _queue() + , _stack() + , _loopVect() + , _bestSolution() + , _idx(0) +{ + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + _instanceMarginWidth.push_back(_mauka->_instanceWidths[i]); + _instanceX.push_back(0); + _instanceY.push_back(0); + _instancePlaced.push_back(true); + } + + for (unsigned netid = 0; netid < _mauka->_nets.size(); netid++) + { + vector bboxes(2); + _netBBoxes.push_back(bboxes); + vector costs(2); + _netCosts.push_back(costs); + _netFlags.push_back(0); + _netCurrCostMark.push_back(0); + } + + + Surface::RowVector& rowVector = _mauka->_surface->_rowVector; + + for (Surface::RowVector::iterator rvit = rowVector.begin(); + rvit != rowVector.end(); + rvit++) + { + Row::SubRowVector& subRowVector = (*rvit)->_subRowVector; + for (Row::SubRowVector::iterator srvit = subRowVector.begin(); + srvit != subRowVector.end(); + srvit++) + { + SubRow* subRow = *srvit; + if (subRow->getSize() > 0) + { + _subRowVector.push_back(subRow); + _subRowInstances.push_back(MaukaEngine::UVector()); + DbU::Unit totalInstanceSizeInRow = 0; + for (SubRow::BinVector::iterator bvit = subRow->_binVector.begin(); + bvit != subRow->_binVector.end(); + bvit++) + { + Bin* bin = *bvit; + totalInstanceSizeInRow += bin->getSize(); + for (MaukaEngine::UList::const_iterator ulit = bin->InstanceOccurrenceIdsBegin(); + ulit != bin->InstanceOccurrenceIdsEnd(); + ulit++) + { + unsigned instanceId = *ulit; + _subRowInstances.back().push_back(instanceId); + } + } + + DbU::Unit pitch = AllianceFramework::get()->getCellGauge()->getPitch(); + DbU::Unit whiteSpace = subRow->getWidth() - totalInstanceSizeInRow; + DbU::Unit instanceWhiteSpacePitch = (whiteSpace / _subRowInstances.back().size()) / pitch; + DbU::Unit whiteSpaceRemain = whiteSpace + - (instanceWhiteSpacePitch * _subRowInstances.back().size() * pitch); + assert(!(whiteSpaceRemain%pitch)); + + if (instanceWhiteSpacePitch > 0) + { + for (MaukaEngine::UVector::const_iterator uvit = _subRowInstances.back().begin(); + uvit != _subRowInstances.back().end(); + uvit++) + { + _instanceMarginWidth[*uvit] += instanceWhiteSpacePitch * pitch; + } + } + + MaukaEngine::UVector::const_iterator uvit = _subRowInstances.back().begin(); + while (whiteSpaceRemain > 0) + { + _instanceMarginWidth[*uvit++] += pitch; + whiteSpaceRemain -= pitch; + assert(uvit != _subRowInstances.back().end()); + } + + DbU::Unit xPos = subRow->getXMin(); + DbU::Unit yPos = subRow->getYMin(); + for (MaukaEngine::UVector::const_iterator uvit = _subRowInstances.back().begin(); + uvit != _subRowInstances.back().end(); + uvit++) + { + unsigned instanceId = *uvit; + _instanceX[instanceId] = xPos; + _instanceY[instanceId] = yPos; + xPos += _instanceMarginWidth[instanceId]; + } + } + } + } +} + +void BBPlacer::Save() +{ + UpdateSession::open(); + for (unsigned i = 0; i < _subRowInstances.size(); i++) + { + SubRow* subRow = _subRowVector[i]; + bool rowOrientation = subRow->getRow()->getOrientation(); + + for (unsigned j = 0; j < _subRowInstances[i].size(); j++) + { + unsigned instanceId = _subRowInstances[i][j]; + DbU::Unit x = _instanceX[instanceId]; + DbU::Unit y = _instanceY[instanceId]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[instanceId]; + Instance* instance = static_cast(instanceOccurrence.getEntity()); + Transformation::Orientation orientation; + if (rowOrientation) + orientation = Transformation::Orientation::ID; + else + orientation = Transformation::Orientation::MY; + Box masterABox = instance->getMasterCell()->getAbutmentBox(); + Transformation instanceTransformation = getTransformation(masterABox + , x + , y + , orientation); +#if 0 + cerr << masterABox.getXMin() << "," << masterABox.getYMin() + << masterABox.getXMax() << "," << masterABox.getYMax() << endl; + cerr << x << "," << y << endl; + cerr << instanceTransformation << endl; + cerr << "occ transfo : " << instanceOccurrence.getPath().getTransformation() << endl; +#endif + instanceOccurrence.getPath().getTransformation().invert().applyOn(instanceTransformation); + instance->setTransformation(instanceTransformation); + instance->setPlacementStatus(Instance::PlacementStatus::PLACED); + //setPlacementStatusRecursivelyToPlaced(instance); + } + + } + UpdateSession::close(); +} + +void BBPlacer::Plot(ofstream& out) const +{ + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + DbU::Unit x = _instanceX[i]; + DbU::Unit y = _instanceY[i]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[i]; + Instance* instance = static_cast(instanceOccurrence.getEntity()); + Box masterABox = instance->getMasterCell()->getAbutmentBox(); + Box instanceBox = Box( + x, + y, + x + masterABox.getWidth(), + y + masterABox.getHeight()); + out << instanceBox.getXMin()+0.4 << " " << instanceBox.getYMin()+0.4 << endl + << instanceBox.getXMin()+0.4 << " " << instanceBox.getYMax()-0.4 << endl + << instanceBox.getXMax()-0.4 << " " << instanceBox.getYMax()-0.4 << endl + << instanceBox.getXMax()-0.4 << " " << instanceBox.getYMin()+0.4 << endl + << instanceBox.getXMin()+0.4 << " " << instanceBox.getYMin()+0.4 << endl << endl; + } + + out << "EOF" << endl << endl; + + out << "#nets" << endl; + for (unsigned i = 0; i < _mauka->_netInstances.size(); i++) + { + if (_mauka->_hasInitX[i]) + continue; + unsigned nbInstances = 0; + DbU::Unit baryX = 0; + DbU::Unit baryY = 0; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[instanceId]; + Instance* instance = static_cast(instanceOccurrence.getEntity()); + Box masterABox = instance->getMasterCell()->getAbutmentBox(); + ++nbInstances; + baryX += _instanceX[instanceId] + masterABox.getWidth() / 2; + baryY += _instanceY[instanceId] + masterABox.getHeight() / 2; + } + + baryX = baryX / nbInstances; + baryY = baryY / nbInstances; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[instanceId]; + Instance* instance = static_cast(instanceOccurrence.getEntity()); + Box masterABox = instance->getMasterCell()->getAbutmentBox(); + out << baryX << " " << baryY << endl + << _instanceX[instanceId] + masterABox.getWidth() / 2 << " " + << _instanceY[instanceId] + masterABox.getHeight() / 2 << endl << endl; + } + } + out << "EOF" << endl << endl; + + out << "#nets with fixed point" << endl; + for (unsigned i = 0; i < _mauka->_netInstances.size(); i++) + { + if (!_mauka->_hasInitX[i]) + continue; + unsigned nbInstances = 1; + DbU::Unit baryX = 0; + DbU::Unit baryY = 0; + baryX += _mauka->_netInitX[i]; + baryY += _mauka->_netInitY[i]; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[instanceId]; + Instance* instance = static_cast(instanceOccurrence.getEntity()); + Box masterABox = instance->getMasterCell()->getAbutmentBox(); + ++nbInstances; + baryX += _instanceX[instanceId] + masterABox.getWidth() / 2; + baryY += _instanceY[instanceId] + masterABox.getHeight() / 2; + } + + baryX = baryX / nbInstances; + baryY = baryY / nbInstances; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[instanceId]; + Instance* instance = static_cast(instanceOccurrence.getEntity()); + Box masterABox = instance->getMasterCell()->getAbutmentBox(); + out << baryX << " " << baryY << endl + << _instanceX[instanceId] + masterABox.getWidth() / 2 << " " + << _instanceY[instanceId] + masterABox.getHeight() / 2 << endl << endl; + } + out << baryX << " " << baryY << endl + << _mauka->_netInitX[i] << " " + << _mauka->_netInitY[i] << endl << endl; + } + out << "EOF" << endl << endl; +} + +void BBPlacer::Run() +{ + for (unsigned i = 0; i < _subRowInstances.size(); i++) + { + unsigned decal = 2; + unsigned nInstancesToOptimize = 0; + MaukaEngine::UVector::iterator ifirst = _subRowInstances[i].begin(); + MaukaEngine::UVector::iterator ilast = _subRowInstances[i].end(); + while (1) + { + _instanceToOptimize.clear(); + while (1) + { + if (ifirst == ilast) + break; + _instanceToOptimize.push_back(*ifirst++); + ++nInstancesToOptimize; + if (nInstancesToOptimize >= 6) + { + nInstancesToOptimize = 0; + break; + } + } + Optimize(); + + if (ifirst == ilast) + break; + + sort(_subRowInstances[i].begin(), _subRowInstances[i].end(), CompareInstancePosition(this)); + + if ((6 + decal) <= nInstancesToOptimize) + { + ifirst = _subRowInstances[i].begin() + decal; + } + else + { + ifirst = _subRowInstances[i].begin() + decal - 1; + } + + decal += 2; + } + } +} + +bool BBPlacer::Optimize() +{ + bool optimizationResult = false; + const int numberInstances = _instanceToOptimize.size(); + + // Save initial Solution + _bestSolution.reserve(numberInstances); + + for (unsigned i=0; i<_instanceToOptimize.size(); i++) + { + _queue.push_back(_instanceToOptimize[i]); + } + + MaukaEngine::UVector::iterator ifirst = _instanceToOptimize.begin(); + MaukaEngine::UVector::iterator ilast = _instanceToOptimize.end(); + vector::iterator it = _bestSolution.begin(); + while (ifirst != ilast) + *it++ = _instanceX[*ifirst++]; + + // init Best Cost + _bestCost = initCost(); +#ifdef PLACE_DEBUG + cout<<" Orig Cost: "<< _bestCost << endl; + cout<<" Actual Cost: " << CurrentCost() << endl; +#endif + + // init initial Cost + // init Edges + _leftEdge = _instanceX[*_instanceToOptimize.begin()]; + _rightEdge = _instanceX[*_instanceToOptimize.rbegin()] + + _instanceMarginWidth[*_instanceToOptimize.rbegin()]; + + UnplaceAll(); + _cost = initCost(); + + +#ifdef PLACE_DEBUG + cout << " init Cost: " << _cost << endl; +#endif + + _loopVect.reserve(numberInstances + 2); + for (int id = 0; id < numberInstances + 2; id++) + _loopVect.push_back(0); + _loopVect[numberInstances] = numberInstances; + _loopVect[numberInstances + 1] = numberInstances + 1; + + _stack.reserve(numberInstances); + + _idx = numberInstances - 1; + + unsigned numAdds = 0; + + + while(_idx < numberInstances) + { + addIns(); + numAdds++; + + if(_loopVect[_idx] == 0 || _cost >= _bestCost) + { + + _loopVect[_idx] = 0; //force a bound + + if(_cost < _bestCost) //got here if: + // new best complete soln (curWL < best) + // bounded partial soln (curWL > best) + // so there is no need to additionally + // check to ensure this is a complete soln + { + optimizationResult = true; + _bestCost = _cost; +#ifdef PLACE_DEBUG + cout<<" New Best: "<< _cost <<" found after "<< numAdds << endl; + cout << "Cost recalculated: " << initCost() << endl; + cout << "Actual Cost: " << CurrentCost() << endl; +#endif + + ifirst = _instanceToOptimize.begin(); + it = _bestSolution.begin(); + while (ifirst != ilast) + { + *it++ = _instanceX[*ifirst++]; + } +#if 0 + Save(); + for_each_view(view, _mauka->getCell()->getViews()) + { + if (CEditor* editor = dynamic_cast(view)) + { + editor->Stop("coucou"); + break; + } + end_for; + } +#endif + } + + while(_loopVect[_idx] == 0) + { + if(_idx < numberInstances) + removeIns(); + _loopVect[++_idx]--; + } + } + --_idx; + } + ifirst = _instanceToOptimize.begin(); + it = _bestSolution.begin(); + while (ifirst != ilast) + _instanceX[*ifirst++] = *it++; + + PlaceAll(); + _bestSolution.clear(); +#ifdef PLACE_DEBUG + cout<<" Total add Operations: "<< numAdds<< endl; + cout<<" Final solution has cost: "<< _bestCost << endl << endl; +#endif + _loopVect.clear(); + _queue.clear(); + _stack.clear(); + return optimizationResult; +} + +void BBPlacer::addIns() +{ + _stack.push_back(_queue.front()); + _queue.pop_front(); + _loopVect[_idx] = _idx; + + unsigned instanceId = _stack.back(); + //cerr << "adding: " << _instanceOccurrenceVector[instanceId] << " " ; + + if(_idx%2) + { + _instanceX[instanceId] = _rightEdge - _instanceMarginWidth[instanceId]; + _rightEdge -= _instanceMarginWidth[instanceId]; + } + else + { + _instanceX[instanceId] = _leftEdge; + _leftEdge += _instanceMarginWidth[instanceId]; + } + //cerr << _instanceX[instanceId] << " "; + _instancePlaced[instanceId] = true; + _cost += UpdateInstanceCost(instanceId); + //cerr << _cost << endl; + //cerr << "verify " << CurrentCost() << endl; +} + +void BBPlacer::removeIns() +{ + unsigned instanceId = _stack.back(); + //cerr << "Removing: " << _instanceOccurrenceVector[instanceId] << " " ; + + _queue.push_back(instanceId); + _stack.pop_back(); + if(_idx%2) + _rightEdge += _instanceMarginWidth[instanceId]; + else + _leftEdge -= _instanceMarginWidth[instanceId]; + _instancePlaced[instanceId] = false; + _cost += UpdateInstanceCost(instanceId); + //cerr << _cost << endl; +} + +void BBPlacer::PlaceAll() +{ + for (MaukaEngine::UVector::iterator uvit = _instanceToOptimize.begin(); + uvit != _instanceToOptimize.end(); + uvit++) + { + _instancePlaced[*uvit] = true; + } +} + +void BBPlacer::UnplaceAll() +{ + for (MaukaEngine::UVector::iterator uvit = _instanceToOptimize.begin(); + uvit != _instanceToOptimize.end(); + uvit++) + { + _instancePlaced[*uvit] = false; + } +} + +double BBPlacer::initCost() +{ + ++_costFlag; + double cost = 0.0; + for (MaukaEngine::UVector::iterator uvit = _instanceToOptimize.begin(); + uvit != _instanceToOptimize.end(); + uvit++) + { + cost += initInstanceCost(*uvit); + } + return cost; +} + +double BBPlacer::CurrentCost() +{ + ++_costFlag; + double cost = 0.0; + for (MaukaEngine::UVector::iterator uvit = _instanceToOptimize.begin(); + uvit != _instanceToOptimize.end(); + uvit++) + cost += CurrentInstanceCost(*uvit); + return cost; +} + +double BBPlacer::UpdateInstanceCost(unsigned instanceid) +{ + double deltaCost = 0.0; + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_instanceNets[instanceid].begin(); + uvit != _mauka->_instanceNets[instanceid].end(); + uvit++) + { + deltaCost += UpdateNetCost(*uvit); + } + return deltaCost; +} + +double BBPlacer::UpdateNetCost(unsigned netid) +{ + Box& netBBox = _netBBoxes[netid][_netFlags[netid]]; + double& netCost = _netCosts[netid][_netFlags[netid]]; + + double initCost = netCost; + netBBox.makeEmpty(); + if (_mauka->_hasInitX[netid]) + netBBox.merge(_mauka->_netInitX[netid], netBBox.getYMin()); + if (_mauka->_hasInitY[netid]) + netBBox.merge(netBBox.getXMin(), _mauka->_netInitY[netid]); + + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_netInstances[netid].begin(); + uvit != _mauka->_netInstances[netid].end(); + uvit++) + { + if (_instancePlaced[*uvit]) + { + //FIXME + netBBox.merge(Point(_instanceX[*uvit], _instanceY[*uvit])); + } + } + netCost = computeCost(netBBox); + return (netCost - initCost); +} + +double BBPlacer::initInstanceCost(unsigned instanceid) +{ + double cost = 0.0; + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_instanceNets[instanceid].begin(); + uvit != _mauka->_instanceNets[instanceid].end(); + uvit++) + { + computeNetBBox(*uvit); + //SaveNetTempValue(*uvit); + cost += CurrentNetCost(*uvit); + } + return cost; +} + +double BBPlacer::CurrentInstanceCost(unsigned instanceid) +{ + double cost = 0.0; + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_instanceNets[instanceid].begin(); + uvit != _mauka->_instanceNets[instanceid].end(); + uvit++) + { + cost += CurrentNetCost(*uvit); + } + return cost; +} + +void BBPlacer::SaveNetTempValue(unsigned netid) +{ + _netFlags[netid] = !_netFlags[netid]; +} + +void BBPlacer::computeNetBBox(unsigned netid) +{ + //cerr << _netVector[netid] << endl; + //Box& netTmpBBox = _netBBoxes[netid][!_netFlags[netid]]; + Box& netTmpBBox = _netBBoxes[netid][_netFlags[netid]]; + //FIXME + netTmpBBox.makeEmpty(); + if (_mauka->_hasInitX[netid]) + netTmpBBox.merge(_mauka->_netInitX[netid], netTmpBBox.getYMin()); + if (_mauka->_hasInitY[netid]) + netTmpBBox.merge(netTmpBBox.getXMin(), _mauka->_netInitY[netid]); + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_netInstances[netid].begin(); + uvit != _mauka->_netInstances[netid].end(); + uvit++) + { + if (_instancePlaced[*uvit]) + { + //FIXME + netTmpBBox.merge(Point(_instanceX[*uvit], _instanceY[*uvit])); + //cerr << netTmpBBox << endl; + } + } + _netCosts[netid][_netFlags[netid]] = computeCost(netTmpBBox); + //_netCosts[netid][!_netFlags[netid]] = computeCost(netTmpBBox); + //cerr << _netCosts[netid][!_netFlags[netid]] << endl; +} + +double BBPlacer::computeCost(const Box& box) const +{ + if (!box.isEmpty()) + return DbU::getLambda(box.getYMax() - box.getYMin() + box.getXMax() - box.getXMin()); + else + return 0.0; +} + +double BBPlacer::CurrentNetCost(unsigned netid) +{ + if (_netCurrCostMark[netid] != _costFlag) + { + _netCurrCostMark[netid] = _costFlag; + return _netCosts[netid][_netFlags[netid]]; + } + return 0; +} + + +} diff --git a/mauka/src/BBPlacer.cpp.noRefactor b/mauka/src/BBPlacer.cpp.noRefactor new file mode 100644 index 00000000..0d2148d6 --- /dev/null +++ b/mauka/src/BBPlacer.cpp.noRefactor @@ -0,0 +1,732 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// inspired by Andrew Caldwell's BranchSmallPlacer +// Authors-Tag + +/************************************************************************** +*** +*** Copyright (c) 1995-2000 Regents of the University of California, +*** Andrew E. Caldwell, Andrew B. Kahng and Igor L. Markov +*** Copyright (c) 2000-2002 Regents of the University of Michigan, +*** Saurabh N. Adya and Igor L. Markov +*** +*** Contact author(s): abk@cs.ucsd.edu, imarkov@umich.edu +*** Original Affiliation: UCLA, Computer Science Department, +*** Los Angeles, CA 90095-1596 USA +*** +*** Permission is hereby granted, free of charge, to any person obtaining +*** a copy of this software and associated documentation files (the +*** "Software"), to deal in the Software without restriction, including +*** without limitation +*** the rights to use, copy, modify, merge, publish, distribute, sublicense, +*** and/or sell copies of the Software, and to permit persons to whom the +*** Software is furnished to do so, subject to the following conditions: +*** +*** The above copyright notice and this permission notice shall be included +*** in all copies or substantial portions of the Software. +*** +*** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +*** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +*** OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +*** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +*** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +*** OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +*** THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*** +*** +***************************************************************************/ + +#include "UpdateSession.h" +#include "Net.h" +USING_NAMESPACE_HURRICANE +#include "CDataBase.h" +#include "CEditor.h" +#include "CToolBox.h" +using namespace CRL; +#include "Nimbus.h" +using namespace NIMBUS; +#include "Mauka.h" +#include "Surface.h" +#include "Row.h" +#include "SubRow.h" +#include "Bin.h" + +#include "BBPlacer.h" + +namespace MAUKA { + +namespace { + +class CompareInstancePosition +{ + private: BBPlacer* _bbPlacer; + + public: CompareInstancePosition(BBPlacer* bbplacer) + : _bbPlacer(bbplacer) + {} + public: bool operator()(unsigned id1, unsigned id2) const + { + return _bbPlacer->GetInstanceIdX(id1) < _bbPlacer->GetInstanceIdX(id2); + } +}; + +} + +//#define PLACE_DEBUG 1 + +BBPlacer::BBPlacer(Mauka* mauka) + : _mauka(mauka) + , _subRowVector() + , _subRowInstances() + , _instanceX() + , _instanceY() + , _instancePlaced() + , _netVector() + , _netBBoxes() + , _netCosts() + , _netCurrCostMark() + , _netFlags() + , _instanceToOptimize() + , _leftEdge(0) + , _rightEdge(0) + , _oldCost(0.0) + , _cost(0.0) + , _bestCost(0.0) + , _costFlag(0) + , _queue() + , _stack() + , _loopVect() + , _bestSolution() + , _idx(0) +{ + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + _instanceMarginWidth.push_back(_mauka->_instanceWidths[i]); + _instanceX.push_back(0); + _instanceY.push_back(0); + _instancePlaced.push_back(true); + } + + for (unsigned netid = 0; netid < _mauka->_nets.size(); netid++) + { + vector bboxes(2); + _netBBoxes.push_back(bboxes); + vector costs(2); + _netCosts.push_back(costs); + _netFlags.push_back(0); + _netCurrCostMark.push_back(0); + } + + + Surface::RowVector& rowVector = _mauka->_surface->_rowVector; + + for (Surface::RowVector::iterator rvit = rowVector.begin(); + rvit != rowVector.end(); + rvit++) + { + Row::SubRowVector& subRowVector = (*rvit)->_subRowVector; + for (Row::SubRowVector::iterator srvit = subRowVector.begin(); + srvit != subRowVector.end(); + srvit++) + { + SubRow* subRow = *srvit; + if (subRow->GetSize() > 0) + { + _subRowVector.push_back(subRow); + _subRowInstances.push_back(Mauka::UVector()); + Unit totalInstanceSizeInRow = 0; + for (SubRow::BinVector::iterator bvit = subRow->_binVector.begin(); + bvit != subRow->_binVector.end(); + bvit++) + { + Bin* bin = *bvit; + totalInstanceSizeInRow += bin->GetSize(); + for (Mauka::UList::const_iterator ulit = bin->InstanceOccurrenceIdsBegin(); + ulit != bin->InstanceOccurrenceIdsEnd(); + ulit++) + { + unsigned instanceId = *ulit; + _subRowInstances.back().push_back(instanceId); + } + } + + Unit pitch = GetCDataBase()->GetDefaultCGPitch(); + Unit whiteSpace = subRow->GetWidth() - totalInstanceSizeInRow; + Unit instanceWhiteSpacePitch = (whiteSpace / _subRowInstances.back().size()) / pitch; + Unit whiteSpaceRemain = whiteSpace + - (instanceWhiteSpacePitch * _subRowInstances.back().size() * pitch); + assert(!(whiteSpaceRemain%pitch)); + + if (instanceWhiteSpacePitch > 0) + { + for (Mauka::UVector::const_iterator uvit = _subRowInstances.back().begin(); + uvit != _subRowInstances.back().end(); + uvit++) + { + _instanceMarginWidth[*uvit] += instanceWhiteSpacePitch * pitch; + } + } + + Mauka::UVector::const_iterator uvit = _subRowInstances.back().begin(); + while (whiteSpaceRemain > 0) + { + _instanceMarginWidth[*uvit++] += pitch; + whiteSpaceRemain -= pitch; + assert(uvit != _subRowInstances.back().end()); + } + + Unit xPos = subRow->GetXMin(); + Unit yPos = subRow->GetYMin(); + for (Mauka::UVector::const_iterator uvit = _subRowInstances.back().begin(); + uvit != _subRowInstances.back().end(); + uvit++) + { + unsigned instanceId = *uvit; + _instanceX[instanceId] = xPos; + _instanceY[instanceId] = yPos; + xPos += _instanceMarginWidth[instanceId]; + } + } + } + } +} + +void BBPlacer::Save() +{ + OpenUpdateSession(); + for (unsigned i = 0; i < _subRowInstances.size(); i++) + { + SubRow* subRow = _subRowVector[i]; + bool rowOrientation = subRow->GetRow()->GetOrientation(); + + for (unsigned j = 0; j < _subRowInstances[i].size(); j++) + { + unsigned instanceId = _subRowInstances[i][j]; + Unit x = _instanceX[instanceId]; + Unit y = _instanceY[instanceId]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[instanceId]; + Instance* instance = static_cast(instanceOccurrence.GetEntity()); + Transformation::Orientation orientation; + if (rowOrientation) + orientation = Transformation::Orientation::ID; + else + orientation = Transformation::Orientation::MY; + Box masterABox = instance->GetMasterCell()->GetAbutmentBox(); + Transformation instanceTransformation = GetTransformation(masterABox + , x + , y + , orientation); +#if 0 + cerr << masterABox.GetXMin() << "," << masterABox.GetYMin() + << masterABox.GetXMax() << "," << masterABox.GetYMax() << endl; + cerr << x << "," << y << endl; + cerr << instanceTransformation << endl; + cerr << "occ transfo : " << instanceOccurrence.GetPath().GetTransformation() << endl; +#endif + instanceOccurrence.GetPath().GetTransformation().Invert().ApplyOn(instanceTransformation); + instance->SetTransformation(instanceTransformation); + instance->SetPlacementStatus(Instance::PlacementStatus::PLACED); + //SetPlacementStatusRecursivelyToPlaced(instance); + } + + } + CloseUpdateSession(); +} + +void BBPlacer::Plot(ofstream& out) const +{ + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + Unit x = _instanceX[i]; + Unit y = _instanceY[i]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[i]; + Instance* instance = static_cast(instanceOccurrence.GetEntity()); + Box masterABox = instance->GetMasterCell()->GetAbutmentBox(); + Box instanceBox = Box( + x, + y, + x + masterABox.GetWidth(), + y + masterABox.GetHeight()); + out << instanceBox.GetXMin()+0.4 << " " << instanceBox.GetYMin()+0.4 << endl + << instanceBox.GetXMin()+0.4 << " " << instanceBox.GetYMax()-0.4 << endl + << instanceBox.GetXMax()-0.4 << " " << instanceBox.GetYMax()-0.4 << endl + << instanceBox.GetXMax()-0.4 << " " << instanceBox.GetYMin()+0.4 << endl + << instanceBox.GetXMin()+0.4 << " " << instanceBox.GetYMin()+0.4 << endl << endl; + } + + out << "EOF" << endl << endl; + + out << "#nets" << endl; + for (unsigned i = 0; i < _mauka->_netInstances.size(); i++) + { + if (_mauka->_hasInitX[i]) + continue; + unsigned nbInstances = 0; + Unit baryX = 0; + Unit baryY = 0; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[instanceId]; + Instance* instance = static_cast(instanceOccurrence.GetEntity()); + Box masterABox = instance->GetMasterCell()->GetAbutmentBox(); + ++nbInstances; + baryX += _instanceX[instanceId] + masterABox.GetWidth() / 2; + baryY += _instanceY[instanceId] + masterABox.GetHeight() / 2; + } + + baryX = baryX / nbInstances; + baryY = baryY / nbInstances; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[instanceId]; + Instance* instance = static_cast(instanceOccurrence.GetEntity()); + Box masterABox = instance->GetMasterCell()->GetAbutmentBox(); + out << baryX << " " << baryY << endl + << _instanceX[instanceId] + masterABox.GetWidth() / 2 << " " + << _instanceY[instanceId] + masterABox.GetHeight() / 2 << endl << endl; + } + } + out << "EOF" << endl << endl; + + out << "#nets with fixed point" << endl; + for (unsigned i = 0; i < _mauka->_netInstances.size(); i++) + { + if (!_mauka->_hasInitX[i]) + continue; + unsigned nbInstances = 1; + Unit baryX = 0; + Unit baryY = 0; + baryX += _mauka->_netInitX[i]; + baryY += _mauka->_netInitY[i]; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[instanceId]; + Instance* instance = static_cast(instanceOccurrence.GetEntity()); + Box masterABox = instance->GetMasterCell()->GetAbutmentBox(); + ++nbInstances; + baryX += _instanceX[instanceId] + masterABox.GetWidth() / 2; + baryY += _instanceY[instanceId] + masterABox.GetHeight() / 2; + } + + baryX = baryX / nbInstances; + baryY = baryY / nbInstances; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[instanceId]; + Instance* instance = static_cast(instanceOccurrence.GetEntity()); + Box masterABox = instance->GetMasterCell()->GetAbutmentBox(); + out << baryX << " " << baryY << endl + << _instanceX[instanceId] + masterABox.GetWidth() / 2 << " " + << _instanceY[instanceId] + masterABox.GetHeight() / 2 << endl << endl; + } + out << baryX << " " << baryY << endl + << _mauka->_netInitX[i] << " " + << _mauka->_netInitY[i] << endl << endl; + } + out << "EOF" << endl << endl; +} + +void BBPlacer::Run() +{ + for (unsigned i = 0; i < _subRowInstances.size(); i++) + { + unsigned decal = 2; + unsigned nInstancesToOptimize = 0; + Mauka::UVector::iterator ifirst = _subRowInstances[i].begin(); + Mauka::UVector::iterator ilast = _subRowInstances[i].end(); + while (1) + { + _instanceToOptimize.clear(); + while (1) + { + if (ifirst == ilast) + break; + _instanceToOptimize.push_back(*ifirst++); + ++nInstancesToOptimize; + if (nInstancesToOptimize >= 6) + { + nInstancesToOptimize = 0; + break; + } + } + Optimize(); + + if (ifirst == ilast) + break; + + sort(_subRowInstances[i].begin(), _subRowInstances[i].end(), CompareInstancePosition(this)); + + if ((6 + decal) <= nInstancesToOptimize) + { + ifirst = _subRowInstances[i].begin() + decal; + } + else + { + ifirst = _subRowInstances[i].begin() + decal - 1; + } + + decal += 2; + } + } +} + +bool BBPlacer::Optimize() +{ + bool optimizationResult = false; + const int numberInstances = _instanceToOptimize.size(); + + // Save Initial Solution + _bestSolution.reserve(numberInstances); + + for (unsigned i=0; i<_instanceToOptimize.size(); i++) + { + _queue.push_back(_instanceToOptimize[i]); + } + + Mauka::UVector::iterator ifirst = _instanceToOptimize.begin(); + Mauka::UVector::iterator ilast = _instanceToOptimize.end(); + vector::iterator it = _bestSolution.begin(); + while (ifirst != ilast) + *it++ = _instanceX[*ifirst++]; + + // Init Best Cost + _bestCost = InitCost(); +#ifdef PLACE_DEBUG + cout<<" Orig Cost: "<< _bestCost << endl; + cout<<" Actual Cost: " << CurrentCost() << endl; +#endif + + // Init Initial Cost + // Init Edges + _leftEdge = _instanceX[*_instanceToOptimize.begin()]; + _rightEdge = _instanceX[*_instanceToOptimize.rbegin()] + + _instanceMarginWidth[*_instanceToOptimize.rbegin()]; + + UnplaceAll(); + _cost = InitCost(); + + +#ifdef PLACE_DEBUG + cout << " Init Cost: " << _cost << endl; +#endif + + _loopVect.reserve(numberInstances + 2); + for (int id = 0; id < numberInstances + 2; id++) + _loopVect.push_back(0); + _loopVect[numberInstances] = numberInstances; + _loopVect[numberInstances + 1] = numberInstances + 1; + + _stack.reserve(numberInstances); + + _idx = numberInstances - 1; + + unsigned numAdds = 0; + + + while(_idx < numberInstances) + { + AddIns(); + numAdds++; + + if(_loopVect[_idx] == 0 || _cost >= _bestCost) + { + + _loopVect[_idx] = 0; //force a bound + + if(_cost < _bestCost) //got here if: + // new best complete soln (curWL < best) + // bounded partial soln (curWL > best) + // so there is no need to additionally + // check to ensure this is a complete soln + { + optimizationResult = true; + _bestCost = _cost; +#ifdef PLACE_DEBUG + cout<<" New Best: "<< _cost <<" found after "<< numAdds << endl; + cout << "Cost recalculated: " << InitCost() << endl; + cout << "Actual Cost: " << CurrentCost() << endl; +#endif + + ifirst = _instanceToOptimize.begin(); + it = _bestSolution.begin(); + while (ifirst != ilast) + { + *it++ = _instanceX[*ifirst++]; + } +#if 0 + Save(); + for_each_view(view, _mauka->GetCell()->GetViews()) + { + if (CEditor* editor = dynamic_cast(view)) + { + editor->Stop("coucou"); + break; + } + end_for; + } +#endif + } + + while(_loopVect[_idx] == 0) + { + if(_idx < numberInstances) + RemoveIns(); + _loopVect[++_idx]--; + } + } + --_idx; + } + ifirst = _instanceToOptimize.begin(); + it = _bestSolution.begin(); + while (ifirst != ilast) + _instanceX[*ifirst++] = *it++; + + PlaceAll(); + _bestSolution.clear(); +#ifdef PLACE_DEBUG + cout<<" Total Add Operations: "<< numAdds<< endl; + cout<<" Final solution has cost: "<< _bestCost << endl << endl; +#endif + _loopVect.clear(); + _queue.clear(); + _stack.clear(); + return optimizationResult; +} + +void BBPlacer::AddIns() +{ + _stack.push_back(_queue.front()); + _queue.pop_front(); + _loopVect[_idx] = _idx; + + unsigned instanceId = _stack.back(); + //cerr << "Adding: " << _instanceOccurrenceVector[instanceId] << " " ; + + if(_idx%2) + { + _instanceX[instanceId] = _rightEdge - _instanceMarginWidth[instanceId]; + _rightEdge -= _instanceMarginWidth[instanceId]; + } + else + { + _instanceX[instanceId] = _leftEdge; + _leftEdge += _instanceMarginWidth[instanceId]; + } + //cerr << _instanceX[instanceId] << " "; + _instancePlaced[instanceId] = true; + _cost += UpdateInstanceCost(instanceId); + //cerr << _cost << endl; + //cerr << "verify " << CurrentCost() << endl; +} + +void BBPlacer::RemoveIns() +{ + unsigned instanceId = _stack.back(); + //cerr << "Removing: " << _instanceOccurrenceVector[instanceId] << " " ; + + _queue.push_back(instanceId); + _stack.pop_back(); + if(_idx%2) + _rightEdge += _instanceMarginWidth[instanceId]; + else + _leftEdge -= _instanceMarginWidth[instanceId]; + _instancePlaced[instanceId] = false; + _cost += UpdateInstanceCost(instanceId); + //cerr << _cost << endl; +} + +void BBPlacer::PlaceAll() +{ + for (Mauka::UVector::iterator uvit = _instanceToOptimize.begin(); + uvit != _instanceToOptimize.end(); + uvit++) + { + _instancePlaced[*uvit] = true; + } +} + +void BBPlacer::UnplaceAll() +{ + for (Mauka::UVector::iterator uvit = _instanceToOptimize.begin(); + uvit != _instanceToOptimize.end(); + uvit++) + { + _instancePlaced[*uvit] = false; + } +} + +double BBPlacer::InitCost() +{ + ++_costFlag; + double cost = 0.0; + for (Mauka::UVector::iterator uvit = _instanceToOptimize.begin(); + uvit != _instanceToOptimize.end(); + uvit++) + { + cost += InitInstanceCost(*uvit); + } + return cost; +} + +double BBPlacer::CurrentCost() +{ + ++_costFlag; + double cost = 0.0; + for (Mauka::UVector::iterator uvit = _instanceToOptimize.begin(); + uvit != _instanceToOptimize.end(); + uvit++) + cost += CurrentInstanceCost(*uvit); + return cost; +} + +double BBPlacer::UpdateInstanceCost(unsigned instanceid) +{ + double deltaCost = 0.0; + for (Mauka::UVector::const_iterator uvit = _mauka->_instanceNets[instanceid].begin(); + uvit != _mauka->_instanceNets[instanceid].end(); + uvit++) + { + deltaCost += UpdateNetCost(*uvit); + } + return deltaCost; +} + +double BBPlacer::UpdateNetCost(unsigned netid) +{ + Box& netBBox = _netBBoxes[netid][_netFlags[netid]]; + double& netCost = _netCosts[netid][_netFlags[netid]]; + + double initCost = netCost; + netBBox.MakeEmpty(); + if (_mauka->_hasInitX[netid]) + netBBox.Merge(_mauka->_netInitX[netid], netBBox.GetYMin()); + if (_mauka->_hasInitY[netid]) + netBBox.Merge(netBBox.GetXMin(), _mauka->_netInitY[netid]); + + for (Mauka::UVector::const_iterator uvit = _mauka->_netInstances[netid].begin(); + uvit != _mauka->_netInstances[netid].end(); + uvit++) + { + if (_instancePlaced[*uvit]) + { + //FIXME + netBBox.Merge(Point(_instanceX[*uvit], _instanceY[*uvit])); + } + } + netCost = ComputeCost(netBBox); + return (netCost - initCost); +} + +double BBPlacer::InitInstanceCost(unsigned instanceid) +{ + double cost = 0.0; + for (Mauka::UVector::const_iterator uvit = _mauka->_instanceNets[instanceid].begin(); + uvit != _mauka->_instanceNets[instanceid].end(); + uvit++) + { + ComputeNetBBox(*uvit); + //SaveNetTempValue(*uvit); + cost += CurrentNetCost(*uvit); + } + return cost; +} + +double BBPlacer::CurrentInstanceCost(unsigned instanceid) +{ + double cost = 0.0; + for (Mauka::UVector::const_iterator uvit = _mauka->_instanceNets[instanceid].begin(); + uvit != _mauka->_instanceNets[instanceid].end(); + uvit++) + { + cost += CurrentNetCost(*uvit); + } + return cost; +} + +void BBPlacer::SaveNetTempValue(unsigned netid) +{ + _netFlags[netid] = !_netFlags[netid]; +} + +void BBPlacer::ComputeNetBBox(unsigned netid) +{ + //cerr << _netVector[netid] << endl; + //Box& netTmpBBox = _netBBoxes[netid][!_netFlags[netid]]; + Box& netTmpBBox = _netBBoxes[netid][_netFlags[netid]]; + //FIXME + netTmpBBox.MakeEmpty(); + if (_mauka->_hasInitX[netid]) + netTmpBBox.Merge(_mauka->_netInitX[netid], netTmpBBox.GetYMin()); + if (_mauka->_hasInitY[netid]) + netTmpBBox.Merge(netTmpBBox.GetXMin(), _mauka->_netInitY[netid]); + for (Mauka::UVector::const_iterator uvit = _mauka->_netInstances[netid].begin(); + uvit != _mauka->_netInstances[netid].end(); + uvit++) + { + if (_instancePlaced[*uvit]) + { + //FIXME + netTmpBBox.Merge(Point(_instanceX[*uvit], _instanceY[*uvit])); + //cerr << netTmpBBox << endl; + } + } + _netCosts[netid][_netFlags[netid]] = ComputeCost(netTmpBBox); + //_netCosts[netid][!_netFlags[netid]] = ComputeCost(netTmpBBox); + //cerr << _netCosts[netid][!_netFlags[netid]] << endl; +} + +double BBPlacer::ComputeCost(const Box& box) const +{ + if (!box.IsEmpty()) + return GetValue(box.GetYMax() - box.GetYMin() + box.GetXMax() - box.GetXMin()); + else + return 0.0; +} + +double BBPlacer::CurrentNetCost(unsigned netid) +{ + if (_netCurrCostMark[netid] != _costFlag) + { + _netCurrCostMark[netid] = _costFlag; + return _netCosts[netid][_netFlags[netid]]; + } + return 0; +} + + +} diff --git a/mauka/src/Bin.cpp b/mauka/src/Bin.cpp new file mode 100644 index 00000000..b9d34e4b --- /dev/null +++ b/mauka/src/Bin.cpp @@ -0,0 +1,207 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#include "hurricane/Error.h" +#include "mauka/SubRow.h" +#include "mauka/Bin.h" +#include "mauka/Surface.h" +#include "mauka/SimAnnealingPlacer.h" + +namespace Mauka { + +using namespace std; +using Hurricane::Error; + +const Name Bin::_goName = "Mauka::Bin"; + +Bin::Bin(Cell* cell, SubRow* subrow, const Box& box) + : Inherit(cell, box) + , _subRow(subrow) + , _mauka(NULL) + , _instanceOccurrenceIds() + , _size(0) + , _capa(0) + , _sourceHits(0) + , _targetHits(0) +{} + +Bin* Bin::create(Cell* cell, SubRow* subrow, const Box& box) +{ + Bin* bin = new Bin(cell, subrow, box); + bin->_postCreate(); + return bin; +} + +void Bin::_postCreate() +{ + if (!_subRow) + throw Error("Empty SubRow for Bin"); + _mauka = _subRow->getSurface()->getMauka(); + if (!_mauka) + throw Error("Empty SimAnnealingPlacer for Bin"); + _capa = DbU::lambda(DbU::getLambda(getWidth()) * (1.0 - _subRow->getSurface()->getMargin())); + Inherit::_postCreate(); +} + +void Bin::_computeCapacity(double margin) +{ + _capa = DbU::lambda(DbU::getLambda(getWidth()) * (1.0 - margin)); +} + +const Name& Bin::getStaticName () +{ + return _goName; +} + +const Name& Bin::getName () const +{ + return _goName; +} + +Cell* Bin::getCell() const +{ + return _subRow->getCell(); +} + +void Bin::addInstance(unsigned instanceid) +{ + _instanceOccurrenceIds.push_back(instanceid); + DbU::Unit insWidth = _mauka->_instanceWidths[instanceid]; + _AddSize(insWidth); + _mauka->_simAnnealingPlacer->_instanceBins[instanceid] = this; +} + +void Bin::_AddSize(DbU::Unit value) +{ + _size += value; + _subRow->_AddSize(value); +} + +void Bin::removeInstance(unsigned instanceid) +{ + _instanceOccurrenceIds.remove(instanceid); + DbU::Unit insWidth = _mauka->_instanceWidths[instanceid]; + _AddSize(-insWidth); + _mauka->_simAnnealingPlacer->_instanceBins[instanceid] = NULL; +} + +void Bin::removeBackInstance(unsigned instanceid) +{ + assert(_instanceOccurrenceIds.back() == instanceid); + _instanceOccurrenceIds.pop_back(); + DbU::Unit insWidth = _mauka->_instanceWidths[instanceid]; + _AddSize(-insWidth); + _mauka->_simAnnealingPlacer->_instanceBins[instanceid] = NULL; +} + +void Bin::removeFrontInstance(unsigned instanceid) +{ + assert(_instanceOccurrenceIds.front() == instanceid); + _instanceOccurrenceIds.pop_front(); + DbU::Unit insWidth = _mauka->_instanceWidths[instanceid]; + _AddSize(-insWidth); + _mauka->_simAnnealingPlacer->_instanceBins[instanceid] = NULL; +} + +bool Bin::TryAddInstance(unsigned instanceid) +{ + DbU::Unit insWidth = _mauka->_instanceWidths[instanceid]; + if (getCapaVsSize() < insWidth) + return false; + addInstance(instanceid); + return true; +} + +bool Bin::UnderOccupied() const +{ + // On Considère pour l'instant qu'un Bin est sous-occupé + // et donc qu'il est intéressant d'y déplacer une instance + // si il a 20% de vide par rapport à son remplissage idéal + + return ((_instanceOccurrenceIds.size() == 0) + || (_size <= (1.0 - _subRow->getSurface()->getMargin() - 0.2) * _capa)); +} + +double Bin::getCost() const +{ + return abs(DbU::getLambda(_size - _capa)); +} + +void Bin::DisplayHits() const +{ + cout << this << " nb source hits: " << _sourceHits << endl; + cout << this << " nb target hits: " << _targetHits << endl; +} + +void Bin::incrementSourceHits() +{ + ++_sourceHits; +} + +void Bin::incrementTargetHits() +{ + ++_targetHits; +} + +void Bin::PlotStats(ofstream& out) const +{ + unsigned x = (unsigned)(DbU::getLambda(getXMin())) + (unsigned)(DbU::getLambda(getXMax() - getXMin())) / 2; + //unsigned decal = (unsigned)(DbU::getLambda(getYMax() - getYMin())) / 4; + //unsigned y = (unsigned)(DbU::getLambda(getYMin())); + unsigned y = (unsigned)(DbU::getLambda(getYMin())) + (unsigned)(DbU::getLambda(getYMax() - getYMin())) / 2; + unsigned totalMoves = _mauka->_simAnnealingPlacer->getMoves(); + if (totalMoves) + { + //double sourcePercent = (_sourceHits * 100.0) / totalMoves; + double targetPercent = (_targetHits * 100.0) / totalMoves; + out << "set label \"" + << targetPercent << "%\" at " << x << "," << y << " center" + << endl; + //out << "set label \"" + // << targetPercent << "%\" at " << x << "," << y + decal << " center" + // << endl; + } +} + +void Bin::Plot(ofstream& out) const +{ + out << DbU::getLambda(getXMin()) + 0.3 << " " << DbU::getLambda(getYMin()) + 0.3 << endl + << DbU::getLambda(getXMin()) + 0.3 << " " << DbU::getLambda(getYMax()) - 0.3 << endl + << DbU::getLambda(getXMax()) - 0.3 << " " << DbU::getLambda(getYMax()) - 0.3 << endl + << DbU::getLambda(getXMax()) - 0.3 << " " << DbU::getLambda(getYMin()) + 0.3 << endl + << DbU::getLambda(getXMin()) + 0.3 << " " << DbU::getLambda(getYMin()) + 0.3 << endl << endl; +} + +} // End of Mauka namespace. diff --git a/mauka/src/Bin.cpp.noRefactor b/mauka/src/Bin.cpp.noRefactor new file mode 100644 index 00000000..ed81dffc --- /dev/null +++ b/mauka/src/Bin.cpp.noRefactor @@ -0,0 +1,191 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#include "SubRow.h" +#include "Bin.h" +#include "Surface.h" +#include "SimAnnealingPlacer.h" + +namespace MAUKA { + +Bin::Bin(const Cell* cell, SubRow* subrow, const Box& box) + : Inherit(cell, box) + , _subRow(subrow) + , _mauka(NULL) + , _instanceOccurrenceIds() + , _size(0) + , _capa(0) + , _sourceHits(0) + , _targetHits(0) +{} + +Bin* Bin::Create(const Cell* cell, SubRow* subrow, const Box& box) +{ + Bin* bin = new Bin(cell, subrow, box); + bin->_PostCreate(); + return bin; +} + +void Bin::_PostCreate() +{ + if (!_subRow) + throw Error("Empty SubRow for Bin"); + _mauka = _subRow->GetSurface()->GetMauka(); + if (!_mauka) + throw Error("Empty SimAnnealingPlacer for Bin"); + _capa = GetUnit(GetValue(GetWidth()) * (1.0 - _subRow->GetSurface()->GetMargin())); + Inherit::_PostCreate(); +} + +void Bin::_ComputeCapacity(double margin) +{ + _capa = GetUnit(GetValue(GetWidth()) * (1.0 - margin)); +} + +Cell* Bin::GetCell() const +{ + return _subRow->GetCell(); +} + +void Bin::AddInstance(unsigned instanceid) +{ + _instanceOccurrenceIds.push_back(instanceid); + Unit insWidth = _mauka->_instanceWidths[instanceid]; + _AddSize(insWidth); + _mauka->_simAnnealingPlacer->_instanceBins[instanceid] = this; +} + +void Bin::_AddSize(Unit value) +{ + _size += value; + _subRow->_AddSize(value); +} + +void Bin::RemoveInstance(unsigned instanceid) +{ + _instanceOccurrenceIds.remove(instanceid); + Unit insWidth = _mauka->_instanceWidths[instanceid]; + _AddSize(-insWidth); + _mauka->_simAnnealingPlacer->_instanceBins[instanceid] = NULL; +} + +void Bin::RemoveBackInstance(unsigned instanceid) +{ + assert(_instanceOccurrenceIds.back() == instanceid); + _instanceOccurrenceIds.pop_back(); + Unit insWidth = _mauka->_instanceWidths[instanceid]; + _AddSize(-insWidth); + _mauka->_simAnnealingPlacer->_instanceBins[instanceid] = NULL; +} + +void Bin::RemoveFrontInstance(unsigned instanceid) +{ + assert(_instanceOccurrenceIds.front() == instanceid); + _instanceOccurrenceIds.pop_front(); + Unit insWidth = _mauka->_instanceWidths[instanceid]; + _AddSize(-insWidth); + _mauka->_simAnnealingPlacer->_instanceBins[instanceid] = NULL; +} + +bool Bin::TryAddInstance(unsigned instanceid) +{ + Unit insWidth = _mauka->_instanceWidths[instanceid]; + if (GetCapaVsSize() < insWidth) + return false; + AddInstance(instanceid); + return true; +} + +bool Bin::UnderOccupied() const +{ + // On Considère pour l'instant qu'un Bin est sous-occupé + // et donc qu'il est intéressant d'y déplacer une instance + // si il a 20% de vide par rapport à son remplissage idéal + + return ((_instanceOccurrenceIds.size() == 0) + || (_size <= (1.0 - _subRow->GetSurface()->GetMargin() - 0.2) * _capa)); +} + +double Bin::GetCost() const +{ + return abs(GetValue(_size - _capa)); +} + +void Bin::DisplayHits() const +{ + cout << this << " nb source hits: " << _sourceHits << endl; + cout << this << " nb target hits: " << _targetHits << endl; +} + +void Bin::IncrementSourceHits() +{ + ++_sourceHits; +} + +void Bin::IncrementTargetHits() +{ + ++_targetHits; +} + +void Bin::PlotStats(ofstream& out) const +{ + unsigned x = (unsigned)(GetValue(GetXMin())) + (unsigned)(GetValue(GetXMax() - GetXMin())) / 2; + //unsigned decal = (unsigned)(GetValue(GetYMax() - GetYMin())) / 4; + //unsigned y = (unsigned)(GetValue(GetYMin())); + unsigned y = (unsigned)(GetValue(GetYMin())) + (unsigned)(GetValue(GetYMax() - GetYMin())) / 2; + unsigned totalMoves = _mauka->_simAnnealingPlacer->GetMoves(); + if (totalMoves) + { + //double sourcePercent = (_sourceHits * 100.0) / totalMoves; + double targetPercent = (_targetHits * 100.0) / totalMoves; + out << "set label \"" + << targetPercent << "%\" at " << x << "," << y << " center" + << endl; + //out << "set label \"" + // << targetPercent << "%\" at " << x << "," << y + decal << " center" + // << endl; + } +} + +void Bin::Plot(ofstream& out) const +{ + out << GetValue(GetXMin()) + 0.3 << " " << GetValue(GetYMin()) + 0.3 << endl + << GetValue(GetXMin()) + 0.3 << " " << GetValue(GetYMax()) - 0.3 << endl + << GetValue(GetXMax()) - 0.3 << " " << GetValue(GetYMax()) - 0.3 << endl + << GetValue(GetXMax()) - 0.3 << " " << GetValue(GetYMin()) + 0.3 << endl + << GetValue(GetXMin()) + 0.3 << " " << GetValue(GetYMin()) + 0.3 << endl << endl; +} + +} diff --git a/mauka/src/CMakeLists.txt b/mauka/src/CMakeLists.txt new file mode 100644 index 00000000..ce130392 --- /dev/null +++ b/mauka/src/CMakeLists.txt @@ -0,0 +1,48 @@ + + include ( ${QT_USE_FILE} ) + + include_directories ( ${MAUKA_SOURCE_DIR}/src + ${HURRICANE_INCLUDE_DIR} + ${CORIOLIS_INCLUDE_DIR} + ) + set ( includes mauka/Configuration.h + mauka/BBPlacer.h + mauka/Bin.h + mauka/Container.h + mauka/MaukaBox.h + mauka/Move.h + mauka/Row.h + mauka/SimAnnealingPlacer.h + mauka/SubRow.h + mauka/Surface.h + mauka/MaukaEngine.h + ) + set ( mocIncludes mauka/ConfigurationWidget.h + mauka/GraphicMaukaEngine.h ) + set ( cpps Configuration.cpp + ConfigurationWidget.cpp + BBPlacer.cpp + Bin.cpp + Container.cpp + MaukaBox.cpp + Move.cpp + Row.cpp + SimAnnealingPlacer.cpp + SubRow.cpp + Surface.cpp + MaukaEngine.cpp + GraphicMaukaEngine.cpp + ) + qt4_wrap_cpp ( mocCpps ${mocIncludes} ) + + + add_library ( mauka ${cpps} ${mocCpps} ) + target_link_libraries ( mauka ${CORIOLIS_LIBRARIES} + ${HURRICANE_LIBRARIES} + ${HURRICANE_GRAPHICAL_LIBRARIES} + ${QT_LIBRARIES} + ${LEFDEF_LIBRARIES} + ${OA_LIBRARIES} + ) + install ( TARGETS mauka DESTINATION lib${LIB_SUFFIX} ) + install ( FILES ${includes} ${mocIncludes} DESTINATION include/coriolis2/mauka ) diff --git a/mauka/src/Configuration.cpp b/mauka/src/Configuration.cpp new file mode 100644 index 00000000..15746da9 --- /dev/null +++ b/mauka/src/Configuration.cpp @@ -0,0 +1,133 @@ + +// -*- 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 a u k a - P l a c 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 +#include + +#include "hurricane/Cell.h" +#include "crlcore/Utilities.h" +#include "mauka/Configuration.h" + + + +namespace Mauka { + + + using std::cout; + using std::cerr; + using std::endl; + using std::setprecision; + using std::ostringstream; + using std::string; + using Hurricane::tab; + using Hurricane::inltrace; + + +// ------------------------------------------------------------------- +// Class : "Mauka::Configuration". + + + Configuration* Configuration::_default = NULL; + + + Configuration* Configuration::getDefault () + { + if ( _default == NULL ) { + _default = new Configuration (); + } + return _default; + } + + + Configuration::Configuration () + : _standardSimulatedAnnealing(false) + , _ignorePins (false) + , _plotBins (true) + , _searchRatio (0.50) + , _annealingNetMult (0.90) + , _annealingBinMult (0.05) + , _annealingRowMult (0.05) + { } + + + Configuration::Configuration ( const Configuration& other ) + : _standardSimulatedAnnealing(other._standardSimulatedAnnealing) + , _ignorePins (other._ignorePins) + , _plotBins (other._plotBins) + , _searchRatio (other._searchRatio) + , _annealingNetMult (other._annealingNetMult) + , _annealingBinMult (other._annealingBinMult) + , _annealingRowMult (other._annealingRowMult) + { } + + + Configuration::~Configuration () + { } + + + Configuration* Configuration::clone () const + { return new Configuration(*this); } + + + void Configuration::print ( Cell* cell ) const + { + cout << " o Configuration of ToolEngine for Cell <" << cell->getName() << ">" << endl; + cout << Dots::asBool (" - Use standard simulated annealing" ,_standardSimulatedAnnealing) << endl; + cout << Dots::asBool (" - Ignore Pins" ,_ignorePins) << endl; + cout << Dots::asBool (" - Plot Bins" ,_plotBins) << endl; + cout << Dots::asPercentage(" - Search Ratio" ,_searchRatio) << endl; + } + + + string Configuration::_getTypeName () const + { + return "Mauka::Configuration"; + } + + + string Configuration::_getString () const + { + ostringstream os; + + os << "<" << _getTypeName() << ">"; + + return os.str(); + } + + + Record* Configuration::_getRecord () const + { + Record* record = new Record ( _getString() ); + record->add ( getSlot( "_standardSimulatedAnnealing", _standardSimulatedAnnealing) ); + record->add ( getSlot( "_ignorePins" , _ignorePins ) ); + record->add ( getSlot( "_plotBins" , _plotBins ) ); + record->add ( getSlot( "_searchRatio" , _searchRatio ) ); + + return ( record ); + } + + + +} // End of Mauka namespace. diff --git a/mauka/src/ConfigurationWidget.cpp b/mauka/src/ConfigurationWidget.cpp new file mode 100644 index 00000000..7cc56e71 --- /dev/null +++ b/mauka/src/ConfigurationWidget.cpp @@ -0,0 +1,371 @@ + +// -*- 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 a u k a - P l a c e r | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./ConfigurationWidget.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hurricane/viewer/Graphics.h" +#include "nimbus/Configuration.h" +#include "mauka/Configuration.h" +#include "mauka/ConfigurationWidget.h" + + +namespace Mauka { + + using Hurricane::Graphics; + + +// ------------------------------------------------------------------- +// Class : "Mauka::ConfigurationWidget". + + + ConfigurationWidget::ConfigurationWidget ( QWidget* parent ) + : QWidget(parent) + , _nimbusConfiguration (NULL) + , _maukaConfiguration (NULL) + , _standardAnnealingState(new QCheckBox()) + , _ignorePinsState (new QCheckBox()) + , _plotBinsState (new QCheckBox()) + , _pinsPlacementState (new QCheckBox()) + , _searchRatioEdit (new QLineEdit()) + , _annealingNetMultEdit (new QLineEdit()) + , _annealingBinMultEdit (new QLineEdit()) + , _annealingRowMultEdit (new QLineEdit()) + , _aspectRatioEdit (new QLineEdit()) + , _marginEdit (new QLineEdit()) + { + setAttribute ( Qt::WA_QuitOnClose, false ); + + QVBoxLayout* vLayout = new QVBoxLayout (); + QGridLayout* gLayout = new QGridLayout (); + + QLabel* label = new QLabel(); + label->setFont ( Graphics::getNormalFont(true) ); + label->setText ( "Mauka - Placer" ); + gLayout->addWidget ( label, 0, 0, 1, 4, Qt::AlignLeft ); + + // Nimbus configuration. + label = new QLabel(); + label->setText ( "Pins Placement" ); + _pinsPlacementState->setEnabled ( false ); + gLayout->addWidget ( label , 1, 0, Qt::AlignRight ); + gLayout->addWidget ( _pinsPlacementState, 1, 1, Qt::AlignLeft ); + + label = new QLabel(); + label->setText ( "Aspect Ratio: X/Y (%)" ); + _aspectRatioEdit->setValidator ( new QDoubleValidator(this) ); + _aspectRatioEdit->setEnabled ( false ); + gLayout->addWidget ( label , 1, 2, Qt::AlignRight ); + gLayout->addWidget ( _aspectRatioEdit, 1, 3, Qt::AlignLeft ); + + label = new QLabel(); + label->setText ( "Space Margin (%)" ); + _marginEdit->setValidator ( new QDoubleValidator(this) ); + _marginEdit->setEnabled ( false ); + gLayout->addWidget ( label , 2, 2, Qt::AlignRight ); + gLayout->addWidget ( _marginEdit, 2, 3, Qt::AlignLeft ); + + QFrame* separator = new QFrame (); + separator->setFrameShape ( QFrame::HLine ); + separator->setFrameShadow ( QFrame::Sunken ); + gLayout->addWidget ( separator, 3, 0, 1, 4 ); + + // Mauka configuration. + label = new QLabel(); + label->setText ( "Standard Annealing" ); + _standardAnnealingState->setEnabled ( false ); + gLayout->addWidget ( label , 4, 0, Qt::AlignRight ); + gLayout->addWidget ( _standardAnnealingState, 4, 1, Qt::AlignLeft ); + + label = new QLabel(); + label->setText ( "Ignore Pins" ); + _ignorePinsState->setEnabled ( false ); + gLayout->addWidget ( label , 5, 0, Qt::AlignRight ); + gLayout->addWidget ( _ignorePinsState, 5, 1, Qt::AlignLeft ); + + label = new QLabel(); + label->setText ( "Plot Bins" ); + _plotBinsState->setEnabled ( false ); + gLayout->addWidget ( label , 6, 0, Qt::AlignRight ); + gLayout->addWidget ( _plotBinsState, 6, 1, Qt::AlignLeft ); + + label = new QLabel(); + label->setText ( "Search Ratio (%)" ); + _searchRatioEdit->setValidator ( new QDoubleValidator(this) ); + _searchRatioEdit->setEnabled ( false ); + gLayout->addWidget ( label , 4, 2, Qt::AlignRight ); + gLayout->addWidget ( _searchRatioEdit, 4, 3, Qt::AlignLeft ); + + label = new QLabel(); + label->setText ( "Annealing Net Mult (%)" ); + _annealingNetMultEdit->setValidator ( new QDoubleValidator(this) ); + _annealingNetMultEdit->setEnabled ( false ); + gLayout->addWidget ( label , 5, 2, Qt::AlignRight ); + gLayout->addWidget ( _annealingNetMultEdit, 5, 3, Qt::AlignLeft ); + + label = new QLabel(); + label->setText ( "Annealing Bin Mult (%)" ); + _annealingBinMultEdit->setValidator ( new QDoubleValidator(this) ); + _annealingBinMultEdit->setEnabled ( false ); + gLayout->addWidget ( label , 6, 2, Qt::AlignRight ); + gLayout->addWidget ( _annealingBinMultEdit, 6, 3, Qt::AlignLeft ); + + label = new QLabel(); + label->setText ( "Annealing Row Mult (%)" ); + _annealingRowMultEdit->setValidator ( new QDoubleValidator(this) ); + _annealingRowMultEdit->setEnabled ( false ); + gLayout->addWidget ( label , 7, 2, Qt::AlignRight ); + gLayout->addWidget ( _annealingRowMultEdit, 7, 3, Qt::AlignLeft ); + + separator = new QFrame (); + separator->setFrameShape ( QFrame::HLine ); + separator->setFrameShadow ( QFrame::Sunken ); + gLayout->addWidget ( separator, 8, 0, 1, 4 ); + + vLayout->addLayout ( gLayout ); + + QHBoxLayout* hLayout = new QHBoxLayout (); + hLayout->addStretch (); + + QPushButton* apply = new QPushButton (); + apply->setText ( tr("Apply") ); + hLayout->addWidget ( apply ); + hLayout->addStretch (); + + vLayout->addLayout ( hLayout ); + vLayout->addStretch (); + + setLayout ( vLayout ); + + connect ( apply, SIGNAL(clicked()), this, SLOT(_applySettings()) ); + } + + + void ConfigurationWidget::setConfiguration ( Nimbus::Configuration* nimbusConfig + , Configuration* maukaConfig ) + { + if ( maukaConfig != NULL ) { + _searchRatioEdit ->setText ( QString("%1").arg(maukaConfig ->getSearchRatio()) ); + _annealingNetMultEdit->setText ( QString("%1").arg(maukaConfig ->getAnnealingNetMult()) ); + _annealingBinMultEdit->setText ( QString("%1").arg(maukaConfig ->getAnnealingBinMult()) ); + _annealingRowMultEdit->setText ( QString("%1").arg(maukaConfig ->getAnnealingRowMult()) ); + _aspectRatioEdit ->setText ( QString("%1").arg(nimbusConfig->getAspectRatio()) ); + _marginEdit ->setText ( QString("%1").arg(nimbusConfig->getMargin()) ); + + _standardAnnealingState->setChecked ( maukaConfig ->useStandardSimulatedAnnealing() ); + _ignorePinsState ->setChecked ( maukaConfig ->doIgnorePins() ); + _plotBinsState ->setChecked ( maukaConfig ->doPlotBins() ); + _pinsPlacementState ->setChecked ( nimbusConfig->doPinsPlacement() ); + + _searchRatioEdit ->setEnabled ( true ); + _annealingNetMultEdit ->setEnabled ( true ); + _annealingBinMultEdit ->setEnabled ( true ); + _annealingRowMultEdit ->setEnabled ( true ); + _aspectRatioEdit ->setEnabled ( true ); + _marginEdit ->setEnabled ( true ); + _standardAnnealingState->setEnabled ( true ); + _ignorePinsState ->setEnabled ( true ); + _plotBinsState ->setEnabled ( true ); + _pinsPlacementState ->setEnabled ( true ); + } else { + _searchRatioEdit ->setEnabled ( false ); + _annealingNetMultEdit ->setEnabled ( false ); + _annealingBinMultEdit ->setEnabled ( false ); + _annealingRowMultEdit ->setEnabled ( false ); + _marginEdit ->setEnabled ( false ); + _standardAnnealingState->setEnabled ( false ); + _standardAnnealingState->setEnabled ( false ); + _ignorePinsState ->setEnabled ( false ); + _plotBinsState ->setEnabled ( false ); + _pinsPlacementState ->setEnabled ( false ); + + _nimbusConfiguration = NULL; + _maukaConfiguration = NULL; + } + _nimbusConfiguration = nimbusConfig; + _maukaConfiguration = maukaConfig; + } + + + void ConfigurationWidget::_applySettings () + { + if ( _maukaConfiguration == NULL ) return; + + _updateStandardAnnealingState (); + _updateIgnorePinsState (); + _updatePlotBinsState (); + _updatePinsPlacementState (); + _updateSearchRatio (); + _updateAnnealingNetMult (); + _updateAnnealingBinMult (); + _updateAnnealingRowMult (); + _updateAspectRatio (); + _updateMargin (); + } + + + void ConfigurationWidget::_updateSearchRatio () + { + if ( _maukaConfiguration == NULL ) return; + + bool success = false; + float ratio = _searchRatioEdit->displayText().toFloat ( &success ); + + if ( success ) { + _maukaConfiguration->setSearchRatio ( ratio ); + success = (_maukaConfiguration->getSearchRatio() == ratio); + } + + if ( not success ) + _searchRatioEdit->setText ( QString("%1").arg(_maukaConfiguration->getSearchRatio()) ); + } + + + void ConfigurationWidget::_updateAnnealingNetMult () + { + if ( _maukaConfiguration == NULL ) return; + + bool success = false; + float ratio = _annealingNetMultEdit->displayText().toFloat ( &success ); + + if ( success ) { + _maukaConfiguration->setAnnealingNetMult ( ratio ); + success = (_maukaConfiguration->getAnnealingNetMult() == ratio); + } + + if ( not success ) + _annealingNetMultEdit->setText ( QString("%1").arg(_maukaConfiguration->getAnnealingNetMult()) ); + } + + + void ConfigurationWidget::_updateAnnealingBinMult () + { + if ( _maukaConfiguration == NULL ) return; + + bool success = false; + float ratio = _annealingBinMultEdit->displayText().toFloat ( &success ); + + if ( success ) { + _maukaConfiguration->setAnnealingBinMult ( ratio ); + success = (_maukaConfiguration->getAnnealingBinMult() == ratio); + } + + if ( not success ) + _annealingBinMultEdit->setText ( QString("%1").arg(_maukaConfiguration->getAnnealingBinMult()) ); + } + + + void ConfigurationWidget::_updateAnnealingRowMult () + { + if ( _maukaConfiguration == NULL ) return; + + bool success = false; + float ratio = _annealingRowMultEdit->displayText().toFloat ( &success ); + + if ( success ) { + _maukaConfiguration->setAnnealingRowMult ( ratio ); + success = (_maukaConfiguration->getAnnealingRowMult() == ratio); + } + + if ( not success ) + _annealingRowMultEdit->setText ( QString("%1").arg(_maukaConfiguration->getAnnealingRowMult()) ); + } + + + void ConfigurationWidget::_updateAspectRatio () + { + if ( _nimbusConfiguration == NULL ) return; + + bool success = false; + float ratio = _aspectRatioEdit->displayText().toFloat ( &success ); + + if ( success ) { + _nimbusConfiguration->setAspectRatio ( ratio ); + success = (_nimbusConfiguration->getAspectRatio() == ratio); + } + + if ( not success ) + _aspectRatioEdit->setText ( QString("%1").arg(_nimbusConfiguration->getAspectRatio()) ); + } + + + void ConfigurationWidget::_updateMargin () + { + if ( _nimbusConfiguration == NULL ) return; + + bool success = false; + float ratio = _marginEdit->displayText().toFloat ( &success ); + + if ( success ) { + _nimbusConfiguration->setMargin ( ratio ); + success = (_nimbusConfiguration->getMargin() == ratio); + } + + if ( not success ) + _marginEdit->setText ( QString("%1").arg(_nimbusConfiguration->getMargin()) ); + } + + + void ConfigurationWidget::_updateStandardAnnealingState () + { + if ( _maukaConfiguration == NULL ) return; + + _maukaConfiguration->setStandardSimulatedAnnealing ( _standardAnnealingState->isChecked() ); + } + + + void ConfigurationWidget::_updateIgnorePinsState () + { + if ( _maukaConfiguration == NULL ) return; + + _maukaConfiguration->setIgnorePins ( _ignorePinsState->isChecked() ); + } + + + void ConfigurationWidget::_updatePlotBinsState () + { + if ( _maukaConfiguration == NULL ) return; + + _maukaConfiguration->setPlotBins ( _plotBinsState->isChecked() ); + } + + + void ConfigurationWidget::_updatePinsPlacementState () + { + if ( _nimbusConfiguration == NULL ) return; + + _nimbusConfiguration->setPinsPlacement ( _pinsPlacementState->isChecked() ); + } + + +} // End of Mauka namespace. diff --git a/mauka/src/Container.cpp b/mauka/src/Container.cpp new file mode 100644 index 00000000..73a2b5a5 --- /dev/null +++ b/mauka/src/Container.cpp @@ -0,0 +1,80 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#include "mauka/Container.h" + +namespace Mauka { + +using namespace std; + +const Name Container::_goName = "Mauka::Container"; + +Container::Container(Cell* cell, const Box& box) + : ExtensionGo(cell) + , _box(box) +{} + +const Name& Container::getStaticName() +// *********************************** +{ + return _goName; +} + +const Name& Container::getName() const +// *********************************** +{ + return _goName; +} + +string Container::_getString() const +// ********************************* +{ + string s = Inherit::_getString(); + s.insert(s.length() - 1, " " + getString(_box)); + return s; +} + +Record* Container::_getRecord() const +// **************************** +{ + Record* record = Inherit::_getRecord(); + if (record) + { + record->add(getSlot("Box", _box)); + } + return record; +} + +} diff --git a/mauka/src/Container.cpp.noRefactor b/mauka/src/Container.cpp.noRefactor new file mode 100644 index 00000000..13ed279f --- /dev/null +++ b/mauka/src/Container.cpp.noRefactor @@ -0,0 +1,84 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#include "Container.h" + +namespace MAUKA { + +Container::Container(const Cell* cell, const Box& box) + : Inherit(GetDisplaySlot(cell, "Mauka")) + , _box(box) +{} + +bool Container::_IsInterceptedBy(View* view, const Point& point, const Unit& aperture) const +// ****************************************************************************************** +{ + return false; +} + +void Container::_Draw(View* view, BasicLayer* basiclayer, const Box& updatearea, const Transformation& transformation) +// ******************************************************************************************************************* +{ + if (basiclayer) + throw Error("Container::_Draw : basiclayer sould be null !"); + view->DrawRectangle(transformation.GetBox(_box)); +} + +void Container::_Highlight(View* view, const Box& updatearea, const Transformation& transformation) +{ + _Draw(view, NULL, updatearea, transformation); +} + + +string Container::_GetString() const +// ********************************* +{ + string s = Inherit::_GetString(); + s.insert(s.length() - 1, " " + GetString(_box)); + return s; +} + +Record* Container::_GetRecord() const +// **************************** +{ + Record* record = Inherit::_GetRecord(); + if (record) + { + record->Add(GetSlot("Box", _box)); + } + return record; +} + +} diff --git a/mauka/src/GraphicMaukaEngine.cpp b/mauka/src/GraphicMaukaEngine.cpp new file mode 100644 index 00000000..47e288b7 --- /dev/null +++ b/mauka/src/GraphicMaukaEngine.cpp @@ -0,0 +1,287 @@ + +// -*- 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 a u k a - P l a c e r | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./GraphicMaukaEngine.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Mauka { + + + using namespace std; + using Hurricane::Error; + using Hurricane::Warning; + using Hurricane::Breakpoint; + using Hurricane::DebugSession; + using Hurricane::UpdateSession; + using Hurricane::Net; + using Hurricane::Graphics; + using Hurricane::ColorScale; + using Hurricane::ControllerWidget; + using CRL::Catalog; + using CRL::AllianceFramework; + using Nimbus::NimbusEngine; + + + size_t GraphicMaukaEngine::_references = 0; + GraphicMaukaEngine* GraphicMaukaEngine::_singleton = NULL; + + + void GraphicMaukaEngine::initMaukaContainer ( CellWidget* widget ) + { + widget->getDrawingPlanes().setPen ( Graphics::getPen ("mauka.container",widget->getDarkening()) ); + widget->getDrawingPlanes().setBrush ( Graphics::getBrush("mauka.container",widget->getDarkening()) ); + } + + + void GraphicMaukaEngine::drawMaukaContainer ( CellWidget* widget + , const Go* go + , const BasicLayer* basicLayer + , const Box& box + , const Transformation& transformation + ) + { + const Container* container = static_cast(go); + + QPainter& painter = widget->getPainter(); + painter.drawRect ( widget->dbuToDisplayRect(container->getBoundingBox()) ); + } + + + MaukaEngine* GraphicMaukaEngine::createEngine () + { + Cell* cell = getCell (); + + MaukaEngine* mauka = MaukaEngine::get ( cell ); + if ( mauka == NULL ) { + NimbusEngine* nimbus = NimbusEngine::create ( cell, AllianceFramework::get()->getLibrary(1) ); + mauka = MaukaEngine::create ( cell ); + } else + cerr << Warning("%s already has a Mauka engine.",getString(cell).c_str()) << endl; + + return mauka; + } + + + MaukaEngine* GraphicMaukaEngine::getForFramework () + { + MaukaEngine* mauka = MaukaEngine::get ( getCell() ); + if ( mauka != NULL ) return mauka; + + mauka = createEngine (); + + if ( mauka == NULL ) + throw Error("Failed to create Mauka engine on %s.",getString(getCell()).c_str()); + + return mauka; + } + + + void GraphicMaukaEngine::run () + { + MaukaEngine* mauka = createEngine (); + if ( mauka == NULL ) { + throw Error("MaukaEngine not created yet, run the global router first."); + } + emit cellPreModificated (); + + _viewer->clearToolInterrupt (); + _viewer->getCellWidget()->fitToContents (); + + mauka->Run (); + emit cellPostModificated (); + } + + + void GraphicMaukaEngine::save () + { + MaukaEngine* mauka = createEngine (); + if ( mauka == NULL ) { + throw Error("MaukaEngine not created yet, run the placer first."); + } + emit cellPreModificated (); + + _viewer->clearToolInterrupt (); + + mauka->Save (); + emit cellPostModificated (); + } + + + void GraphicMaukaEngine::postEvent () + { + static unsigned int count = 0; + + if ( not (count++ % 500) ) { + //UpdateSession::close (); + + //_viewer->getCellWidget()->refresh (); + QApplication::processEvents (); + + //UpdateSession::open (); + + if ( _viewer->isToolInterrupted() ) { + //MaukaEngine* mauka = MaukaEngine::get ( getCell() ); + //if ( mauka ) mauka->setInterrupt ( true ); + + _viewer->clearToolInterrupt (); + } + } + } + + + void GraphicMaukaEngine::addToMenu ( CellViewer* viewer ) + { + assert ( _viewer == NULL ); + + _viewer = viewer; + + QMenu* prMenu = _viewer->findChild("viewer.menuBar.placeAndRoute"); + QMenu* stepMenu = _viewer->findChild("viewer.menuBar.placeAndRoute.stepByStep"); + if ( prMenu == NULL ) { + QMenuBar* menuBar = _viewer->findChild("viewer.menuBar"); + if ( menuBar == NULL ) { + cerr << Warning("GraphicMaukaEngine::addToMenu() - No MenuBar in parent widget.") << endl; + return; + } + prMenu = menuBar->addMenu ( tr("P&&R") ); + prMenu->setObjectName ( "viewer.menuBar.placeAndRoute" ); + + stepMenu = prMenu->addMenu ( tr("&Step by Step") ); + stepMenu->setObjectName ( "viewer.menuBar.placeAndRoute.stepByStep" ); + + prMenu->addSeparator (); + } + + QAction* placeAction = _viewer->findChild("viewer.menuBar.placeAndRoute.maukaPlace"); + if ( placeAction != NULL ) + cerr << Warning("GraphicMaukaEngine::addToMenu() - Mauka placer already hooked in.") << endl; + else { + QAction* placeAction = new QAction ( tr("Mauka - &Place"), _viewer ); + placeAction->setObjectName ( "viewer.menuBar.placeAndRoute.maukaPlace" ); + placeAction->setStatusTip ( tr("Run the Mauka placer") ); + placeAction->setVisible ( true ); + prMenu->addAction ( placeAction ); + + connect ( placeAction, SIGNAL(triggered()), this, SLOT(run()) ); + } + + connect ( this, SIGNAL(cellPreModificated ()), _viewer->getCellWidget(), SLOT(cellPreModificate ()) ); + connect ( this, SIGNAL(cellPostModificated()), _viewer->getCellWidget(), SLOT(cellPostModificate()) ); + + ControllerWidget* controller = _viewer->getControllerWidget(); + ConfigurationWidget* setting = controller->getSettings() + ->findChild("controller.tabSettings.setting.mauka"); + + if ( setting == NULL ) { + setting = new ConfigurationWidget (); + setting->setObjectName ( "controller.tabSettings.setting.mauka" ); + setting->setConfiguration ( Nimbus::Configuration::getDefault(), Configuration::getDefault() ); + controller->addSetting ( setting, "Mauka" ); + } + } + + + const Name& GraphicMaukaEngine::getName () const + { + return MaukaEngine::staticGetName (); + } + + + Cell* GraphicMaukaEngine::getCell () + { + if ( _viewer == NULL ) { + throw Error ( "Mauka: GraphicMaukaEngine not bound to any Viewer." ); + return NULL; + } + + if ( _viewer->getCell() == NULL ) { + throw Error ( "Mauka: No Cell is loaded into the Viewer." ); + return NULL; + } + + return _viewer->getCell(); + } + + + GraphicMaukaEngine* GraphicMaukaEngine::grab () + { + if ( not _references ) { + _singleton = new GraphicMaukaEngine (); + } + _references++; + + return _singleton; + } + + + size_t GraphicMaukaEngine::release () + { + _references--; + if ( not _references ) { + delete _singleton; + _singleton = NULL; + } + return _references; + } + + + GraphicMaukaEngine::GraphicMaukaEngine () + : GraphicTool() + , _viewer (NULL) + { + addDrawGo ( "Mauka::Container", initMaukaContainer, drawMaukaContainer ); + addDrawGo ( "Mauka::Bin" , initMaukaContainer, drawMaukaContainer ); + } + + + GraphicMaukaEngine::~GraphicMaukaEngine () + { } + + +} // End of Mauka namespace. diff --git a/mauka/src/Mauka.cpp.noRefactor b/mauka/src/Mauka.cpp.noRefactor new file mode 100644 index 00000000..bf3a028c --- /dev/null +++ b/mauka/src/Mauka.cpp.noRefactor @@ -0,0 +1,678 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag + +#include "Cell.h" +#include "HyperNet.h" +USING_NAMESPACE_HURRICANE + +#include "CTimer.h" +#include "CDataBase.h" +#include "CCellGauge.h" +using namespace CRL; + +#include "Nimbus.h" +using namespace NIMBUS; + +#include "Surface.h" +#include "Row.h" +#include "SimAnnealingPlacer.h" +#include "BBPlacer.h" +#include "Mauka.h" + +namespace MAUKA { + +namespace { + +Name MaukaName("Mauka"); + +} + + +Mauka::Mauka(Cell* cell) +// ************************* + : Inherit(cell) + , _params() + , _displaySlot(NULL) + , _instanceOccurrencesVector() + , _instanceOccurrencesMap() + , _instanceWidths() + , _instanceNets() + , _nets() + , _netInstances() + , _netInitX() + , _netInitY() + , _hasInitX() + , _hasInitY() + , _surface(NULL) + , _simAnnealingPlacer(NULL) + , _bbPlacer(NULL) +{} + +Mauka* Mauka::Create(Cell* cell, double searchratio, Box placementbox) +// ******************************************************************* +{ + Mauka* mauka = new Mauka(cell); + + mauka->_PostCreate(placementbox, searchratio); + + return mauka; +} + +void Mauka::_PostCreate(Box& placementbox, double searchratio) +// *********************************************************** +{ + Inherit::_PostCreate(); + + Construct(); + + //_simAnnealingPlacer = new SimAnnealingPlacer(this, 1, 0.0, 0.0); + _simAnnealingPlacer = new SimAnnealingPlacer(this, 0.9, 0.05, 0.05); + + _displaySlot = DisplaySlot::Create(GetCell(),MaukaName,139,0,139); + + _surface = Surface::Create(this, placementbox, searchratio); + + + _simAnnealingPlacer->Init(); + + //Plot(); +} + +#if 0 +void Mauka::ReInit() +// ******************* +{ + Box placementBox = _surface->GetBox(); + _surface->Delete(); + _simAnnealingPlacer->Delete(); + _surface = Surface::Create(this, placementBox); + _simAnnealingPlacer = SimAnnealingPlacer::Create(this); +} +#endif + +void Mauka::Run() +{ + + CTimer timer; + timer.Start(); + while (_simAnnealingPlacer->Iterate()) + ; + timer.Stop(); + if (_verbosity.MajorStatsIsOn()) + { + _simAnnealingPlacer->DisplayResults(); + } + if (_params.plotBins) + { + //PlotBinsStats(); + } + if (_verbosity.SystemResourcesIsOn()) + { + cout << endl << " o Simulated Annealing run took " << timer.GetUserTime() << " s ..." << endl; + } + //Plot(); + _bbPlacer = new BBPlacer(this); + _bbPlacer->Run(); + _bbPlacer->Save(); + //Plot(); +} + +namespace { +void VerifyPathCellBox(const Occurrence& occurrence) +//On occurrence Path set all cells Abox to (0,0,0,0) if Box is empty +//This avoids bad Transfos on Path +{ + Path path = occurrence.GetPath(); + while (!path.IsEmpty()) + { + Instance* instance = path.GetHeadInstance(); + Cell* model = instance->GetMasterCell(); + if (model->GetAbutmentBox().IsEmpty()) + { + model->SetAbutmentBox(Box(Point(0,0), Point(0,0))); + } + path = path.GetTailPath(); + } +} +} + +void Mauka::Construct() +// ********************** +{ + typedef map InstanceOccurrenceMap; + typedef set InstanceSet; + typedef map NetMap; + InstanceSet instanceSet; + NetMap netMap; + unsigned instanceId = 0; + unsigned netId = 0; + + Unit standardCellHeight = 0; + + for_each_occurrence(occurrence, GetCell()->GetLeafInstanceOccurrences()) + { + Instance* instance = static_cast(occurrence.GetEntity()); + if (!instance->IsFixed()) + { + //cerr << "unplaced " << occurrence << occurrence.GetBoundingBox() << endl; + Cell* model = instance->GetMasterCell(); + Unit insWidth = model->GetAbutmentBox().GetWidth(); + Unit insHeight = model->GetAbutmentBox().GetHeight(); + if (standardCellHeight == 0) + standardCellHeight = insHeight; + else if (insHeight != standardCellHeight) + { + throw Error("All non-standard instances : " + + GetString(instance->GetName()) + + " must be placed"); + } + _instanceOccurrencesVector.push_back(occurrence); + //VerifyPathCellBox(occurrence); + _instanceWidths.push_back(insWidth); + InstanceSet::iterator isit = instanceSet.find(instance); + if (isit != instanceSet.end()) + { + cerr << "Unplaced Instance : " << *isit << endl; + cerr << "Unplaced Occurrence : " << occurrence << endl; + cerr << (*isit)->GetPlacementStatus() << endl; + throw Error("Each unplaced instance must have one occurrence only"); + } + _instanceOccurrencesMap[occurrence] = instanceId++; + instanceSet.insert(instance); + _instanceNets.push_back(UVector()); + } + end_for; + } + + if (_instanceOccurrencesVector.size() == 0) + throw Error("No Instance to place..."); + + typedef set NetSet; + NetSet treatedNets; + + for (InstanceOccurrencesVector::const_iterator iovit = _instanceOccurrencesVector.begin(); + iovit != _instanceOccurrencesVector.end(); + iovit++) + { + Instance* instance = static_cast(iovit->GetEntity()); + for_each_plug(plug, instance->GetConnectedPlugs()) + { + Net* net = plug->GetNet(); + if (net->IsGlobal()) + continue; + typedef list InstanceOccurrenceList; + InstanceOccurrenceList instanceOccurrenceList; + Occurrence rootNetOccurrence = GetHyperNetRootNetOccurrence(Occurrence(net, iovit->GetPath())); + Net* rootNet = static_cast(rootNetOccurrence.GetEntity()); + NetSet::iterator snit = treatedNets.find(rootNet); + if (snit != treatedNets.end()) + continue; + treatedNets.insert(rootNet); + HyperNet hyperNet(rootNetOccurrence); + typedef list PointList; + PointList pointList; + for_each_occurrence(occurrence, hyperNet.GetNetOccurrences()) + { + Instance* instance = occurrence.GetPath().GetTailInstance(); + if (instance && instance->IsLeaf()) + { + Occurrence instanceOccurrence = Occurrence(instance, occurrence.GetPath().GetHeadPath()); + if (instance->IsFixed()) + pointList.push_back(instanceOccurrence.GetBoundingBox().GetCenter()); + else + instanceOccurrenceList.push_back(instanceOccurrence); + } + end_for; + } + unsigned pointListSize = pointList.size(); + Point fixedPoint(0,0); + if (pointListSize > 0) + { + for (PointList::iterator plit = pointList.begin(); + plit != pointList.end(); + plit++) + { + fixedPoint.SetX(fixedPoint.GetX() + plit->GetX() / pointListSize); + fixedPoint.SetY(fixedPoint.GetY() + plit->GetY() / pointListSize); + } + } + if ((instanceOccurrenceList.size() < 2) && pointListSize == 0) + continue; + _netInstances.push_back(UVector()); + _nets.push_back(net); + if (pointListSize > 0) + { + _netInitX.push_back(fixedPoint.GetX()); + _netInitY.push_back(fixedPoint.GetY()); + _hasInitX.push_back(true); + _hasInitY.push_back(true); + } + else + { + _netInitX.push_back(0); + _netInitY.push_back(0); + _hasInitX.push_back(false); + _hasInitY.push_back(false); + } + + netMap[net] = netId; + for (InstanceOccurrenceList::iterator iolit = instanceOccurrenceList.begin(); + iolit != instanceOccurrenceList.end(); + iolit++) + { + InstanceOccurrenceMap::const_iterator iomit = _instanceOccurrencesMap.find(*iolit); + if (iomit == _instanceOccurrencesMap.end()) + { + cerr << "cannot find " << iomit->first << endl; + throw Error("Error in netsInstances construction in SimAnnealingPlacer"); + } + _netInstances.back().push_back(iomit->second); + _instanceNets[iomit->second].push_back(netId); + } + ++netId; + end_for; + } + + } + +#if DEBUG + + //debug ... display netlist + for (unsigned instanceId = 0; instanceId < _instanceOccurrencesVector.size(); instanceId++) + { + cerr << "instance " << _instanceOccurrencesVector[instanceId] << endl; + cerr << "is connected to " << endl; + for (UVector::const_iterator uvit = _instanceNets[instanceId].begin(); + uvit != _instanceNets[instanceId].end(); + uvit++) + { + unsigned netid = *uvit; + cerr << _nets[netid] << endl; + for (UVector::const_iterator nuvit = _netInstances[netid].begin(); + nuvit != _netInstances[netid].end(); + nuvit++) + { + cerr << _instanceOccurrencesVector[*nuvit] << endl; + } + cerr << endl; + } + cerr << endl; + } +#endif + + +} + +bool Mauka::Iterate() +// ****************** +{ + bool canContinue = _simAnnealingPlacer->Iterate(); + Save(); + return canContinue; +} + +void Mauka::_PreDelete() +// ********************* +{ + _surface->Delete(); + if (_simAnnealingPlacer) + delete _simAnnealingPlacer; + if (_bbPlacer) + delete _bbPlacer; + _displaySlot->Delete(); + Inherit::_PreDelete(); +} + +Record* Mauka::_GetRecord() const +// ************************ +{ + Record* record = Inherit::_GetRecord(); + if (record) { + record->Add(GetSlot("Surface", _surface)); + } + return record; +} + +const Name& Mauka::GetName() const +// ******************************* +{ + return MaukaName; +} + +void Mauka::Save() const +// ********************* +{ + if (_bbPlacer) + _bbPlacer->Save(); + else if (_simAnnealingPlacer) + _simAnnealingPlacer->Save(); +} + +Mauka* GetMauka(const Cell* cell) +// ****************************** +{ + return static_cast(GetCEngine(cell, MaukaName)); +} + +namespace { + class TestSubRow : public Box { + public: Unit _size; // sum of the contained instances width + public: TestSubRow(const Box& box): Box(box), _size(0) {} + }; + + typedef list TestSubRowsList; + typedef vector InstanceOccurrencesVector; + typedef list InstanceOccurrencesList; + + void DestroyTestSubRows(TestSubRowsList& testsubrowslist) + { + for (TestSubRowsList::iterator tsrlit = testsubrowslist.begin(); + tsrlit != testsubrowslist.end(); + tsrlit++) + { + delete *tsrlit; + } + testsubrowslist.clear(); + } + + struct SortInstanceOccurrencesByWidth + { + bool operator()(Occurrence occurrence1, Occurrence occurrence2) + { + Instance* instance1 = static_cast(occurrence1.GetEntity()); + Instance* instance2 = static_cast(occurrence2.GetEntity()); + return instance1->GetAbutmentBox().GetWidth() > instance2->GetAbutmentBox().GetWidth(); + } + }; + + bool TryDisplayInstancesInSubRows( + InstanceOccurrencesVector& instanceoccurrencesvector, TestSubRowsList& testsubrowslist) + { + // Try Insert instances in subrows + sort(instanceoccurrencesvector.begin(), instanceoccurrencesvector.end(), SortInstanceOccurrencesByWidth()); + + TestSubRowsList::iterator tsrlit = testsubrowslist.begin(); + InstanceOccurrencesVector::const_iterator insIterator = instanceoccurrencesvector.begin(); + InstanceOccurrencesVector::const_iterator lastLoopInsertedInsIterator = insIterator; + + while(insIterator != instanceoccurrencesvector.end()) + { + if (tsrlit == testsubrowslist.end()) + { + tsrlit = testsubrowslist.begin(); + if (lastLoopInsertedInsIterator != insIterator) + lastLoopInsertedInsIterator = insIterator; + else + { + return false; + } + } + TestSubRow* testSubRow = *tsrlit; + Instance* instance = static_cast(insIterator->GetEntity()); + Cell* model = instance->GetMasterCell(); + Unit insWidth = model->GetAbutmentBox().GetWidth(); + if (insWidth <= testSubRow->GetWidth() - testSubRow->_size) + { + testSubRow->_size += insWidth; + ++insIterator; + } + ++tsrlit; + } + return true; + } +} + +bool TestMaukaConstruction(Cell* cell, GCell* gcell) +// ************************************************* +{ + Unit pitch = GetCDataBase()->GetDefaultCGPitch(); + Unit sliceHeight = GetCDataBase()->GetDefaultCGSliceHeight(); + + const Box& box = gcell->GetBox(); + + if (box.IsEmpty() || box.IsPonctual() ||box.IsFlat()) + throw Error("Wrong Box for GCell"); + if (box.GetHeight() % sliceHeight) + throw Error("Box Height must be a multiple of Slice Height"); + + InstanceOccurrencesList fixedInstanceOccurrenceList; + InstanceOccurrencesVector toPlaceInstanceOccurrencesVector; + //search for preplaced leaf instances + Unit instanceToPlaceWidthMax = 0; + for_each_occurrence(occurrence, cell->GetLeafInstanceOccurrencesUnder(gcell->GetBox())) + { + Instance* instance = static_cast(occurrence.GetEntity()); + if (instance->IsFixed()) + fixedInstanceOccurrenceList.push_back(occurrence); + else + { + Cell* model = instance->GetMasterCell(); + Unit insWidth = model->GetAbutmentBox().GetWidth(); + toPlaceInstanceOccurrencesVector.push_back(occurrence); + if (instanceToPlaceWidthMax > insWidth) + instanceToPlaceWidthMax = insWidth; + } + end_for; + } + + Unit binWidthMax = GetUnit((unsigned)( + 2.0 * GetValue(instanceToPlaceWidthMax) / GetValue(pitch)) * GetValue(pitch)); + Unit binWidthMin = GetUnit((unsigned)( + GetValue(binWidthMax) / (GetValue(pitch) * 2)) * GetValue(pitch)); + + TestSubRowsList testSubRowsList; + + if (fixedInstanceOccurrenceList.size() != 0) + { + int width = (unsigned)(gcell->GetWidth() / pitch); //number of x pitch + int height = (unsigned)(gcell->GetHeight() / sliceHeight); //number of y slices + + + Mauka::PrePlaceTab prePlaceTab(height, Mauka::PrePlaceRow(width, false)); + + for (InstanceOccurrencesList::iterator iolit = fixedInstanceOccurrenceList.begin(); + iolit != fixedInstanceOccurrenceList.end(); + iolit++) + { + Instance* instance = static_cast(iolit->GetEntity()); + Box instanceAbutmentBox = instance->GetAbutmentBox(); + iolit->GetPath().GetTransformation().ApplyOn(instanceAbutmentBox); + + Box preplacedBox = gcell->GetIntersection(instanceAbutmentBox); + + Unit insWidth = preplacedBox.GetWidth(); + Unit insHeight = preplacedBox.GetHeight(); + + int insPitchWidth = (int)(insWidth / pitch); // largeur ramene au pitch + int insSliceHeight = (int)(insHeight / sliceHeight); // hauteur ramene a la hauteur du slice + + int ypos = (int)((preplacedBox.GetYMin() - gcell->GetYMin()) / sliceHeight); // position en y ramene au slice + int xpos = (int)((preplacedBox.GetXMin() - gcell->GetXMin()) / pitch); // position en x ramene au pitch + for (int yit = ypos; yit < ypos + insSliceHeight; yit++) + { + for (int xit = xpos; xit < xpos + insPitchWidth; xit++) + { + if ( (xit > width - 1) || (yit > height - 1) + || (xit < 0 ) || (yit < 0 ) ) + { + cerr << " o ERROR : " << *iolit + << " out of the abutment box" << endl; + exit(1); + } + if (prePlaceTab[yit][xit] == false) + { + prePlaceTab[yit][xit] = true; + } + else + { + cerr << " o ERROR : " << *iolit + << " badly placed .... There is already an instance at its position ...." + << endl; + exit (1); + } + } + } + } + for (int y = 0; y < (int)prePlaceTab.size(); y++) + { + int x = 0; + while (x < (int)prePlaceTab[y].size()) + { + while ((x < (int)prePlaceTab[y].size()) && (prePlaceTab[y][x] == true)) + ++x; + Unit subRowXMin = gcell->GetXMin() + x * pitch; + + if (x >= (int)prePlaceTab[y].size()) + break; + + while ((x < (int)prePlaceTab[y].size()) && (prePlaceTab[y][x] == false)) + ++x; + Unit subRowXMax = gcell->GetXMin() + x * pitch; + if (subRowXMax - subRowXMin > binWidthMin) + { + testSubRowsList.push_back(new TestSubRow( + Box(subRowXMin, gcell->GetYMin() + y * sliceHeight + , subRowXMax, gcell->GetYMin() + (y+1) * sliceHeight) + )); + } + + } + } + } + else + { + for (Unit ymin = gcell->GetYMin(); ymin <= gcell->GetYMax() - sliceHeight; ymin += sliceHeight) + { + testSubRowsList.push_back(new TestSubRow( + Box(gcell->GetXMin(), ymin, gcell->GetXMax(), ymin + sliceHeight) + )); + } + } + + bool tryInstanceInsertion = TryDisplayInstancesInSubRows(toPlaceInstanceOccurrencesVector, testSubRowsList); + DestroyTestSubRows(testSubRowsList); + return tryInstanceInsertion; +} + + +void Mauka::PlotBinsStats() const +// ****************************** +{ + ofstream out("binsstats.gpl"); + + out << "set noxtics" << endl << "set noytics" << endl + << "set noborder" << endl << "set nokey" << endl + << "set title '" << GetCell()->GetName() << "'" << endl + << "#set terminal postscript eps color solid" << endl + << "#set output 'binsstats.ps'" << endl; + + _surface->PlotBinsStats(out); +} + +void Mauka::Plot() const +// ********************* +{ + static unsigned count = 0; + string cellNameString = GetString(GetCell()->GetName()) + + "_" + GetString(count) + ".gpl"; + ++count; + ofstream out(cellNameString.c_str()); + + out << "set noxtics" << endl << "set noytics" << endl + << "set noborder" << endl << "set nokey" << endl + << "set title '" << cellNameString << "'" << endl + << "#set terminal postscript eps color solid" << endl << "#set output '" + << cellNameString << ".ps'" << endl; + + Box boundingBox = _surface->GetBox(); + boundingBox.Merge(PlotFixedPointsLabels(out)); + + out << "set xrange[" << boundingBox.GetXMin() + << ":" << boundingBox.GetXMax() << "]" << endl + << "set yrange[" << boundingBox.GetYMin() + << ":" << boundingBox.GetYMax() << "]" << endl; + + out << "plot [:][:][:][:] '-' w l, '-' w l 2, '-' w l 3, '-' w l 4" << endl; +// << "plot [:][:][:][:] '-' w l, '-' w l 2, '-' w l 3, '-' w l 4" << endl; + + _surface->Plot(out); + if (_bbPlacer) + _bbPlacer->Plot(out); + else + _simAnnealingPlacer->Plot(out); + + out << "pause -1 'press any key'" << endl; +} + +Box Mauka::PlotFixedPointsLabels(ofstream& out) const +// **************************************************** +{ + Box boundingBox; + + out << "#FixedPoints" << endl; + for (unsigned i = 0; i < _netInstances.size(); i++) + { + if (_hasInitX[i]) + { + + out << "set label \"" + << GetString(_nets[i]->GetName()) << "\" at " + << _netInitX[i] << "," << _netInitY[i] << " center" + << endl; + } + boundingBox.Merge(_netInitX[i], _netInitY[i]); + } + return boundingBox; +} + +void Mauka::Hide() { + if (_displaySlot != NULL) { + _displaySlot->Hide(); + } +} + +void Mauka::Show() { + if (_displaySlot != NULL) { + _displaySlot->Show(); + } +} + +unsigned Mauka::GetRandomInstanceId() const { + unsigned instanceId = (unsigned)((double)_instanceOccurrencesVector.size() * rand() / (RAND_MAX + 1.0)); + return instanceId; +} + +} diff --git a/mauka/src/MaukaBox.cpp b/mauka/src/MaukaBox.cpp new file mode 100644 index 00000000..def0ac0e --- /dev/null +++ b/mauka/src/MaukaBox.cpp @@ -0,0 +1,107 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#include "mauka/MaukaBox.h" + +namespace Mauka { + +using Hurricane::DbU; + +Box& Update(Box& box, const Point& src, const Point& dst) +{ + DbU::Unit minX = box.getXMin(); + DbU::Unit maxX = box.getXMax(); + DbU::Unit minY = box.getYMin(); + DbU::Unit maxY = box.getYMax(); + + if (dst.getX() > src.getX()) + { + if (src.getX() == minX) + { + box = Box(); + return box; + } + else + if (dst.getX() > maxX) + { + maxX = dst.getX(); + } + } + else + if (dst.getX() < src.getX()) + { + if (src.getX() == maxX) + { + box = Box(); + return box; + } + else + if (dst.getX() < minX) + { + minX = dst.getX(); + } + } + if (dst.getY() > src.getY()) + { + if (src.getY() == minY) + { + box = Box(); + return box; + } + else + if (dst.getY() > maxY) + { + maxY = dst.getY(); + } + } + else + if (dst.getY() < src.getY()) + { + if (src.getY() == maxY) + { + box = Box(); + return box; + } + else + if (dst.getY() < minY) + { + minY = dst.getY(); + } + } + box = Box(Point(minX, minY), Point(maxX, maxY)); + return box; +} + +} diff --git a/mauka/src/MaukaBox.cpp.noRefactor b/mauka/src/MaukaBox.cpp.noRefactor new file mode 100644 index 00000000..9d644eae --- /dev/null +++ b/mauka/src/MaukaBox.cpp.noRefactor @@ -0,0 +1,105 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#include "MaukaBox.h" + +namespace MAUKA { + +Box& Update(Box& box, const Point& src, const Point& dst) +{ + Unit minX = box.GetXMin(); + Unit maxX = box.GetXMax(); + Unit minY = box.GetYMin(); + Unit maxY = box.GetYMax(); + + if (dst.GetX() > src.GetX()) + { + if (src.GetX() == minX) + { + box = Box(); + return box; + } + else + if (dst.GetX() > maxX) + { + maxX = dst.GetX(); + } + } + else + if (dst.GetX() < src.GetX()) + { + if (src.GetX() == maxX) + { + box = Box(); + return box; + } + else + if (dst.GetX() < minX) + { + minX = dst.GetX(); + } + } + if (dst.GetY() > src.GetY()) + { + if (src.GetY() == minY) + { + box = Box(); + return box; + } + else + if (dst.GetY() > maxY) + { + maxY = dst.GetY(); + } + } + else + if (dst.GetY() < src.GetY()) + { + if (src.GetY() == maxY) + { + box = Box(); + return box; + } + else + if (dst.GetY() < minY) + { + minY = dst.GetY(); + } + } + box = Box(Point(minX, minY), Point(maxX, maxY)); + return box; +} + +} diff --git a/mauka/src/MaukaEngine.cpp b/mauka/src/MaukaEngine.cpp new file mode 100644 index 00000000..019a5cd3 --- /dev/null +++ b/mauka/src/MaukaEngine.cpp @@ -0,0 +1,669 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag + +#include "hurricane/Cell.h" +#include "hurricane/HyperNet.h" +#include "hurricane/Timer.h" +#include "hurricane/DataBase.h" +#include "crlcore/CellGauge.h" +#include "crlcore/AllianceFramework.h" + +#include "mauka/Surface.h" +#include "mauka/Row.h" +#include "mauka/SimAnnealingPlacer.h" +#include "mauka/BBPlacer.h" +#include "mauka/MaukaEngine.h" + +namespace Mauka { + +using Hurricane::Plug; +using Hurricane::Path; +using Hurricane::OccurrenceLocator; +using Hurricane::PlugLocator; +using Hurricane::HyperNet; +using Hurricane::Timer; +using namespace CRL; + +Name MaukaEngine::_toolName = "Mauka"; + +MaukaEngine::MaukaEngine(Cell* cell) +// ********************************* + : Inherit(cell) + , _configuration(Configuration::getDefault()->clone()) + , _instanceOccurrencesVector() + , _instanceOccurrencesMap() + , _instanceWidths() + , _instanceNets() + , _nets() + , _netInstances() + , _netInitX() + , _netInitY() + , _hasInitX() + , _hasInitY() + , _surface(NULL) + , _simAnnealingPlacer(NULL) + , _bbPlacer(NULL) +{} + +MaukaEngine* MaukaEngine::create(Cell* cell, Box placementbox) +// *********************************************************** +{ + MaukaEngine* mauka = new MaukaEngine(cell); + + mauka->_postCreate(placementbox); + + return mauka; +} + +void MaukaEngine::_postCreate(Box& placementbox) +// ********************************************* +{ + Inherit::_postCreate(); + + Construct(); + + //_simAnnealingPlacer = new SimAnnealingPlacer(this, 1, 0.0, 0.0); + _simAnnealingPlacer = new SimAnnealingPlacer(this); + + //_displaySlot = DisplaySlot::create(getCell(),,139,0,139); + + _surface = Surface::create(this, placementbox); + + + _simAnnealingPlacer->init(); + + //Plot(); +} + +#if 0 +void MaukaEngine::ReInit() +// ******************* +{ + Box placementBox = _surface->getBox(); + _surface->destroy(); + _simAnnealingPlacer->destroy(); + _surface = Surface::create(this, placementBox); + _simAnnealingPlacer = SimAnnealingPlacer::create(this); +} +#endif + +void MaukaEngine::Run() +{ + + Timer timer; + timer.start(); + while ( _simAnnealingPlacer->Iterate() ); + + timer.stop(); + _simAnnealingPlacer->DisplayResults(); + + //if ( doPlotBins() ) PlotBinsStats(); + + //cmess2 << endl << " o Simulated Annealing run took " << timer.getUserTime() << " s ..." << endl; + cmess1 << " o Simulated annealing took " << Timer::getStringTime(timer.getCombTime()) + << " [+" << Timer::getStringMemory(timer.getIncrease()) << "]." << endl; + cmess1 << " (raw measurements : " << timer.getCombTime() + << "s [+" << (timer.getIncrease()>>10) << "Ko/" + << (timer.getMemorySize()>>10) << "Ko])" << endl; + + //Plot(); + _bbPlacer = new BBPlacer(this); + _bbPlacer->Run(); + _bbPlacer->Save(); + //Plot(); +} + +namespace { +void VerifyPathCellBox(const Occurrence& occurrence) +//On occurrence Path set all cells Abox to (0,0,0,0) if Box is empty +//This avoids bad Transfos on Path +{ + Path path = occurrence.getPath(); + while (!path.isEmpty()) + { + Instance* instance = path.getHeadInstance(); + Cell* model = instance->getMasterCell(); + if (model->getAbutmentBox().isEmpty()) + { + model->setAbutmentBox(Box(Point(0,0), Point(0,0))); + } + path = path.getTailPath(); + } +} +} + +void MaukaEngine::Construct() +// ********************** +{ + typedef map InstanceOccurrenceMap; + typedef set InstanceSet; + typedef map NetMap; + InstanceSet instanceSet; + NetMap netMap; + unsigned instanceId = 0; + unsigned netId = 0; + + DbU::DbU::Unit standardCellHeight = 0; + + for_each_occurrence(occurrence, getCell()->getLeafInstanceOccurrences()) + { + Instance* instance = static_cast(occurrence.getEntity()); + if (!instance->isFixed()) + { + //cerr << "unplaced " << occurrence << occurrence.getBoundingBox() << endl; + Cell* model = instance->getMasterCell(); + DbU::DbU::Unit insWidth = model->getAbutmentBox().getWidth(); + DbU::DbU::Unit insHeight = model->getAbutmentBox().getHeight(); + if (standardCellHeight == 0) + standardCellHeight = insHeight; + else if (insHeight != standardCellHeight) + { + throw Error("All non-standard instances : " + + getString(instance->getName()) + + " must be placed"); + } + _instanceOccurrencesVector.push_back(occurrence); + //VerifyPathCellBox(occurrence); + _instanceWidths.push_back(insWidth); + InstanceSet::iterator isit = instanceSet.find(instance); + if (isit != instanceSet.end()) + { + cerr << "Unplaced Instance : " << *isit << endl; + cerr << "Unplaced Occurrence : " << occurrence << endl; + cerr << (*isit)->getPlacementStatus() << endl; + throw Error("Each unplaced instance must have one occurrence only"); + } + _instanceOccurrencesMap[occurrence] = instanceId++; + instanceSet.insert(instance); + _instanceNets.push_back(UVector()); + } + end_for; + } + + if (_instanceOccurrencesVector.size() == 0) + throw Error("No Instance to place..."); + + typedef set NetSet; + NetSet treatedNets; + + for (InstanceOccurrencesVector::const_iterator iovit = _instanceOccurrencesVector.begin(); + iovit != _instanceOccurrencesVector.end(); + iovit++) + { + Instance* instance = static_cast(iovit->getEntity()); + for_each_plug(plug, instance->getConnectedPlugs()) + { + Net* net = plug->getNet(); + if (net->isGlobal()) + continue; + typedef list InstanceOccurrenceList; + InstanceOccurrenceList instanceOccurrenceList; + Occurrence rootNetOccurrence = getHyperNetRootNetOccurrence(Occurrence(net, iovit->getPath())); + Net* rootNet = static_cast(rootNetOccurrence.getEntity()); + NetSet::iterator snit = treatedNets.find(rootNet); + if (snit != treatedNets.end()) + continue; + treatedNets.insert(rootNet); + HyperNet hyperNet(rootNetOccurrence); + typedef list PointList; + PointList pointList; + for_each_occurrence(occurrence, hyperNet.getNetOccurrences()) + { + Instance* instance = occurrence.getPath().getTailInstance(); + if (instance && instance->isLeaf()) + { + Occurrence instanceOccurrence = Occurrence(instance, occurrence.getPath().getHeadPath()); + if (instance->isFixed()) + pointList.push_back(instanceOccurrence.getBoundingBox().getCenter()); + else + instanceOccurrenceList.push_back(instanceOccurrence); + } + end_for; + } + unsigned pointListSize = pointList.size(); + Point fixedPoint(0,0); + if (pointListSize > 0) + { + for (PointList::iterator plit = pointList.begin(); + plit != pointList.end(); + plit++) + { + fixedPoint.setX(fixedPoint.getX() + plit->getX() / pointListSize); + fixedPoint.setY(fixedPoint.getY() + plit->getY() / pointListSize); + } + } + if ((instanceOccurrenceList.size() < 2) && pointListSize == 0) + continue; + _netInstances.push_back(UVector()); + _nets.push_back(net); + if (pointListSize > 0) + { + _netInitX.push_back(fixedPoint.getX()); + _netInitY.push_back(fixedPoint.getY()); + _hasInitX.push_back(true); + _hasInitY.push_back(true); + } + else + { + _netInitX.push_back(0); + _netInitY.push_back(0); + _hasInitX.push_back(false); + _hasInitY.push_back(false); + } + + netMap[net] = netId; + for (InstanceOccurrenceList::iterator iolit = instanceOccurrenceList.begin(); + iolit != instanceOccurrenceList.end(); + iolit++) + { + InstanceOccurrenceMap::const_iterator iomit = _instanceOccurrencesMap.find(*iolit); + if (iomit == _instanceOccurrencesMap.end()) + { + cerr << "cannot find " << iomit->first << endl; + throw Error("Error in netsInstances construction in SimAnnealingPlacer"); + } + _netInstances.back().push_back(iomit->second); + _instanceNets[iomit->second].push_back(netId); + } + ++netId; + end_for; + } + + } + +#if DEBUG + + //debug ... display netlist + for (unsigned instanceId = 0; instanceId < _instanceOccurrencesVector.size(); instanceId++) + { + cerr << "instance " << _instanceOccurrencesVector[instanceId] << endl; + cerr << "is connected to " << endl; + for (UVector::const_iterator uvit = _instanceNets[instanceId].begin(); + uvit != _instanceNets[instanceId].end(); + uvit++) + { + unsigned netid = *uvit; + cerr << _nets[netid] << endl; + for (UVector::const_iterator nuvit = _netInstances[netid].begin(); + nuvit != _netInstances[netid].end(); + nuvit++) + { + cerr << _instanceOccurrencesVector[*nuvit] << endl; + } + cerr << endl; + } + cerr << endl; + } +#endif + + +} + +bool MaukaEngine::Iterate() +// ****************** +{ + bool canContinue = _simAnnealingPlacer->Iterate(); + Save(); + return canContinue; +} + +void MaukaEngine::_preDestroy() +// ********************* +{ + _surface->destroy(); + if (_simAnnealingPlacer) + delete _simAnnealingPlacer; + if (_bbPlacer) + delete _bbPlacer; + delete _configuration; + Inherit::_preDestroy(); +} + +Record* MaukaEngine::_getRecord() const +// ************************ +{ + Record* record = Inherit::_getRecord(); + if (record) { + record->add(getSlot("Surface", _surface)); + } + return record; +} + +const Name& MaukaEngine::staticGetName() +// ************************************* +{ + return _toolName; +} + +const Name& MaukaEngine::getName() const +// ******************************* +{ + return _toolName; +} + +void MaukaEngine::Save() const +// ********************* +{ + if (_bbPlacer) + _bbPlacer->Save(); + else if (_simAnnealingPlacer) + _simAnnealingPlacer->Save(); +} + +MaukaEngine* MaukaEngine::get(Cell* cell) +// ******************************************** +{ + return static_cast(ToolEngine::get(cell,staticGetName())); +} + +namespace { + class TestSubRow : public Box { + public: DbU::DbU::Unit _size; // sum of the contained instances width + public: TestSubRow(const Box& box): Box(box), _size(0) {} + }; + + typedef list TestSubRowsList; + typedef vector InstanceOccurrencesVector; + typedef list InstanceOccurrencesList; + + void DestroyTestSubRows(TestSubRowsList& testsubrowslist) + { + for (TestSubRowsList::iterator tsrlit = testsubrowslist.begin(); + tsrlit != testsubrowslist.end(); + tsrlit++) + { + delete *tsrlit; + } + testsubrowslist.clear(); + } + + struct sortInstanceOccurrencesByWidth + { + bool operator()(Occurrence occurrence1, Occurrence occurrence2) + { + Instance* instance1 = static_cast(occurrence1.getEntity()); + Instance* instance2 = static_cast(occurrence2.getEntity()); + return instance1->getAbutmentBox().getWidth() > instance2->getAbutmentBox().getWidth(); + } + }; + + bool TryDisplayInstancesInSubRows( + InstanceOccurrencesVector& instanceoccurrencesvector, TestSubRowsList& testsubrowslist) + { + // Try Insert instances in subrows + sort(instanceoccurrencesvector.begin(), instanceoccurrencesvector.end(), sortInstanceOccurrencesByWidth()); + + TestSubRowsList::iterator tsrlit = testsubrowslist.begin(); + InstanceOccurrencesVector::const_iterator insIterator = instanceoccurrencesvector.begin(); + InstanceOccurrencesVector::const_iterator lastLoopInsertedInsIterator = insIterator; + + while(insIterator != instanceoccurrencesvector.end()) + { + if (tsrlit == testsubrowslist.end()) + { + tsrlit = testsubrowslist.begin(); + if (lastLoopInsertedInsIterator != insIterator) + lastLoopInsertedInsIterator = insIterator; + else + { + return false; + } + } + TestSubRow* testSubRow = *tsrlit; + Instance* instance = static_cast(insIterator->getEntity()); + Cell* model = instance->getMasterCell(); + DbU::DbU::Unit insWidth = model->getAbutmentBox().getWidth(); + if (insWidth <= testSubRow->getWidth() - testSubRow->_size) + { + testSubRow->_size += insWidth; + ++insIterator; + } + ++tsrlit; + } + return true; + } +} + +bool TestMaukaConstruction(Cell* cell, GCell* gcell) +// ************************************************* +{ + CellGauge* gauge = AllianceFramework::get()->getCellGauge(); + DbU::Unit pitch = gauge->getPitch(); + DbU::Unit sliceHeight = gauge->getSliceHeight(); + + const Box& box = gcell->getBox(); + + if (box.isEmpty() || box.isPonctual() ||box.isFlat()) + throw Error("Wrong Box for GCell"); + if (box.getHeight() % sliceHeight) + throw Error("Box Height must be a multiple of Slice Height"); + + InstanceOccurrencesList fixedInstanceOccurrenceList; + InstanceOccurrencesVector toPlaceInstanceOccurrencesVector; + //search for preplaced leaf instances + DbU::DbU::Unit instanceToPlaceWidthMax = 0; + for_each_occurrence(occurrence, cell->getLeafInstanceOccurrencesUnder(gcell->getBox())) + { + Instance* instance = static_cast(occurrence.getEntity()); + if (instance->isFixed()) + fixedInstanceOccurrenceList.push_back(occurrence); + else + { + Cell* model = instance->getMasterCell(); + DbU::DbU::Unit insWidth = model->getAbutmentBox().getWidth(); + toPlaceInstanceOccurrencesVector.push_back(occurrence); + if (instanceToPlaceWidthMax > insWidth) + instanceToPlaceWidthMax = insWidth; + } + end_for; + } + + DbU::DbU::Unit binWidthMax = DbU::lambda((unsigned)( + 2.0 * DbU::getLambda(instanceToPlaceWidthMax) / DbU::getLambda(pitch)) * DbU::getLambda(pitch)); + DbU::DbU::Unit binWidthMin = DbU::lambda((unsigned)( + DbU::getLambda(binWidthMax) / (DbU::getLambda(pitch) * 2)) * DbU::getLambda(pitch)); + + TestSubRowsList testSubRowsList; + + if (fixedInstanceOccurrenceList.size() != 0) + { + int width = (unsigned)(gcell->getWidth() / pitch); //number of x pitch + int height = (unsigned)(gcell->getHeight() / sliceHeight); //number of y slices + + + MaukaEngine::PrePlaceTab prePlaceTab(height, MaukaEngine::PrePlaceRow(width, false)); + + for (InstanceOccurrencesList::iterator iolit = fixedInstanceOccurrenceList.begin(); + iolit != fixedInstanceOccurrenceList.end(); + iolit++) + { + Instance* instance = static_cast(iolit->getEntity()); + Box instanceAbutmentBox = instance->getAbutmentBox(); + iolit->getPath().getTransformation().applyOn(instanceAbutmentBox); + + Box preplacedBox = gcell->getIntersection(instanceAbutmentBox); + + DbU::DbU::Unit insWidth = preplacedBox.getWidth(); + DbU::DbU::Unit insHeight = preplacedBox.getHeight(); + + int insPitchWidth = (int)(insWidth / pitch); // largeur ramene au pitch + int insSliceHeight = (int)(insHeight / sliceHeight); // hauteur ramene a la hauteur du slice + + int ypos = (int)((preplacedBox.getYMin() - gcell->getYMin()) / sliceHeight); // position en y ramene au slice + int xpos = (int)((preplacedBox.getXMin() - gcell->getXMin()) / pitch); // position en x ramene au pitch + for (int yit = ypos; yit < ypos + insSliceHeight; yit++) + { + for (int xit = xpos; xit < xpos + insPitchWidth; xit++) + { + if ( (xit > width - 1) || (yit > height - 1) + || (xit < 0 ) || (yit < 0 ) ) + { + cerr << " o ERROR : " << *iolit + << " out of the abutment box" << endl; + exit(1); + } + if (prePlaceTab[yit][xit] == false) + { + prePlaceTab[yit][xit] = true; + } + else + { + cerr << " o ERROR : " << *iolit + << " badly placed .... There is already an instance at its position ...." + << endl; + exit (1); + } + } + } + } + for (int y = 0; y < (int)prePlaceTab.size(); y++) + { + int x = 0; + while (x < (int)prePlaceTab[y].size()) + { + while ((x < (int)prePlaceTab[y].size()) && (prePlaceTab[y][x] == true)) + ++x; + DbU::DbU::Unit subRowXMin = gcell->getXMin() + x * pitch; + + if (x >= (int)prePlaceTab[y].size()) + break; + + while ((x < (int)prePlaceTab[y].size()) && (prePlaceTab[y][x] == false)) + ++x; + DbU::DbU::Unit subRowXMax = gcell->getXMin() + x * pitch; + if (subRowXMax - subRowXMin > binWidthMin) + { + testSubRowsList.push_back(new TestSubRow( + Box(subRowXMin, gcell->getYMin() + y * sliceHeight + , subRowXMax, gcell->getYMin() + (y+1) * sliceHeight) + )); + } + + } + } + } + else + { + for (DbU::DbU::Unit ymin = gcell->getYMin(); ymin <= gcell->getYMax() - sliceHeight; ymin += sliceHeight) + { + testSubRowsList.push_back(new TestSubRow( + Box(gcell->getXMin(), ymin, gcell->getXMax(), ymin + sliceHeight) + )); + } + } + + bool tryInstanceInsertion = TryDisplayInstancesInSubRows(toPlaceInstanceOccurrencesVector, testSubRowsList); + DestroyTestSubRows(testSubRowsList); + return tryInstanceInsertion; +} + + +void MaukaEngine::PlotBinsStats() const +// ****************************** +{ + ofstream out("binsstats.gpl"); + + out << "set noxtics" << endl << "set noytics" << endl + << "set noborder" << endl << "set nokey" << endl + << "set title '" << getCell()->getName() << "'" << endl + << "#set terminal postscript eps color solid" << endl + << "#set output 'binsstats.ps'" << endl; + + _surface->PlotBinsStats(out); +} + +void MaukaEngine::Plot() const +// ********************* +{ + static unsigned count = 0; + string cellNameString = getString(getCell()->getName()) + + "_" + getString(count) + ".gpl"; + ++count; + ofstream out(cellNameString.c_str()); + + out << "set noxtics" << endl << "set noytics" << endl + << "set noborder" << endl << "set nokey" << endl + << "set title '" << cellNameString << "'" << endl + << "#set terminal postscript eps color solid" << endl << "#set output '" + << cellNameString << ".ps'" << endl; + + Box boundingBox = _surface->getBox(); + boundingBox.merge(PlotFixedPointsLabels(out)); + + out << "set xrange[" << boundingBox.getXMin() + << ":" << boundingBox.getXMax() << "]" << endl + << "set yrange[" << boundingBox.getYMin() + << ":" << boundingBox.getYMax() << "]" << endl; + + out << "plot [:][:][:][:] '-' w l, '-' w l 2, '-' w l 3, '-' w l 4" << endl; +// << "plot [:][:][:][:] '-' w l, '-' w l 2, '-' w l 3, '-' w l 4" << endl; + + _surface->Plot(out); + if (_bbPlacer) + _bbPlacer->Plot(out); + else + _simAnnealingPlacer->Plot(out); + + out << "pause -1 'press any key'" << endl; +} + +Box MaukaEngine::PlotFixedPointsLabels(ofstream& out) const +// **************************************************** +{ + Box boundingBox; + + out << "#FixedPoints" << endl; + for (unsigned i = 0; i < _netInstances.size(); i++) + { + if (_hasInitX[i]) + { + + out << "set label \"" + << getString(_nets[i]->getName()) << "\" at " + << _netInitX[i] << "," << _netInitY[i] << " center" + << endl; + } + boundingBox.merge(_netInitX[i], _netInitY[i]); + } + return boundingBox; +} + +unsigned MaukaEngine::getRandomInstanceId() const { + unsigned instanceId = (unsigned)((double)_instanceOccurrencesVector.size() * rand() / (RAND_MAX + 1.0)); + return instanceId; +} + +} diff --git a/mauka/src/MaukaEngine.cpp.noRefactor b/mauka/src/MaukaEngine.cpp.noRefactor new file mode 100644 index 00000000..9c4b0ea4 --- /dev/null +++ b/mauka/src/MaukaEngine.cpp.noRefactor @@ -0,0 +1,678 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag + +#include "Cell.h" +#include "HyperNet.h" +USING_NAMESPACE_HURRICANE + +#include "CTimer.h" +#include "CDataBase.h" +#include "CCellGauge.h" +using namespace CRL; + +#include "Nimbus.h" +using namespace NIMBUS; + +#include "Surface.h" +#include "Row.h" +#include "SimAnnealingPlacer.h" +#include "BBPlacer.h" +#include "Mauka.h" + +namespace MAUKA { + +namespace { + +Name MaukaName("Mauka"); + +} + + +Mauka::Mauka(Cell* cell) +// ************************* + : Inherit(cell) + , _params() + , _displaySlot(NULL) + , _instanceOccurrencesVector() + , _instanceOccurrencesMap() + , _instanceWidths() + , _instanceNets() + , _nets() + , _netInstances() + , _netInitX() + , _netInitY() + , _hasInitX() + , _hasInitY() + , _surface(NULL) + , _simAnnealingPlacer(NULL) + , _bbPlacer(NULL) +{} + +Mauka* Mauka::create(Cell* cell, double searchratio, Box placementbox) +// ******************************************************************* +{ + Mauka* mauka = new Mauka(cell); + + mauka->_postCreate(placementbox, searchratio); + + return mauka; +} + +void Mauka::_postCreate(Box& placementbox, double searchratio) +// *********************************************************** +{ + Inherit::_postCreate(); + + Construct(); + + //_simAnnealingPlacer = new SimAnnealingPlacer(this, 1, 0.0, 0.0); + _simAnnealingPlacer = new SimAnnealingPlacer(this, 0.9, 0.05, 0.05); + + _displaySlot = DisplaySlot::create(getCell(),MaukaName,139,0,139); + + _surface = Surface::create(this, placementbox, searchratio); + + + _simAnnealingPlacer->init(); + + //Plot(); +} + +#if 0 +void Mauka::ReInit() +// ******************* +{ + Box placementBox = _surface->getBox(); + _surface->destroy(); + _simAnnealingPlacer->destroy(); + _surface = Surface::create(this, placementBox); + _simAnnealingPlacer = SimAnnealingPlacer::create(this); +} +#endif + +void Mauka::Run() +{ + + CTimer timer; + timer.Start(); + while (_simAnnealingPlacer->Iterate()) + ; + timer.Stop(); + if (_verbosity.MajorStatsIsOn()) + { + _simAnnealingPlacer->DisplayResults(); + } + if (_params.plotBins) + { + //PlotBinsStats(); + } + if (_verbosity.SystemResourcesIsOn()) + { + cout << endl << " o Simulated Annealing run took " << timer.getUserTime() << " s ..." << endl; + } + //Plot(); + _bbPlacer = new BBPlacer(this); + _bbPlacer->Run(); + _bbPlacer->Save(); + //Plot(); +} + +namespace { +void VerifyPathCellBox(const Occurrence& occurrence) +//On occurrence Path set all cells Abox to (0,0,0,0) if Box is empty +//This avoids bad Transfos on Path +{ + Path path = occurrence.getPath(); + while (!path.isEmpty()) + { + Instance* instance = path.getHeadInstance(); + Cell* model = instance->getMasterCell(); + if (model->getAbutmentBox().isEmpty()) + { + model->setAbutmentBox(Box(Point(0,0), Point(0,0))); + } + path = path.getTailPath(); + } +} +} + +void Mauka::Construct() +// ********************** +{ + typedef map InstanceOccurrenceMap; + typedef set InstanceSet; + typedef map NetMap; + InstanceSet instanceSet; + NetMap netMap; + unsigned instanceId = 0; + unsigned netId = 0; + + DbU::Unit standardCellHeight = 0; + + for_each_occurrence(occurrence, getCell()->getLeafInstanceOccurrences()) + { + Instance* instance = static_cast(occurrence.getEntity()); + if (!instance->isFixed()) + { + //cerr << "unplaced " << occurrence << occurrence.getBoundingBox() << endl; + Cell* model = instance->getMasterCell(); + DbU::Unit insWidth = model->getAbutmentBox().getWidth(); + DbU::Unit insHeight = model->getAbutmentBox().getHeight(); + if (standardCellHeight == 0) + standardCellHeight = insHeight; + else if (insHeight != standardCellHeight) + { + throw Error("All non-standard instances : " + + getString(instance->getName()) + + " must be placed"); + } + _instanceOccurrencesVector.push_back(occurrence); + //VerifyPathCellBox(occurrence); + _instanceWidths.push_back(insWidth); + InstanceSet::iterator isit = instanceSet.find(instance); + if (isit != instanceSet.end()) + { + cerr << "Unplaced Instance : " << *isit << endl; + cerr << "Unplaced Occurrence : " << occurrence << endl; + cerr << (*isit)->getPlacementStatus() << endl; + throw Error("Each unplaced instance must have one occurrence only"); + } + _instanceOccurrencesMap[occurrence] = instanceId++; + instanceSet.insert(instance); + _instanceNets.push_back(UVector()); + } + end_for; + } + + if (_instanceOccurrencesVector.size() == 0) + throw Error("No Instance to place..."); + + typedef set NetSet; + NetSet treatedNets; + + for (InstanceOccurrencesVector::const_iterator iovit = _instanceOccurrencesVector.begin(); + iovit != _instanceOccurrencesVector.end(); + iovit++) + { + Instance* instance = static_cast(iovit->getEntity()); + for_each_plug(plug, instance->getConnectedPlugs()) + { + Net* net = plug->getNet(); + if (net->isGlobal()) + continue; + typedef list InstanceOccurrenceList; + InstanceOccurrenceList instanceOccurrenceList; + Occurrence rootNetOccurrence = getHyperNetRootNetOccurrence(Occurrence(net, iovit->getPath())); + Net* rootNet = static_cast(rootNetOccurrence.getEntity()); + NetSet::iterator snit = treatedNets.find(rootNet); + if (snit != treatedNets.end()) + continue; + treatedNets.insert(rootNet); + HyperNet hyperNet(rootNetOccurrence); + typedef list PointList; + PointList pointList; + for_each_occurrence(occurrence, hyperNet.getNetOccurrences()) + { + Instance* instance = occurrence.getPath().getTailInstance(); + if (instance && instance->isLeaf()) + { + Occurrence instanceOccurrence = Occurrence(instance, occurrence.getPath().getHeadPath()); + if (instance->isFixed()) + pointList.push_back(instanceOccurrence.getBoundingBox().getCenter()); + else + instanceOccurrenceList.push_back(instanceOccurrence); + } + end_for; + } + unsigned pointListSize = pointList.size(); + Point fixedPoint(0,0); + if (pointListSize > 0) + { + for (PointList::iterator plit = pointList.begin(); + plit != pointList.end(); + plit++) + { + fixedPoint.setX(fixedPoint.getX() + plit->getX() / pointListSize); + fixedPoint.setY(fixedPoint.getY() + plit->getY() / pointListSize); + } + } + if ((instanceOccurrenceList.size() < 2) && pointListSize == 0) + continue; + _netInstances.push_back(UVector()); + _nets.push_back(net); + if (pointListSize > 0) + { + _netInitX.push_back(fixedPoint.getX()); + _netInitY.push_back(fixedPoint.getY()); + _hasInitX.push_back(true); + _hasInitY.push_back(true); + } + else + { + _netInitX.push_back(0); + _netInitY.push_back(0); + _hasInitX.push_back(false); + _hasInitY.push_back(false); + } + + netMap[net] = netId; + for (InstanceOccurrenceList::iterator iolit = instanceOccurrenceList.begin(); + iolit != instanceOccurrenceList.end(); + iolit++) + { + InstanceOccurrenceMap::const_iterator iomit = _instanceOccurrencesMap.find(*iolit); + if (iomit == _instanceOccurrencesMap.end()) + { + cerr << "cannot find " << iomit->first << endl; + throw Error("Error in netsInstances construction in SimAnnealingPlacer"); + } + _netInstances.back().push_back(iomit->second); + _instanceNets[iomit->second].push_back(netId); + } + ++netId; + end_for; + } + + } + +#if DEBUG + + //debug ... display netlist + for (unsigned instanceId = 0; instanceId < _instanceOccurrencesVector.size(); instanceId++) + { + cerr << "instance " << _instanceOccurrencesVector[instanceId] << endl; + cerr << "is connected to " << endl; + for (UVector::const_iterator uvit = _instanceNets[instanceId].begin(); + uvit != _instanceNets[instanceId].end(); + uvit++) + { + unsigned netid = *uvit; + cerr << _nets[netid] << endl; + for (UVector::const_iterator nuvit = _netInstances[netid].begin(); + nuvit != _netInstances[netid].end(); + nuvit++) + { + cerr << _instanceOccurrencesVector[*nuvit] << endl; + } + cerr << endl; + } + cerr << endl; + } +#endif + + +} + +bool Mauka::Iterate() +// ****************** +{ + bool canContinue = _simAnnealingPlacer->Iterate(); + Save(); + return canContinue; +} + +void Mauka::_preDestroy() +// ********************* +{ + _surface->destroy(); + if (_simAnnealingPlacer) + delete _simAnnealingPlacer; + if (_bbPlacer) + delete _bbPlacer; + _displaySlot->destroy(); + Inherit::_preDestroy(); +} + +Record* Mauka::_getRecord() const +// ************************ +{ + Record* record = Inherit::_getRecord(); + if (record) { + record->add(getSlot("Surface", _surface)); + } + return record; +} + +const Name& Mauka::getName() const +// ******************************* +{ + return MaukaName; +} + +void Mauka::Save() const +// ********************* +{ + if (_bbPlacer) + _bbPlacer->Save(); + else if (_simAnnealingPlacer) + _simAnnealingPlacer->Save(); +} + +Mauka* getMauka(const Cell* cell) +// ****************************** +{ + return static_cast(getCEngine(cell, MaukaName)); +} + +namespace { + class TestSubRow : public Box { + public: DbU::Unit _size; // sum of the contained instances width + public: TestSubRow(const Box& box): Box(box), _size(0) {} + }; + + typedef list TestSubRowsList; + typedef vector InstanceOccurrencesVector; + typedef list InstanceOccurrencesList; + + void DestroyTestSubRows(TestSubRowsList& testsubrowslist) + { + for (TestSubRowsList::iterator tsrlit = testsubrowslist.begin(); + tsrlit != testsubrowslist.end(); + tsrlit++) + { + delete *tsrlit; + } + testsubrowslist.clear(); + } + + struct sortInstanceOccurrencesByWidth + { + bool operator()(Occurrence occurrence1, Occurrence occurrence2) + { + Instance* instance1 = static_cast(occurrence1.getEntity()); + Instance* instance2 = static_cast(occurrence2.getEntity()); + return instance1->getAbutmentBox().getWidth() > instance2->getAbutmentBox().getWidth(); + } + }; + + bool TryDisplayInstancesInSubRows( + InstanceOccurrencesVector& instanceoccurrencesvector, TestSubRowsList& testsubrowslist) + { + // Try Insert instances in subrows + sort(instanceoccurrencesvector.begin(), instanceoccurrencesvector.end(), sortInstanceOccurrencesByWidth()); + + TestSubRowsList::iterator tsrlit = testsubrowslist.begin(); + InstanceOccurrencesVector::const_iterator insIterator = instanceoccurrencesvector.begin(); + InstanceOccurrencesVector::const_iterator lastLoopInsertedInsIterator = insIterator; + + while(insIterator != instanceoccurrencesvector.end()) + { + if (tsrlit == testsubrowslist.end()) + { + tsrlit = testsubrowslist.begin(); + if (lastLoopInsertedInsIterator != insIterator) + lastLoopInsertedInsIterator = insIterator; + else + { + return false; + } + } + TestSubRow* testSubRow = *tsrlit; + Instance* instance = static_cast(insIterator->getEntity()); + Cell* model = instance->getMasterCell(); + DbU::Unit insWidth = model->getAbutmentBox().getWidth(); + if (insWidth <= testSubRow->getWidth() - testSubRow->_size) + { + testSubRow->_size += insWidth; + ++insIterator; + } + ++tsrlit; + } + return true; + } +} + +bool TestMaukaConstruction(Cell* cell, GCell* gcell) +// ************************************************* +{ + DbU::Unit pitch = getCDataBase()->getDefaultCGPitch(); + DbU::Unit sliceHeight = getCDataBase()->getDefaultCGSliceHeight(); + + const Box& box = gcell->getBox(); + + if (box.isEmpty() || box.isPonctual() ||box.isFlat()) + throw Error("Wrong Box for GCell"); + if (box.getHeight() % sliceHeight) + throw Error("Box Height must be a multiple of Slice Height"); + + InstanceOccurrencesList fixedInstanceOccurrenceList; + InstanceOccurrencesVector toPlaceInstanceOccurrencesVector; + //search for preplaced leaf instances + DbU::Unit instanceToPlaceWidthMax = 0; + for_each_occurrence(occurrence, cell->getLeafInstanceOccurrencesUnder(gcell->getBox())) + { + Instance* instance = static_cast(occurrence.getEntity()); + if (instance->isFixed()) + fixedInstanceOccurrenceList.push_back(occurrence); + else + { + Cell* model = instance->getMasterCell(); + DbU::Unit insWidth = model->getAbutmentBox().getWidth(); + toPlaceInstanceOccurrencesVector.push_back(occurrence); + if (instanceToPlaceWidthMax > insWidth) + instanceToPlaceWidthMax = insWidth; + } + end_for; + } + + DbU::Unit binWidthMax = DbU::lambda((unsigned)( + 2.0 * getValue(instanceToPlaceWidthMax) / getValue(pitch)) * getValue(pitch)); + DbU::Unit binWidthMin = DbU::lambda((unsigned)( + getValue(binWidthMax) / (getValue(pitch) * 2)) * getValue(pitch)); + + TestSubRowsList testSubRowsList; + + if (fixedInstanceOccurrenceList.size() != 0) + { + int width = (unsigned)(gcell->getWidth() / pitch); //number of x pitch + int height = (unsigned)(gcell->getHeight() / sliceHeight); //number of y slices + + + Mauka::PrePlaceTab prePlaceTab(height, Mauka::PrePlaceRow(width, false)); + + for (InstanceOccurrencesList::iterator iolit = fixedInstanceOccurrenceList.begin(); + iolit != fixedInstanceOccurrenceList.end(); + iolit++) + { + Instance* instance = static_cast(iolit->getEntity()); + Box instanceAbutmentBox = instance->getAbutmentBox(); + iolit->getPath().getTransformation().ApplyOn(instanceAbutmentBox); + + Box preplacedBox = gcell->getIntersection(instanceAbutmentBox); + + DbU::Unit insWidth = preplacedBox.getWidth(); + DbU::Unit insHeight = preplacedBox.getHeight(); + + int insPitchWidth = (int)(insWidth / pitch); // largeur ramene au pitch + int insSliceHeight = (int)(insHeight / sliceHeight); // hauteur ramene a la hauteur du slice + + int ypos = (int)((preplacedBox.getYMin() - gcell->getYMin()) / sliceHeight); // position en y ramene au slice + int xpos = (int)((preplacedBox.getXMin() - gcell->getXMin()) / pitch); // position en x ramene au pitch + for (int yit = ypos; yit < ypos + insSliceHeight; yit++) + { + for (int xit = xpos; xit < xpos + insPitchWidth; xit++) + { + if ( (xit > width - 1) || (yit > height - 1) + || (xit < 0 ) || (yit < 0 ) ) + { + cerr << " o ERROR : " << *iolit + << " out of the abutment box" << endl; + exit(1); + } + if (prePlaceTab[yit][xit] == false) + { + prePlaceTab[yit][xit] = true; + } + else + { + cerr << " o ERROR : " << *iolit + << " badly placed .... There is already an instance at its position ...." + << endl; + exit (1); + } + } + } + } + for (int y = 0; y < (int)prePlaceTab.size(); y++) + { + int x = 0; + while (x < (int)prePlaceTab[y].size()) + { + while ((x < (int)prePlaceTab[y].size()) && (prePlaceTab[y][x] == true)) + ++x; + DbU::Unit subRowXMin = gcell->getXMin() + x * pitch; + + if (x >= (int)prePlaceTab[y].size()) + break; + + while ((x < (int)prePlaceTab[y].size()) && (prePlaceTab[y][x] == false)) + ++x; + DbU::Unit subRowXMax = gcell->getXMin() + x * pitch; + if (subRowXMax - subRowXMin > binWidthMin) + { + testSubRowsList.push_back(new TestSubRow( + Box(subRowXMin, gcell->getYMin() + y * sliceHeight + , subRowXMax, gcell->getYMin() + (y+1) * sliceHeight) + )); + } + + } + } + } + else + { + for (DbU::Unit ymin = gcell->getYMin(); ymin <= gcell->getYMax() - sliceHeight; ymin += sliceHeight) + { + testSubRowsList.push_back(new TestSubRow( + Box(gcell->getXMin(), ymin, gcell->getXMax(), ymin + sliceHeight) + )); + } + } + + bool tryInstanceInsertion = TryDisplayInstancesInSubRows(toPlaceInstanceOccurrencesVector, testSubRowsList); + DestroyTestSubRows(testSubRowsList); + return tryInstanceInsertion; +} + + +void Mauka::PlotBinsStats() const +// ****************************** +{ + ofstream out("binsstats.gpl"); + + out << "set noxtics" << endl << "set noytics" << endl + << "set noborder" << endl << "set nokey" << endl + << "set title '" << getCell()->getName() << "'" << endl + << "#set terminal postscript eps color solid" << endl + << "#set output 'binsstats.ps'" << endl; + + _surface->PlotBinsStats(out); +} + +void Mauka::Plot() const +// ********************* +{ + static unsigned count = 0; + string cellNameString = getString(getCell()->getName()) + + "_" + getString(count) + ".gpl"; + ++count; + ofstream out(cellNameString.c_str()); + + out << "set noxtics" << endl << "set noytics" << endl + << "set noborder" << endl << "set nokey" << endl + << "set title '" << cellNameString << "'" << endl + << "#set terminal postscript eps color solid" << endl << "#set output '" + << cellNameString << ".ps'" << endl; + + Box boundingBox = _surface->getBox(); + boundingBox.merge(PlotFixedPointsLabels(out)); + + out << "set xrange[" << boundingBox.getXMin() + << ":" << boundingBox.getXMax() << "]" << endl + << "set yrange[" << boundingBox.getYMin() + << ":" << boundingBox.getYMax() << "]" << endl; + + out << "plot [:][:][:][:] '-' w l, '-' w l 2, '-' w l 3, '-' w l 4" << endl; +// << "plot [:][:][:][:] '-' w l, '-' w l 2, '-' w l 3, '-' w l 4" << endl; + + _surface->Plot(out); + if (_bbPlacer) + _bbPlacer->Plot(out); + else + _simAnnealingPlacer->Plot(out); + + out << "pause -1 'press any key'" << endl; +} + +Box Mauka::PlotFixedPointsLabels(ofstream& out) const +// **************************************************** +{ + Box boundingBox; + + out << "#FixedPoints" << endl; + for (unsigned i = 0; i < _netInstances.size(); i++) + { + if (_hasInitX[i]) + { + + out << "set label \"" + << getString(_nets[i]->getName()) << "\" at " + << _netInitX[i] << "," << _netInitY[i] << " center" + << endl; + } + boundingBox.merge(_netInitX[i], _netInitY[i]); + } + return boundingBox; +} + +void Mauka::hide() { + if (_displaySlot != NULL) { + _displaySlot->hide(); + } +} + +void Mauka::show() { + if (_displaySlot != NULL) { + _displaySlot->show(); + } +} + +unsigned Mauka::getRandomInstanceId() const { + unsigned instanceId = (unsigned)((double)_instanceOccurrencesVector.size() * rand() / (RAND_MAX + 1.0)); + return instanceId; +} + +} diff --git a/mauka/src/Move.cpp b/mauka/src/Move.cpp new file mode 100644 index 00000000..a26b37c0 --- /dev/null +++ b/mauka/src/Move.cpp @@ -0,0 +1,542 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#include +#include +#include + +#include "hurricane/Error.h" +#include "hurricane/Plug.h" + +#include "mauka/MaukaEngine.h" +#include "mauka/Bin.h" +#include "mauka/SubRow.h" +#include "mauka/Row.h" +#include "mauka/MaukaBox.h" +#include "mauka/SimAnnealingPlacer.h" +#include "mauka/Surface.h" +#include "mauka/Move.h" + +namespace { + +using Hurricane::DbU; + +DbU::Unit PositionRand(const DbU::Unit position, const double distance, const DbU::Unit min, const DbU::Unit max) +{ + DbU::Unit borneInf, borneSup; + + if ((borneSup = position + DbU::lambda((int)(distance * DbU::getLambda(max) + 0.5)) ) > max ) + borneSup = max; + + if ((borneInf = position - DbU::lambda((int)(distance * DbU::getLambda(max) + 0.5)) ) < min ) + borneInf = min; + + return borneInf + DbU::lambda((int)(DbU::getLambda(borneSup - borneInf) * rand() / (RAND_MAX+1.0))); +} + +} // End of anonymous namespace. + + +namespace Mauka { + +using namespace std; + +Move::Move(SimAnnealingPlacer* simannealingplacer) + : _simAnnealingPlacer(simannealingplacer) + , _mauka(_simAnnealingPlacer->_mauka) + , _surface(_mauka->_surface) + , _exchange(false) + , _srcIns(0) + , _srcBin(NULL) + , _srcBinInitCost(0.0) + , _srcSubRow(NULL) + , _srcRow(NULL) + , _srcRowInitCost(0.0) + , _srcWidth(0) + , _dstBin(NULL) + , _dstBinInitCost(0.0) + , _dstSubRow(NULL) + , _dstRow(NULL) + , _dstRowInitCost(0.0) + , _dstIns(0) + , _dstWidth(0) + , _affectedNets() +{} + +double Move::getDeltaRowCost() const +{ + double deltaRowCost = -_srcRowInitCost; + deltaRowCost -= _dstRowInitCost; + deltaRowCost += _srcRow->getCost(); + deltaRowCost += _dstRow->getCost(); + return deltaRowCost; +} + +double Move::getDeltaBinCost() const +{ + double deltaBinCost = -_srcBinInitCost; + deltaBinCost -= _dstBinInitCost; + deltaBinCost += _srcBin->getCost(); + deltaBinCost += _dstBin->getCost(); +#if 0 + cerr << "src init cost " << _srcBinInitCost << endl; + cerr << "dst init cost " << _dstBinInitCost << endl; + cerr << "src after cost " << _srcBin->getCost() << endl; + cerr << "dst after cost " << _dstBin->getCost() << endl; + cerr << deltaBinCost << endl; + if (_exchange) + { + cerr << "exchange" << endl; + cerr << "srcWidth " << _srcWidth << endl; + cerr << "dstWidth " << _dstWidth << endl; + cerr << "after .... src " << endl; + cerr << "srcsize " << _srcBin->getSize() << endl; + cerr << "srccapa " << _srcBin->getCapa() << endl; + } + else + { + cerr << "move" << endl; + cerr << _srcWidth << endl; + cerr << "after .... src " << endl; + cerr << _srcBin->getSize() << endl; + cerr << _srcBin->getCapa() << endl; + } +#endif + return deltaBinCost; +} + +static const unsigned NetSrc = 1; +static const unsigned NetDst = 2; +static const unsigned NetSrcDst = 3; + +double Move::getDeltaNetCost() +{ + // Find affected nets + // ================== + _affectedNets.clear(); + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_instanceNets[_srcIns].begin(); + uvit != _mauka->_instanceNets[_srcIns].end(); + uvit++) + { + _affectedNets[*uvit] = NetSrc; + } + + if (_exchange) + { + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_instanceNets[_dstIns].begin(); + uvit != _mauka->_instanceNets[_dstIns].end(); + uvit++) + { + unsigned netId = *uvit; + if (_affectedNets.find(netId) == _affectedNets.end()) + _affectedNets[netId] = NetDst; + else + if (_affectedNets[netId] != NetDst) + _affectedNets[netId] = NetSrcDst; + } + } + + // compute delta + // ============= + + double delta = 0.0; + for (AffectedNets::iterator anit = _affectedNets.begin(); + anit != _affectedNets.end(); + anit++) + { + unsigned netId = anit->first; + unsigned flag = anit->second; + double& netCost = _simAnnealingPlacer->_getNetIdCost(netId); + //cerr << "netCost " << netCost << endl; + double& netTmpCost = _simAnnealingPlacer->_getNetIdTmpCost(netId); + //cerr << "netTmpCost " << netTmpCost << endl; + Box& currBox = _simAnnealingPlacer->_getNetIdBBox(netId); + Box& tmpBox = _simAnnealingPlacer->_getNetTmpBBox(netId); + //cerr << "before" << endl; + //cerr << "currBox " << currBox << endl; + //cerr << "tmpBox " << tmpBox << endl; + + if (flag == NetSrc) + { + tmpBox = currBox; + if ((tmpBox = Update(tmpBox , _srcBin->getCenter(), _dstBin->getCenter())).isEmpty()) + { + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_netInstances[netId].begin(); + uvit != _mauka->_netInstances[netId].end(); + uvit++) + { + unsigned instanceId = *uvit; + Bin* bin = _simAnnealingPlacer->_instanceBins[instanceId]; + tmpBox.merge(bin->getCenter().getX(), bin->getCenter().getY()); + } + } + + if (_mauka->_hasInitX[netId]) + tmpBox.merge(_mauka->_netInitX[netId], tmpBox.getYMin()); + if (_mauka->_hasInitY[netId]) + tmpBox.merge(tmpBox.getXMin(), _mauka->_netInitY[netId]); + + DbU::Unit width = tmpBox.getWidth(); + if (width == 0) + { + width = _srcBin->getWidth() / 2; + } + netTmpCost = DbU::getLambda(tmpBox.getHeight() + width); +#if 0 + cerr << "tmpBox " << tmpBox <_netInstances[netId].begin(); + uvit != _mauka->_netInstances[netId].end(); + uvit++) + { + unsigned instanceId = *uvit; + Bin* bin = _mauka->_instanceBins[instanceId]; + checkBox.merge(bin->getCenter().getX(), bin->getCenter().getY()); + } + + if (checkBox != tmpBox) { + cout << "error: mauvaise bbox : NetSrc" << endl; + cout << " checkBox = " << checkBox << endl; + cout << " tmpBox = " << tmpBox << endl; + cout << " CurrBBox = " << currBox << endl; + cout << " SrcPos = " << _srcBin->getCenter() << endl; + cout << " DstPos = " << _dstBin->getCenter() << endl; + exit(1); + } +#endif + } + else + if (flag == NetDst) + { + tmpBox = currBox; + if ((tmpBox = Update(tmpBox , _dstBin->getCenter(), _srcBin->getCenter())).isEmpty()) + { + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_netInstances[netId].begin(); + uvit != _mauka->_netInstances[netId].end(); + uvit++) + { + Bin* bin = _simAnnealingPlacer->_instanceBins[*uvit]; + tmpBox.merge(bin->getCenter().getX(), bin->getCenter().getY()); + } + } + if (_mauka->_hasInitX[netId]) + tmpBox.merge(_mauka->_netInitX[netId], tmpBox.getYMin()); + if (_mauka->_hasInitY[netId]) + tmpBox.merge(tmpBox.getXMin(), _mauka->_netInitY[netId]); + DbU::Unit width = tmpBox.getWidth(); + if (width == 0) + { + width = _dstBin->getWidth() / 2; + } + netTmpCost = DbU::getLambda(tmpBox.getHeight() + width); +#if 0 + cerr << "netDst" << endl; + cerr << "width " << tmpBox.getWidth() << endl; + cerr << "height " << tmpBox.getHeight() << endl; + cerr << "netTmpCost(netDst) " << netTmpCost << endl << endl; +#endif + delta += netTmpCost - netCost; +#ifdef MOVE_DEBUG + cout << "end" << endl; + cout << "check" << endl; + Box checkBox; + for_each_plug(plug, net); + { + Instance* ins = plug->getInstance(); + SurfContainer* container = PGetContainer(*ins); + cout << container->getXCenter() << " " << container->getYCenter() << endl; + checkBox.merge(container->getXCenter(), container->getYCenter()); + end_for; + } + + if (checkBox != *PTmpBBox(*net)) { + cout << "error: mauvaise bbox : NetDst" << endl; + cout << " check_bbox = " << checkBox << endl; + cout << " TmpBBox = " << PTmpBBox(*net) << endl; + cout << " CurrentBBox = " << PCurrentBBox(*net) << endl; + cout << " SrcPos = " << _dstBin->getPos() << endl; + cout << " DstPos = " << _srcBin->getPos() << endl; + exit(1); + } +#endif + } + } + return delta; +} + +void Move::TryMove() +{ + if (!_exchange) + { + _srcBin->removeInstance(_srcIns); + _dstBin->addInstance(_srcIns); + } + else + { + _srcBin->removeInstance(_srcIns); + _dstBin->removeFrontInstance(_dstIns); + _dstBin->addInstance(_srcIns); + _srcBin->addInstance(_dstIns); + } +} + +bool Move::Next(double dist) +{ + bool moveCondition; + unsigned nbrefused = 0; + + // Choisi un mouvement + // =================== + + do { +#if 0 + if (1) + { + if (dist < 0.4) + for_each_view(view, _mauka->getCell()->getViews()) + { + if (CEditor* editor = dynamic_cast(view)) + { + if (_srcBin) + editor->Unselect(_srcBin); + if (_dstBin && (_dstBin != _srcBin)) + editor->Unselect(_dstBin); + break; + } + end_for; + } + } +#endif + + + moveCondition = true; + + _srcIns = _mauka->getRandomInstanceId(); + assert ( _srcIns < _simAnnealingPlacer->_instanceBins.size() ); // d2 11/02/05 + _srcBin = _simAnnealingPlacer->_instanceBins[_srcIns]; + _srcSubRow = _srcBin->getSubRow(); + _srcRow = _srcSubRow->getRow(); + assert ( _srcIns < _mauka->_instanceWidths.size() ); // d2 11/02/05 + _srcWidth = _mauka->_instanceWidths[_srcIns]; + _srcBinInitCost = _srcBin->getCost(); +#if 0 + cerr << "_srcBin " << endl; + cerr << "srcbinsize " << _srcBin->getSize() << endl; + cerr << "srcbincapa " << _srcBin->getCapa() << endl; +#endif + + _srcRowInitCost = _srcRow->getCost(); + + _dstBin = _surface->getBinInSurface(_srcBin, dist); + _dstSubRow = _dstBin->getSubRow(); + _dstRow = _dstSubRow->getRow(); + +#if 0 + if (1) + { + if (dist < 0.4) + { + for_each_view(view, _mauka->getCell()->getViews()) + { + if (CEditor* editor = dynamic_cast(view)) + { + cerr << _srcBin << endl; + cerr << _srcRow << endl; + cerr << _srcSubRow << endl; + cerr << _dstBin << endl; + cerr << _dstRow << endl; + cerr << _dstSubRow << endl; + cerr << endl; + editor->Select(_srcBin); + if (_dstBin != _srcBin) + editor->Select(_dstBin); + editor->Stop("gli"); + break; + } + end_for; + } + } + } +#endif + + _dstBinInitCost = _dstBin->getCost(); +#if 0 + cerr << "initially .... dst" << endl; + cerr << "dstbinsize " << _dstBin->getSize() << endl; + cerr << "dstbincapa " << _dstBin->getCapa() << endl; +#endif + _dstRowInitCost = _dstRow->getCost(); + + if (_dstBin == _srcBin) + { + _simAnnealingPlacer->incrSourceEqualTargetMovementNumber(); + moveCondition = false; + } + if (moveCondition && _dstBin->UnderOccupied()) + { + _exchange = false; + // Le bin destination est sous-occupé + // On tente de déplacer l'instance + if (_dstSubRow->getWidth() - _dstSubRow->getSize() < _srcWidth) + { + moveCondition = false; + _simAnnealingPlacer->incrSurOccupationTargetMovementNumber(); + } + } + else if (moveCondition) + { + _exchange = true; + _dstIns = _dstBin->getFirstInstanceOccurrenceId(); + assert ( _dstIns < _mauka->_instanceWidths.size() ); // d2 11/02/05 + _dstWidth = _mauka->_instanceWidths[_dstIns]; + + if (_srcSubRow->getWidth() - _srcSubRow->getSize() < _dstWidth - _srcWidth) + { + //Try to move the src ins to dst bin + if (_dstSubRow->getWidth() - _dstSubRow->getSize() < _srcWidth) + { + moveCondition = false; + _simAnnealingPlacer->incrSurOccupationTargetMovementNumber(); + } + _exchange = false; + } + if (_exchange + && (_dstSubRow->getWidth() - _dstSubRow->getSize() < _srcWidth - _dstWidth)) + { + //Try to move the dst ins to src bin + if (_srcSubRow->getWidth() - _srcSubRow->getSize() < _dstWidth) + { + moveCondition = false; + _simAnnealingPlacer->incrSurOccupationTargetMovementNumber(); + } + else + { + _exchange = false; + _srcIns = _dstIns; + _srcWidth = _dstWidth; + Bin* tmpBin = _dstBin; + _dstBin = _srcBin; + _srcBin = tmpBin; + SubRow* tmpSubRow = _dstSubRow; + _dstSubRow = _srcSubRow; + _srcSubRow = tmpSubRow; + Row* tmpRow = _dstRow; + _dstRow = _srcRow; + _srcRow = tmpRow; + double tmp2 = _dstRowInitCost; + _dstRowInitCost = _srcRowInitCost; + _srcRowInitCost = tmp2; + tmp2 = _dstBinInitCost; + _dstBinInitCost = _srcBinInitCost; + _srcBinInitCost = tmp2; + } + } + } + if (!moveCondition) + { + ++nbrefused; + } + if (nbrefused > (unsigned)(1.5 * _mauka->_instanceOccurrencesVector.size())) + return false; + } while (!moveCondition); + + // Deplace les instances + // ===================== + _srcBin->incrementSourceHits(); + _dstBin->incrementTargetHits(); + + TryMove(); + +#if TO_BE_PORTED_UNDER_CORIOLIS_2 + if (_mauka->getRunMode().actionIsOn()) + { + if (dist < 0.4) + for_each_view(view, _mauka->getCell()->getViews()) + { + if (CEditor* editor = dynamic_cast(view)) + { + editor->Refresh(); + editor->Stop("coucou"); + break; + } + end_for; + } + } +#endif + return true; +} + +void +Move::accept() +{ + // Sauvegarde des cout des nets + for (AffectedNets::iterator anit = _affectedNets.begin(); + anit != _affectedNets.end(); + anit++) + { + unsigned netId = anit->first; + unsigned flag = anit->second; + if (flag == NetSrc || flag == NetDst) + { + _simAnnealingPlacer->_InvertNetIdFlag(netId); + } + } +} + +void +Move::Reject() +{ + if (!_exchange) + { + _dstBin->removeBackInstance(_srcIns); + _srcBin->addInstance(_srcIns); + } + else + { + _srcBin->removeBackInstance(_dstIns); + _dstBin->removeBackInstance(_srcIns); + _dstBin->addInstance(_dstIns); + _srcBin->addInstance(_srcIns); + } +} + +} diff --git a/mauka/src/Move.cpp.noRefactor b/mauka/src/Move.cpp.noRefactor new file mode 100644 index 00000000..555efe34 --- /dev/null +++ b/mauka/src/Move.cpp.noRefactor @@ -0,0 +1,541 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#include +#include +#include +using namespace std; + +#include "Error.h" +#include "Plug.h" +USING_NAMESPACE_HURRICANE + +#include "CEditor.h" +using namespace CRL; + +#include "Mauka.h" +#include "Bin.h" +#include "SubRow.h" +#include "Row.h" +#include "MaukaBox.h" +#include "SimAnnealingPlacer.h" +#include "Surface.h" + +#include "Move.h" + +namespace MAUKA { + +namespace { + +Unit PositionRand(const Unit position, const double distance, const Unit min, const Unit max) +{ + Unit borneInf, borneSup; + + if ((borneSup = position + GetUnit((int)(distance * GetValue(max) + 0.5)) ) > max ) + borneSup = max; + + if ((borneInf = position - GetUnit((int)(distance * GetValue(max) + 0.5)) ) < min ) + borneInf = min; + + return borneInf + GetUnit((int)(GetValue(borneSup - borneInf) * rand() / (RAND_MAX+1.0))); +} + +} + +Move::Move(SimAnnealingPlacer* simannealingplacer) + : _simAnnealingPlacer(simannealingplacer) + , _mauka(_simAnnealingPlacer->_mauka) + , _surface(_mauka->_surface) + , _exchange(false) + , _srcIns(0) + , _srcBin(NULL) + , _srcBinInitCost(0.0) + , _srcSubRow(NULL) + , _srcRow(NULL) + , _srcRowInitCost(0.0) + , _srcWidth(0) + , _dstBin(NULL) + , _dstBinInitCost(0.0) + , _dstSubRow(NULL) + , _dstRow(NULL) + , _dstRowInitCost(0.0) + , _dstIns(0) + , _dstWidth(0) + , _affectedNets() +{} + +double Move::GetDeltaRowCost() const +{ + double deltaRowCost = -_srcRowInitCost; + deltaRowCost -= _dstRowInitCost; + deltaRowCost += _srcRow->GetCost(); + deltaRowCost += _dstRow->GetCost(); + return deltaRowCost; +} + +double Move::GetDeltaBinCost() const +{ + double deltaBinCost = -_srcBinInitCost; + deltaBinCost -= _dstBinInitCost; + deltaBinCost += _srcBin->GetCost(); + deltaBinCost += _dstBin->GetCost(); +#if 0 + cerr << "src init cost " << _srcBinInitCost << endl; + cerr << "dst init cost " << _dstBinInitCost << endl; + cerr << "src after cost " << _srcBin->GetCost() << endl; + cerr << "dst after cost " << _dstBin->GetCost() << endl; + cerr << deltaBinCost << endl; + if (_exchange) + { + cerr << "exchange" << endl; + cerr << "srcWidth " << _srcWidth << endl; + cerr << "dstWidth " << _dstWidth << endl; + cerr << "after .... src " << endl; + cerr << "srcsize " << _srcBin->GetSize() << endl; + cerr << "srccapa " << _srcBin->GetCapa() << endl; + } + else + { + cerr << "move" << endl; + cerr << _srcWidth << endl; + cerr << "after .... src " << endl; + cerr << _srcBin->GetSize() << endl; + cerr << _srcBin->GetCapa() << endl; + } +#endif + return deltaBinCost; +} + +static const unsigned NetSrc = 1; +static const unsigned NetDst = 2; +static const unsigned NetSrcDst = 3; + +double Move::GetDeltaNetCost() +{ + // Find affected nets + // ================== + _affectedNets.clear(); + for (Mauka::UVector::const_iterator uvit = _mauka->_instanceNets[_srcIns].begin(); + uvit != _mauka->_instanceNets[_srcIns].end(); + uvit++) + { + _affectedNets[*uvit] = NetSrc; + } + + if (_exchange) + { + for (Mauka::UVector::const_iterator uvit = _mauka->_instanceNets[_dstIns].begin(); + uvit != _mauka->_instanceNets[_dstIns].end(); + uvit++) + { + unsigned netId = *uvit; + if (_affectedNets.find(netId) == _affectedNets.end()) + _affectedNets[netId] = NetDst; + else + if (_affectedNets[netId] != NetDst) + _affectedNets[netId] = NetSrcDst; + } + } + + // Compute delta + // ============= + + double delta = 0.0; + for (AffectedNets::iterator anit = _affectedNets.begin(); + anit != _affectedNets.end(); + anit++) + { + unsigned netId = anit->first; + unsigned flag = anit->second; + double& netCost = _simAnnealingPlacer->_GetNetIdCost(netId); + //cerr << "netCost " << netCost << endl; + double& netTmpCost = _simAnnealingPlacer->_GetNetIdTmpCost(netId); + //cerr << "netTmpCost " << netTmpCost << endl; + Box& currBox = _simAnnealingPlacer->_GetNetIdBBox(netId); + Box& tmpBox = _simAnnealingPlacer->_GetNetTmpBBox(netId); + //cerr << "before" << endl; + //cerr << "currBox " << currBox << endl; + //cerr << "tmpBox " << tmpBox << endl; + + if (flag == NetSrc) + { + tmpBox = currBox; + if ((tmpBox = Update(tmpBox , _srcBin->GetCenter(), _dstBin->GetCenter())).IsEmpty()) + { + for (Mauka::UVector::const_iterator uvit = _mauka->_netInstances[netId].begin(); + uvit != _mauka->_netInstances[netId].end(); + uvit++) + { + unsigned instanceId = *uvit; + Bin* bin = _simAnnealingPlacer->_instanceBins[instanceId]; + tmpBox.Merge(bin->GetCenter().GetX(), bin->GetCenter().GetY()); + } + } + + if (_mauka->_hasInitX[netId]) + tmpBox.Merge(_mauka->_netInitX[netId], tmpBox.GetYMin()); + if (_mauka->_hasInitY[netId]) + tmpBox.Merge(tmpBox.GetXMin(), _mauka->_netInitY[netId]); + + Unit width = tmpBox.GetWidth(); + if (width == 0) + { + width = _srcBin->GetWidth() / 2; + } + netTmpCost = GetValue(tmpBox.GetHeight() + width); +#if 0 + cerr << "tmpBox " << tmpBox <_netInstances[netId].begin(); + uvit != _mauka->_netInstances[netId].end(); + uvit++) + { + unsigned instanceId = *uvit; + Bin* bin = _mauka->_instanceBins[instanceId]; + checkBox.Merge(bin->GetCenter().GetX(), bin->GetCenter().GetY()); + } + + if (checkBox != tmpBox) { + cout << "error: mauvaise bbox : NetSrc" << endl; + cout << " checkBox = " << checkBox << endl; + cout << " tmpBox = " << tmpBox << endl; + cout << " CurrBBox = " << currBox << endl; + cout << " SrcPos = " << _srcBin->GetCenter() << endl; + cout << " DstPos = " << _dstBin->GetCenter() << endl; + exit(1); + } +#endif + } + else + if (flag == NetDst) + { + tmpBox = currBox; + if ((tmpBox = Update(tmpBox , _dstBin->GetCenter(), _srcBin->GetCenter())).IsEmpty()) + { + for (Mauka::UVector::const_iterator uvit = _mauka->_netInstances[netId].begin(); + uvit != _mauka->_netInstances[netId].end(); + uvit++) + { + Bin* bin = _simAnnealingPlacer->_instanceBins[*uvit]; + tmpBox.Merge(bin->GetCenter().GetX(), bin->GetCenter().GetY()); + } + } + if (_mauka->_hasInitX[netId]) + tmpBox.Merge(_mauka->_netInitX[netId], tmpBox.GetYMin()); + if (_mauka->_hasInitY[netId]) + tmpBox.Merge(tmpBox.GetXMin(), _mauka->_netInitY[netId]); + Unit width = tmpBox.GetWidth(); + if (width == 0) + { + width = _dstBin->GetWidth() / 2; + } + netTmpCost = GetValue(tmpBox.GetHeight() + width); +#if 0 + cerr << "netDst" << endl; + cerr << "width " << tmpBox.GetWidth() << endl; + cerr << "height " << tmpBox.GetHeight() << endl; + cerr << "netTmpCost(netDst) " << netTmpCost << endl << endl; +#endif + delta += netTmpCost - netCost; +#ifdef MOVE_DEBUG + cout << "end" << endl; + cout << "check" << endl; + Box checkBox; + for_each_plug(plug, net); + { + Instance* ins = plug->GetInstance(); + SurfContainer* container = PGetContainer(*ins); + cout << container->GetXCenter() << " " << container->GetYCenter() << endl; + checkBox.Merge(container->GetXCenter(), container->GetYCenter()); + end_for; + } + + if (checkBox != *PTmpBBox(*net)) { + cout << "error: mauvaise bbox : NetDst" << endl; + cout << " check_bbox = " << checkBox << endl; + cout << " TmpBBox = " << PTmpBBox(*net) << endl; + cout << " CurrentBBox = " << PCurrentBBox(*net) << endl; + cout << " SrcPos = " << _dstBin->GetPos() << endl; + cout << " DstPos = " << _srcBin->GetPos() << endl; + exit(1); + } +#endif + } + } + return delta; +} + +void Move::TryMove() +{ + if (!_exchange) + { + _srcBin->RemoveInstance(_srcIns); + _dstBin->AddInstance(_srcIns); + } + else + { + _srcBin->RemoveInstance(_srcIns); + _dstBin->RemoveFrontInstance(_dstIns); + _dstBin->AddInstance(_srcIns); + _srcBin->AddInstance(_dstIns); + } +} + +bool Move::Next(double dist) +{ + bool moveCondition; + unsigned nbrefused = 0; + + // Choisi un mouvement + // =================== + + do { +#if 0 + if (1) + { + if (dist < 0.4) + for_each_view(view, _mauka->GetCell()->GetViews()) + { + if (CEditor* editor = dynamic_cast(view)) + { + if (_srcBin) + editor->Unselect(_srcBin); + if (_dstBin && (_dstBin != _srcBin)) + editor->Unselect(_dstBin); + break; + } + end_for; + } + } +#endif + + + moveCondition = true; + + _srcIns = _mauka->GetRandomInstanceId(); + assert ( _srcIns < _simAnnealingPlacer->_instanceBins.size() ); // d2 11/02/05 + _srcBin = _simAnnealingPlacer->_instanceBins[_srcIns]; + _srcSubRow = _srcBin->GetSubRow(); + _srcRow = _srcSubRow->GetRow(); + assert ( _srcIns < _mauka->_instanceWidths.size() ); // d2 11/02/05 + _srcWidth = _mauka->_instanceWidths[_srcIns]; + _srcBinInitCost = _srcBin->GetCost(); +#if 0 + cerr << "_srcBin " << endl; + cerr << "srcbinsize " << _srcBin->GetSize() << endl; + cerr << "srcbincapa " << _srcBin->GetCapa() << endl; +#endif + + _srcRowInitCost = _srcRow->GetCost(); + + _dstBin = _surface->GetBinInSurface(_srcBin, dist); + _dstSubRow = _dstBin->GetSubRow(); + _dstRow = _dstSubRow->GetRow(); + +#if 0 + if (1) + { + if (dist < 0.4) + { + for_each_view(view, _mauka->GetCell()->GetViews()) + { + if (CEditor* editor = dynamic_cast(view)) + { + cerr << _srcBin << endl; + cerr << _srcRow << endl; + cerr << _srcSubRow << endl; + cerr << _dstBin << endl; + cerr << _dstRow << endl; + cerr << _dstSubRow << endl; + cerr << endl; + editor->Select(_srcBin); + if (_dstBin != _srcBin) + editor->Select(_dstBin); + editor->Stop("gli"); + break; + } + end_for; + } + } + } +#endif + + _dstBinInitCost = _dstBin->GetCost(); +#if 0 + cerr << "initially .... dst" << endl; + cerr << "dstbinsize " << _dstBin->GetSize() << endl; + cerr << "dstbincapa " << _dstBin->GetCapa() << endl; +#endif + _dstRowInitCost = _dstRow->GetCost(); + + if (_dstBin == _srcBin) + { + _simAnnealingPlacer->IncrSourceEqualTargetMovementNumber(); + moveCondition = false; + } + if (moveCondition && _dstBin->UnderOccupied()) + { + _exchange = false; + // Le bin destination est sous-occupé + // On tente de déplacer l'instance + if (_dstSubRow->GetWidth() - _dstSubRow->GetSize() < _srcWidth) + { + moveCondition = false; + _simAnnealingPlacer->IncrSurOccupationTargetMovementNumber(); + } + } + else if (moveCondition) + { + _exchange = true; + _dstIns = _dstBin->GetFirstInstanceOccurrenceId(); + assert ( _dstIns < _mauka->_instanceWidths.size() ); // d2 11/02/05 + _dstWidth = _mauka->_instanceWidths[_dstIns]; + + if (_srcSubRow->GetWidth() - _srcSubRow->GetSize() < _dstWidth - _srcWidth) + { + //Try to move the src ins to dst bin + if (_dstSubRow->GetWidth() - _dstSubRow->GetSize() < _srcWidth) + { + moveCondition = false; + _simAnnealingPlacer->IncrSurOccupationTargetMovementNumber(); + } + _exchange = false; + } + if (_exchange + && (_dstSubRow->GetWidth() - _dstSubRow->GetSize() < _srcWidth - _dstWidth)) + { + //Try to move the dst ins to src bin + if (_srcSubRow->GetWidth() - _srcSubRow->GetSize() < _dstWidth) + { + moveCondition = false; + _simAnnealingPlacer->IncrSurOccupationTargetMovementNumber(); + } + else + { + _exchange = false; + _srcIns = _dstIns; + _srcWidth = _dstWidth; + Bin* tmpBin = _dstBin; + _dstBin = _srcBin; + _srcBin = tmpBin; + SubRow* tmpSubRow = _dstSubRow; + _dstSubRow = _srcSubRow; + _srcSubRow = tmpSubRow; + Row* tmpRow = _dstRow; + _dstRow = _srcRow; + _srcRow = tmpRow; + double tmp2 = _dstRowInitCost; + _dstRowInitCost = _srcRowInitCost; + _srcRowInitCost = tmp2; + tmp2 = _dstBinInitCost; + _dstBinInitCost = _srcBinInitCost; + _srcBinInitCost = tmp2; + } + } + } + if (!moveCondition) + { + ++nbrefused; + } + if (nbrefused > (unsigned)(1.5 * _mauka->_instanceOccurrencesVector.size())) + return false; + } while (!moveCondition); + + // Deplace les instances + // ===================== + _srcBin->IncrementSourceHits(); + _dstBin->IncrementTargetHits(); + + TryMove(); + + if (_mauka->_verbosity.ActionIsOn()) + { + if (dist < 0.4) + for_each_view(view, _mauka->GetCell()->GetViews()) + { + if (CEditor* editor = dynamic_cast(view)) + { + editor->Refresh(); + editor->Stop("coucou"); + break; + } + end_for; + } + } + return true; +} + +void +Move::Accept() +{ + // Sauvegarde des cout des nets + for (AffectedNets::iterator anit = _affectedNets.begin(); + anit != _affectedNets.end(); + anit++) + { + unsigned netId = anit->first; + unsigned flag = anit->second; + if (flag == NetSrc || flag == NetDst) + { + _simAnnealingPlacer->_InvertNetIdFlag(netId); + } + } +} + +void +Move::Reject() +{ + if (!_exchange) + { + _dstBin->RemoveBackInstance(_srcIns); + _srcBin->AddInstance(_srcIns); + } + else + { + _srcBin->RemoveBackInstance(_dstIns); + _dstBin->RemoveBackInstance(_srcIns); + _dstBin->AddInstance(_dstIns); + _srcBin->AddInstance(_srcIns); + } +} + +} diff --git a/mauka/src/Row.cpp b/mauka/src/Row.cpp new file mode 100644 index 00000000..3bbe1fd0 --- /dev/null +++ b/mauka/src/Row.cpp @@ -0,0 +1,252 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag + +#include "mauka/SubRow.h" +#include "mauka/Surface.h" +#include "mauka/Row.h" + +namespace Mauka { + +using Hurricane::Error; + +Row::Row(Cell* cell, Surface* surface, const Box& box, bool orientation) + :Inherit(cell, box) + , _surface(surface) + , _subRowVector() + , _subRowXMax() + , _subRowXMinInv() + , _orientation(orientation) + , _size(0) + , _capa(0) +{} + +Row* Row::create(Cell* cell, Surface* surface, const Box& box, bool orientation) +{ + if (!surface) + throw Error("Can't create Mauka::Row : empty surface"); + Row* row = new Row(cell, surface, box, orientation); + row->_postCreate(); + return row; +} + +void Row::_preDestroy() +{ + Inherit::_preDestroy(); + for (SubRowVector::iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + (*srit)->destroy(); + } + _subRowVector.clear(); +} + +namespace { + + using namespace Hurricane; + + struct SubRowSortByX + { + bool operator()(const SubRow* subrow1, const SubRow* subrow2) const + { + return subrow1->getXMin() < subrow2->getXMin(); + } + }; +} + +void Row::_InsertSubRow(SubRow* subrow) +{ + if (_subRowVector.size() == 0) + _subRowVector.push_back(subrow); + else + { + SubRowVector::iterator srvit = lower_bound(_subRowVector.begin(), _subRowVector.end(), subrow, SubRowSortByX()); + if (srvit == _subRowVector.end()) + { + _subRowVector.push_back(subrow); + } + else if ((*srvit)->getXMin() == subrow->getXMin()) + { + throw Error("Bug in SubRow insertion"); + } + else + { + _subRowVector.insert(srvit, subrow); + } + } + _box.merge(subrow->getBox()); +} + +void Row::_computeSubRows() +{ + _subRowXMax.clear(); + _subRowXMinInv.clear(); + for (unsigned i = 0; i < _subRowVector.size(); i++) + { + SubRow* subRow = _subRowVector[i]; + _subRowXMax[subRow->getXMax()] = i; + _subRowXMinInv[subRow->getXMin()] = i; + } +} + +SubRow* Row::getSubRowBetween(DbU::Unit x1, DbU::Unit x2) +{ + assert(x1 <= x2); + assert(x1 >= getXMin()); + assert(x2 <= getXMax()); + + if (_subRowVector.size() == 1) + return _subRowVector[0]; + + SubRowXMax::iterator rinf = _subRowXMax.upper_bound(x1); + SubRowXMax::iterator rsup = _subRowXMinInv.upper_bound(x2); + + + unsigned randidx = rinf->second + + (unsigned)((rsup->second - rinf->second + 1) * (rand() / (RAND_MAX+1.0))); +#if 0 + //cerr << x1 << endl; + //cerr << x2 << endl; + for (SubRowXMax::iterator srit = _subRowXMax.begin(); + srit != _subRowXMax.end(); + srit++) + { + cerr << srit->first << "," << srit->second << endl; + } + cerr << randidx << endl << endl;; +#endif + + return _subRowVector[randidx]; +} + +void Row::_AddSize(DbU::Unit value) +{ + _size += value; +} + +double Row::getCost() const +{ + return abs(DbU::getLambda(_size - _capa)); +} + +double Row::getBinCost() const +{ + double binCost = 0.0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + binCost += (*srit)->getBinCost(); + } + return binCost; +} + +DbU::Unit Row::getBinsSize() const +{ + DbU::Unit totalBinsSize = 0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + totalBinsSize += (*srit)->getBinsSize(); + } + return totalBinsSize; +} + +DbU::Unit Row::getBinsCapa() const +{ + DbU::Unit totalBinsCapa = 0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + totalBinsCapa += (*srit)->getBinsCapa(); + } + return totalBinsCapa; +} + +DbU::Unit Row::getSubRowsWidth() const +{ + DbU::Unit subRowsWidth = 0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + subRowsWidth += (*srit)->getWidth(); + } + return subRowsWidth; +} + +DbU::Unit Row::getSubRowsCapa() const +{ + DbU::Unit totalSubRowsCapa = 0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + totalSubRowsCapa += (*srit)->getCapa(); + } + return totalSubRowsCapa; +} + +void Row::_computeCapacity(double margin) +{ + _capa = 0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + (*srit)->_computeCapacity(margin); + _capa += (*srit)->_capa; + } +} + +void Row::DisplayBinHits() const +{ + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + (*srit)->DisplayBinHits(); + } +} + +Cell* Row::getCell() const +{ + return _surface->getCell(); +} + +} diff --git a/mauka/src/Row.cpp.noRefactor b/mauka/src/Row.cpp.noRefactor new file mode 100644 index 00000000..cc857391 --- /dev/null +++ b/mauka/src/Row.cpp.noRefactor @@ -0,0 +1,249 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag + +#include "SubRow.h" +#include "Surface.h" + +#include "Row.h" + +namespace MAUKA { + +Row::Row(Cell* cell, Surface* surface, const Box& box, bool orientation) + :Inherit(cell, box) + , _surface(surface) + , _subRowVector() + , _subRowXMax() + , _subRowXMinInv() + , _orientation(orientation) + , _size(0) + , _capa(0) +{} + +Row* Row::Create(Cell* cell, Surface* surface, const Box& box, bool orientation) +{ + if (!surface) + throw Error("Can't create " + _TName("Row") + " : empty surface"); + Row* row = new Row(cell, surface, box, orientation); + row->_PostCreate(); + return row; +} + +void Row::_PreDelete() +{ + Inherit::_PreDelete(); + for (SubRowVector::iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + (*srit)->Delete(); + } + _subRowVector.clear(); +} + +namespace { + + struct SubRowSortByX + { + bool operator()(const SubRow* subrow1, const SubRow* subrow2) const + { + return subrow1->GetXMin() < subrow2->GetXMin(); + } + }; +} + +void Row::_InsertSubRow(SubRow* subrow) +{ + if (_subRowVector.size() == 0) + _subRowVector.push_back(subrow); + else + { + SubRowVector::iterator srvit = lower_bound(_subRowVector.begin(), _subRowVector.end(), subrow, SubRowSortByX()); + if (srvit == _subRowVector.end()) + { + _subRowVector.push_back(subrow); + } + else if ((*srvit)->GetXMin() == subrow->GetXMin()) + { + throw Error("Bug in SubRow insertion"); + } + else + { + _subRowVector.insert(srvit, subrow); + } + } + _box.Merge(subrow->GetBox()); +} + +void Row::_ComputeSubRows() +{ + _subRowXMax.clear(); + _subRowXMinInv.clear(); + for (unsigned i = 0; i < _subRowVector.size(); i++) + { + SubRow* subRow = _subRowVector[i]; + _subRowXMax[subRow->GetXMax()] = i; + _subRowXMinInv[subRow->GetXMin()] = i; + } +} + +SubRow* Row::GetSubRowBetween(Unit x1, Unit x2) +{ + assert(x1 <= x2); + assert(x1 >= GetXMin()); + assert(x2 <= GetXMax()); + + if (_subRowVector.size() == 1) + return _subRowVector[0]; + + SubRowXMax::iterator rinf = _subRowXMax.upper_bound(x1); + SubRowXMax::iterator rsup = _subRowXMinInv.upper_bound(x2); + + + unsigned randidx = rinf->second + + (unsigned)((rsup->second - rinf->second + 1) * (rand() / (RAND_MAX+1.0))); +#if 0 + //cerr << x1 << endl; + //cerr << x2 << endl; + for (SubRowXMax::iterator srit = _subRowXMax.begin(); + srit != _subRowXMax.end(); + srit++) + { + cerr << srit->first << "," << srit->second << endl; + } + cerr << randidx << endl << endl;; +#endif + + return _subRowVector[randidx]; +} + +void Row::_AddSize(Unit value) +{ + _size += value; +} + +double Row::GetCost() const +{ + return abs(GetValue(_size - _capa)); +} + +double Row::GetBinCost() const +{ + double binCost = 0.0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + binCost += (*srit)->GetBinCost(); + } + return binCost; +} + +Unit Row::GetBinsSize() const +{ + Unit totalBinsSize = 0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + totalBinsSize += (*srit)->GetBinsSize(); + } + return totalBinsSize; +} + +Unit Row::GetBinsCapa() const +{ + Unit totalBinsCapa = 0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + totalBinsCapa += (*srit)->GetBinsCapa(); + } + return totalBinsCapa; +} + +Unit Row::GetSubRowsWidth() const +{ + Unit subRowsWidth = 0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + subRowsWidth += (*srit)->GetWidth(); + } + return subRowsWidth; +} + +Unit Row::GetSubRowsCapa() const +{ + Unit totalSubRowsCapa = 0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + totalSubRowsCapa += (*srit)->GetCapa(); + } + return totalSubRowsCapa; +} + +void Row::_ComputeCapacity(double margin) +{ + _capa = 0; + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + (*srit)->_ComputeCapacity(margin); + _capa += (*srit)->_capa; + } +} + +void Row::DisplayBinHits() const +{ + for (SubRowVector::const_iterator srit = _subRowVector.begin(); + srit != _subRowVector.end(); + srit++) + { + (*srit)->DisplayBinHits(); + } +} + +Cell* Row::GetCell() const +{ + return _surface->GetCell(); +} + +} diff --git a/mauka/src/SimAnnealingPlacer.cpp b/mauka/src/SimAnnealingPlacer.cpp new file mode 100644 index 00000000..ca2b646a --- /dev/null +++ b/mauka/src/SimAnnealingPlacer.cpp @@ -0,0 +1,666 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag + +#include + +#include "hurricane/Warning.h" +#include "hurricane/Cell.h" +#include "hurricane/UpdateSession.h" +#include "crlcore/Utilities.h" +#include "crlcore/ToolBox.h" + +#include "mauka/Surface.h" +#include "mauka/Bin.h" +#include "mauka/Row.h" +#include "mauka/MaukaEngine.h" +#include "mauka/Move.h" +#include "mauka/SimAnnealingPlacer.h" + +namespace { + +using Hurricane::Error; +using Hurricane::Warning; +using Hurricane::Transformation; +using Hurricane::UpdateSession; +using CRL::getTransformation; + +double computeStdDev(double sumcost, double sumsquare, unsigned accepted) +{ + if (accepted <= 1) + return 0.0; + + double stdDev = (sumsquare - sumcost * sumcost / (double)accepted) / ((double)accepted - 1.0); + if (stdDev > 0.0) + stdDev = sqrt(stdDev); + else + stdDev = 0.0; + + return stdDev; +} + +} + +namespace Mauka { + +using namespace std; + +SimAnnealingPlacer::SimAnnealingPlacer(MaukaEngine* mauka) +// ******************************************************* + : _mauka(mauka) + , _instanceBins() + , _netBBoxes() + , _netCosts() + , _netFlags() + , _netCost(0.0) + , _binCost(0.0) + , _rowCost(0.0) + , _initNetCost(0.0) + , _initBinCost(0.0) + , _initRowCost(0.0) + , _netMult(_mauka->getAnnealingNetMult()) + , _binMult(_mauka->getAnnealingBinMult()) + , _rowMult(_mauka->getAnnealingRowMult()) + , _temperature(0.0) + , _distance(0.0) + , _loop(0) + , _iterationsFactor(0) + , _iterations(0) + , _moves(0) + , _sourceEqualTargetMovementNumber(0) + , _surOccupationTargetMovementNumber(0) + , _impossibleExchangeMovementNumber(0) +{ + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + _instanceBins.push_back(NULL); + } + + for (unsigned netid = 0; netid < _mauka->_nets.size(); netid++) + { + vector bboxes(2); + _netBBoxes.push_back(bboxes); + vector costs(2); + _netCosts.push_back(costs); + _netFlags.push_back(0); + } + +} + +void SimAnnealingPlacer::init() +{ + Surface* surface = _mauka->_surface; + if (!surface) + throw Error("Cannot init with no surface ..."); + + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + if (_instanceBins[i] == NULL) + cerr << "no bin for " << _mauka->_instanceOccurrencesVector[i] << endl; + } + + _initNetCost = _netCost = getNetCost(); + _initBinCost = _binCost = surface->getBinCost(); + _initRowCost = _rowCost = surface->getRowCost(); + + double stdDev = 0.0; + double sumCost = 0.0; + double sumSquare = 0.0; + unsigned accepted = 0; + + _temperature = 1e30; + _distance = 1.0; + + cmess1 << " o Beginning global placement" << endl; + cmess2 << Dots::asSizet (" - Number of nodes to place",_mauka->_instanceOccurrencesVector.size()) << endl; + cmess2 << Dots::asPercentage(" - Margin" ,100.0 * surface->getMargin()) << endl; + + cmess2 << Dots::asDouble(" - Initial RowCost" ,_rowCost) << endl; + cmess2 << Dots::asDouble(" - Initial BinCost" ,_binCost) << endl; + cmess2 << Dots::asDouble(" - Initial NetCost" ,_netCost) << endl; + cmess2 << Dots::asDouble(" - Initial Cost" ,getCost()) << endl; + cmess2 << Dots::asLambda(" - Total bins capa" ,surface->getBinsCapa()) << endl; + cmess2 << Dots::asLambda(" - Total bins size" ,surface->getBinsSize()) << endl; + cmess2 << Dots::asLambda(" - Total subrows capa",surface->getSubRowsCapa()) << endl; + cmess1 << " o Computing initial Temperature ..."; + + Move move(this); + + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + if (!move.Next(_distance)) + { + cmess2 << " o No more mouvement possible..." << endl; + return; + } + + double deltaRowCost = move.getDeltaRowCost(); + double deltaBinCost = move.getDeltaBinCost(); + double deltaNetCost = move.getDeltaNetCost(); + + double deltaCost = computeCost(deltaRowCost, deltaBinCost, deltaNetCost); + + + if (accept(deltaCost)) + { + move.accept(); + accepted += 1; + _rowCost += deltaRowCost; + _netCost += deltaNetCost; + _binCost += deltaBinCost; + double cost = getCost(); + sumCost += cost; sumSquare += cost * cost; + //sumCost += deltaCost; sumSquare += deltaCost * deltaCost; + } + else + { + move.Reject(); + } + ++_moves; + } + + stdDev = computeStdDev(sumCost, sumSquare, accepted); + _temperature = 20.0 * stdDev; + _iterationsFactor = 15; + _iterations = (unsigned)(_iterationsFactor * pow(_mauka->_instanceOccurrencesVector.size(), 1.33)); + + if (false) + { + double debug = DebugNetCost(); + cout << "debug = " << debug << endl; + cout << "NetCost = " << _netCost << endl << endl; + // assert ((netCost - 1.0 <= debug) && (debug <= netCost + 1.0)); + } + + cmess1 << " done" << endl; +} + + +bool SimAnnealingPlacer::Iterate() +{ + unsigned accepted = 0; + double sumCost = 0.0; + double sumSquare = 0.0; + double stdDev = 0.0, sucRatio = 0.0; + double oldTemperature = 0.0; + + Move move(this); + + for (unsigned i = 0; i < _iterations; ++i) + { + if (!move.Next(_distance)) + { + cmess1 << " o No More Mouvement Possible ....." << endl; + return false; + } + + double deltaRowCost = move.getDeltaRowCost(); + double deltaBinCost = move.getDeltaBinCost(); + double deltaNetCost = move.getDeltaNetCost(); + + double deltaCost = computeCost(deltaRowCost, deltaBinCost, deltaNetCost); + +#if 0 + cerr << deltaRowCost << endl; + cerr << deltaBinCost << endl; + cerr << deltaNetCost << endl; + cerr << deltaCost << endl << endl; +#endif + + if (accept(deltaCost)) { + move.accept(); + + accepted += 1; + _rowCost += deltaRowCost; + _binCost += deltaBinCost; + _netCost += deltaNetCost; + double cost = getCost(); + sumCost += cost; sumSquare += cost * cost; + //sumCost += deltaCost; sumSquare += deltaCost * deltaCost; + } + else + { + move.Reject(); + } + ++_moves; + } + ++_loop; + + oldTemperature = _temperature; + stdDev = computeStdDev(sumCost, sumSquare, accepted); + + if (stdDev == 0.0) + _temperature = 0.0; + else + _temperature = _temperature * max(0.5, exp(-0.7 * _temperature / stdDev)); + + sucRatio = accepted / (double)_iterations; + _distance = max(0.1, min(_distance * (1.0 - 0.44 + sucRatio), 1.0)); + + cmess2 << " - Loop:" << setw(4) << setfill('0')<< _loop + << " NIns:" << _mauka->_instanceOccurrencesVector.size() + << " Temperature:" << _temperature + << " Cost:" << getCost() << endl; + cmess2 << " RowCost:" << _rowCost + << " BinCost:" << _binCost + << " NetCost:" << _netCost << endl; + cmess2 << " Success Ratio:" << sucRatio * 100.0 + << "% Dist:" << _distance + << " Delta:" << _temperature / oldTemperature << endl; + + if (false) + { + double debug = DebugNetCost(); + cout << "debug = " << debug << endl; + cout << "NetCost = " << _netCost << endl << endl; + // assert ((netCost - 1.0 <= debug) && (debug <= netCost + 1.0)); + } + return ((_temperature != 0.0) + && ((sucRatio > 0.15) || (stdDev > (0.0001 / getCost())))); +} + +double SimAnnealingPlacer::getNetCost() +// ************************************ +{ + double totalNetCost = 0.0; + for (unsigned netid = 0; netid < _mauka->_netInstances.size(); netid++) + { + unsigned lastInstanceId = 0; + unsigned insCount = 0; + Box& netBBox = _netBBoxes[netid][_netFlags[netid]]; + + double& netCost = _netCosts[netid][_netFlags[netid]]; + netCost = 0.0; + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_netInstances[netid].begin(); + uvit != _mauka->_netInstances[netid].end(); + uvit++) + { + unsigned instanceId = *uvit; + lastInstanceId = instanceId; + Bin* bin = _instanceBins[instanceId]; + netBBox.merge(bin->getCenter().getX(), bin->getCenter().getY()); + ++insCount; + } + if (_mauka->_hasInitX[netid]) + netBBox.merge(_mauka->_netInitX[netid], netBBox.getYMin()); + if (_mauka->_hasInitY[netid]) + netBBox.merge(netBBox.getXMin(), _mauka->_netInitY[netid]); + + if ( insCount == 0 ) + { + cerr << Warning("Net <%s> is not connected.",getString(_mauka->_nets[netid]).c_str()) << endl; + } + else + { + DbU::Unit width = 0; +#if 0 + if (_mauka->_params.takeSplittersIntoAccountOptimization) + { + Instance* instance = _instanceOccurrences[lastInstanceId]; + Net* net = _nets[netid]; + Plug* netPlug = NULL; + for_each_plug(plug, instance->getConnectedPlugs()) + { + Net* plugNet = plug->getNet(); + if (plugNet == net) + { + netPlug = plug; + break; + } + end_for; + } + if (!netPlug) + throw Error("MaukaEngine internal error: no plug"); + Hook* bodyHook = netPlug->getBodyHook(); + for_each_hook(hook, bodyHook->getHooks()) + { + Component* component = hook->getComponent(); + if (SplitterContact* splitterContact = dynamic_cast(component)) + { + if (VFence* vfence = dynamic_cast(splitterContact->getSplitter()->getFence())) + { + if (_hasInitX[netid]) + _hasInitX[netid] = false; + else + { + _hasInitX[netid] = true; + _netInitX[netid] = vfence->getX(); + } + } + else if (HFence* hfence = dynamic_cast(splitterContact->getSplitter()->getFence())) + { + if (_hasInitY[netid]) + _hasInitY[netid] = false; + else + { + _hasInitY[netid] = true; + _netInitY[netid] = hfence->getY(); + } + } + else throw Error("MaukaEngine internal error"); + } + else if (Pin* pin = dynamic_cast(component)) + { + if (not _mauka->odIgnorePins()) + { + netBBox.merge(pin->getX(), pin->getY()); + } + } + end_for; + } + if (_hasInitX[netid]) + netBBox.merge(_netInitX[netid], netBBox.getYMin()); + if (_hasInitY[netid]) + netBBox.merge(netBBox.getXMin(), _netInitY[netid]); + } +#endif + width = netBBox.getWidth(); + if (width == 0) + { + //all instances in the same bin... + //take for width half of the bin + Bin* bin = _instanceBins[lastInstanceId]; + width = bin->getWidth() / 2; + } + double cost = DbU::getLambda(netBBox.getHeight() + width); + netCost = cost; + totalNetCost += cost; + } + } + return totalNetCost; +} + +double SimAnnealingPlacer::DebugNetCost() +// ************************************** +{ + double totalNetCost = 0.0; + for (unsigned netid = 0; netid < _mauka->_netInstances.size(); netid++) + { + unsigned lastInstanceId = 0; + unsigned insCount = 0; + Box box; + for (MaukaEngine::UVector::const_iterator uvit = _mauka->_netInstances[netid].begin(); + uvit != _mauka->_netInstances[netid].end(); + uvit++) + { + unsigned instanceId = *uvit; + lastInstanceId = instanceId; + Bin* bin = _instanceBins[instanceId]; + box.merge(bin->getCenter().getX(), bin->getCenter().getY()); + ++insCount; + } + + if (insCount) + { +#if 0 + if (_mauka->_params.takeSplittersIntoAccountOptimization) + { + Occurrence instanceOccurrence = _instanceOccurrences[lastInstanceId]; + Instance* instance = dynamic_cast(instanceOccurrence.getEntity()); + assert(instance); + Net* net = _nets[netid]; + Plug* netPlug = NULL; + for_each_plug(plug, instance->getConnectedPlugs()) + { + Net* plugNet = plug->getNet(); + if (plugNet == net) + { + netPlug = plug; + break; + } + end_for; + } + if (!netPlug) + throw Error("MaukaEngine internal error: no plug"); + Hook* bodyHook = netPlug->getBodyHook(); + bool hasInitX = false; + bool hasInitY = false; + DbU::Unit netInitX = 0; + DbU::Unit netInitY = 0; + for_each_hook(hook, bodyHook->getHooks()) + { + if (SplitterContact* splitterContact = dynamic_cast(hook->getComponent())) + { + if (VFence* vfence = dynamic_cast(splitterContact->getSplitter()->getFence())) + { + if (hasInitX) + hasInitX = false; + else + { + hasInitX = true; + netInitX = vfence->getX(); + } + } + else if (HFence* hfence = dynamic_cast(splitterContact->getSplitter()->getFence())) + { + if (hasInitY) + hasInitY = false; + else + { + hasInitY = true; + netInitY = hfence->getY(); + } + } + else throw Error("MaukaEngine internal error"); + } + end_for; + } + if (hasInitX) + box.merge(netInitX, box.getYMin()); + if (hasInitY) + box.merge(box.getXMin(), netInitY); + } +#endif + DbU::Unit width = box.getWidth(); + if (width == 0) + { + //all instances in the same bin... + //take for width half of the bin + Bin* bin = _instanceBins[lastInstanceId]; + width = bin->getWidth() / 2; + } + totalNetCost += DbU::getLambda(box.getHeight() + width); + } + } + return totalNetCost; +} + +void SimAnnealingPlacer::DisplayResults() const +{ + unsigned totalImpossibleMovements + = _impossibleExchangeMovementNumber + + _sourceEqualTargetMovementNumber + + _surOccupationTargetMovementNumber; + + cmess2 << Dots::asUInt (" - Total impossible movements",totalImpossibleMovements) << endl; + cmess2 << Dots::asPercentage(" - Suroccupied target" ,100.0 * _surOccupationTargetMovementNumber / totalImpossibleMovements) << endl; + cmess2 << Dots::asPercentage(" - Source equal target" ,100.0 * _sourceEqualTargetMovementNumber / totalImpossibleMovements) << endl; + cmess2 << Dots::asPercentage(" - Impossible exchange" ,100.0 * _impossibleExchangeMovementNumber / totalImpossibleMovements) << endl; + cmess1 << " o Global Placement finished" << endl; + cmess2 << Dots::asPercentage(" - Gain for RowCost" ,100.0 * (_initRowCost - _rowCost) / _initRowCost) << endl; + cmess2 << Dots::asPercentage(" - Gain for BinCost" ,100.0 * (_initBinCost - _binCost) / _initBinCost) << endl; + cmess2 << Dots::asPercentage(" - Gain for NetCost" ,100.0 * (_initNetCost - _netCost) / _initNetCost) << endl; + cmess2 << Dots::asDouble (" - NetCost Estimated",_netCost) << endl; +} + +double SimAnnealingPlacer::getCost() const +{ + return computeCost(_rowCost, _binCost, _netCost); +} + +double SimAnnealingPlacer::computeCost(double rowcost, double bincost, double netcost) const +{ + return rowcost / _initRowCost * _rowMult + + bincost / _initBinCost * _binMult + + netcost / _initNetCost * _netMult; +} + +bool SimAnnealingPlacer::accept(double deltacost) const +{ + if (_mauka->useStandardSimulatedAnnealing()) + { + double doubleRand = (double) (rand() / (RAND_MAX + 1.0)); + return ((deltacost <= 0.0) + || ((_temperature != 0.0) + && (exp(-deltacost / _temperature) > doubleRand))); + } + else + return deltacost <= 0.0; +} + + +void SimAnnealingPlacer::Save() const +{ + UpdateSession::open(); + for(unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[i]; + Instance* instance = static_cast(instanceOccurrence.getEntity()); + Bin* bin = _instanceBins[i]; + bool rowOrientation = bin->getSubRow()->getRow()->getOrientation(); + if (!bin) + throw Error("No bin for instance"); + DbU::Unit xPos = bin->getCenter().getX(); + DbU::Unit yPos = bin->getCenter().getY(); + Box masterABox = instance->getMasterCell()->getAbutmentBox(); + Transformation::Orientation orientation; + if (rowOrientation) + orientation = Transformation::Orientation::ID; + else + orientation = Transformation::Orientation::MY; + Transformation instanceTransformation = getTransformation(masterABox + , xPos - masterABox.getHalfWidth() + , yPos - masterABox.getHalfHeight() + , orientation); + instanceOccurrence.getPath().getTransformation().invert().applyOn(instanceTransformation); + instance->setTransformation(instanceTransformation); + instance->setPlacementStatus(Instance::PlacementStatus::PLACED); + //setPlacementStatusRecursivelyToPlaced(instance); + } + UpdateSession::close(); +} + +void SimAnnealingPlacer::Plot(ofstream& out) const +{ + out << "#instances" << endl; + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + Instance* instance = static_cast(_mauka->_instanceOccurrencesVector[i].getEntity()); + const Bin* bin = _instanceBins[i]; + if (!bin) + throw Error("No bin for instance"); + DbU::Unit xPos = bin->getCenter().getX(); + DbU::Unit yPos = bin->getCenter().getY(); + Box masterABox = instance->getMasterCell()->getAbutmentBox(); + Box instanceBox = Box( + xPos - masterABox.getWidth() / 2, + yPos - masterABox.getHeight() / 2, + xPos + masterABox.getWidth() / 2, + yPos + masterABox.getHeight() / 2); + out << instanceBox.getXMin()+0.4 << " " << instanceBox.getYMin()+0.4 << endl + << instanceBox.getXMin()+0.4 << " " << instanceBox.getYMax()-0.4 << endl + << instanceBox.getXMax()-0.4 << " " << instanceBox.getYMax()-0.4 << endl + << instanceBox.getXMax()-0.4 << " " << instanceBox.getYMin()+0.4 << endl + << instanceBox.getXMin()+0.4 << " " << instanceBox.getYMin()+0.4 << endl << endl; + } + out << "EOF" << endl << endl; + + out << "#nets" << endl; + for (unsigned i = 0; i < _mauka->_netInstances.size(); i++) + { + if (_mauka->_hasInitX[i]) + continue; + unsigned nbInstances = 0; + DbU::Unit baryX = 0; + DbU::Unit baryY = 0; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + ++nbInstances; + const Bin* bin = _instanceBins[instanceId]; + baryX += bin->getCenter().getX(); + baryY += bin->getCenter().getY(); + } + + baryX = baryX / nbInstances; + baryY = baryY / nbInstances; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + const Bin* bin = _instanceBins[instanceId]; + out << baryX << " " << baryY << endl + << bin->getCenter().getX() << " " + << bin->getCenter().getY() << endl << endl; + } + } + out << "EOF" << endl << endl; + + out << "#nets with fixed point" << endl; + for (unsigned i = 0; i < _mauka->_netInstances.size(); i++) + { + if (!_mauka->_hasInitX[i]) + continue; + unsigned nbInstances = 1; + DbU::Unit baryX = 0; + DbU::Unit baryY = 0; + baryX += _mauka->_netInitX[i]; + baryY += _mauka->_netInitY[i]; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + ++nbInstances; + const Bin* bin = _instanceBins[instanceId]; + baryX += bin->getCenter().getX(); + baryY += bin->getCenter().getY(); + } + + baryX = baryX / nbInstances; + baryY = baryY / nbInstances; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + const Bin* bin = _instanceBins[instanceId]; + out << baryX << " " << baryY << endl + << bin->getCenter().getX() << " " + << bin->getCenter().getY() << endl << endl; + } + out << baryX << " " << baryY << endl + << _mauka->_netInitX[i] << " " + << _mauka->_netInitY[i] << endl << endl; + } + out << "EOF" << endl << endl; +} + +} diff --git a/mauka/src/SimAnnealingPlacer.cpp.noRefactor b/mauka/src/SimAnnealingPlacer.cpp.noRefactor new file mode 100644 index 00000000..4678c9e0 --- /dev/null +++ b/mauka/src/SimAnnealingPlacer.cpp.noRefactor @@ -0,0 +1,682 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag + +#include +using namespace std; + +#include "UpdateSession.h" +USING_NAMESPACE_HURRICANE + +#include "CToolBox.h" +using namespace CRL; + +#include "Surface.h" +#include "Bin.h" +#include "Row.h" +#include "Mauka.h" +#include "Move.h" +#include "SimAnnealingPlacer.h" + +namespace { + +double ComputeStdDev(double sumcost, double sumsquare, unsigned accepted) +{ + if (accepted <= 1) + return 0.0; + + double stdDev = (sumsquare - sumcost * sumcost / (double)accepted) / ((double)accepted - 1.0); + if (stdDev > 0.0) + stdDev = sqrt(stdDev); + else + stdDev = 0.0; + + return stdDev; +} + +} + +namespace MAUKA { + +SimAnnealingPlacer::SimAnnealingPlacer(Mauka* mauka, double netmult, double binmult, double rowmult) +// ***************************************************************************************************** + : _mauka(mauka) + , _instanceBins() + , _netBBoxes() + , _netCosts() + , _netFlags() + , _netCost(0.0) + , _binCost(0.0) + , _rowCost(0.0) + , _initNetCost(0.0) + , _initBinCost(0.0) + , _initRowCost(0.0) + , _netMult(netmult) + , _binMult(binmult) + , _rowMult(rowmult) + , _temperature(0.0) + , _distance(0.0) + , _loop(0) + , _iterationsFactor(0.0) + , _iterations(0) + , _moves(0) + , _sourceEqualTargetMovementNumber(0) + , _surOccupationTargetMovementNumber(0) + , _impossibleExchangeMovementNumber(0) +{ + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + _instanceBins.push_back(NULL); + } + + for (unsigned netid = 0; netid < _mauka->_nets.size(); netid++) + { + vector bboxes(2); + _netBBoxes.push_back(bboxes); + vector costs(2); + _netCosts.push_back(costs); + _netFlags.push_back(0); + } + +} + +void SimAnnealingPlacer::Init() +{ + Surface* surface = _mauka->_surface; + if (!surface) + throw Error("Cannot init with no surface ..."); + + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + if (_instanceBins[i] == NULL) + cerr << "no bin for " << _mauka->_instanceOccurrencesVector[i] << endl; + } + + _initNetCost = _netCost = GetNetCost(); + _initBinCost = _binCost = surface->GetBinCost(); + _initRowCost = _rowCost = surface->GetRowCost(); + + double stdDev = 0.0; + double sumCost = 0.0; + double sumSquare = 0.0; + unsigned accepted = 0; + + _temperature = 1e30; + _distance = 1.0; + + if (_mauka->_verbosity.MajorStatsIsOn()) + { + cout << " o Beginning global placement ...." << endl; + cout << " o Number of nodes to place is: " << _mauka->_instanceOccurrencesVector.size() << endl; + cout << " o Margin is: " << 100.0 * surface->GetMargin() << "%" << endl; + + cout << " o Initial RowCost = " << _rowCost << endl; + cout << " o Initial BinCost = " << _binCost << endl; + cout << " o Initial NetCost = " << _netCost << endl; + cout << " o Initial Cost = " << GetCost() << endl; + cout << " o total bins capa = " << surface->GetBinsCapa() << endl; + cout << " o total bins size = " << surface->GetBinsSize() << endl; + cout << " o total subrows capa = " << surface->GetSubRowsCapa() << endl; + cout << " o Computing Initial Temperature ..."; + } + + Move move(this); + + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + if (!move.Next(_distance)) + { + if (_mauka->_verbosity.IsOn()) + { + cout << " o No More Mouvement Possible ....." << endl; + } + return; + } + + double deltaRowCost = move.GetDeltaRowCost(); + double deltaBinCost = move.GetDeltaBinCost(); + double deltaNetCost = move.GetDeltaNetCost(); + + double deltaCost = ComputeCost(deltaRowCost, deltaBinCost, deltaNetCost); + + + if (Accept(deltaCost)) + { + move.Accept(); + accepted += 1; + _rowCost += deltaRowCost; + _netCost += deltaNetCost; + _binCost += deltaBinCost; + double cost = GetCost(); + sumCost += cost; sumSquare += cost * cost; + //sumCost += deltaCost; sumSquare += deltaCost * deltaCost; + } + else + { + move.Reject(); + } + ++_moves; + } + + stdDev = ComputeStdDev(sumCost, sumSquare, accepted); + _temperature = 20.0 * stdDev; + _iterationsFactor = 15.0; + _iterations = (unsigned)(_iterationsFactor * pow(_mauka->_instanceOccurrencesVector.size(), 1.33)); + + if (false) + { + double debug = DebugNetCost(); + cout << "debug = " << debug << endl; + cout << "NetCost = " << _netCost << endl << endl; + // assert ((netCost - 1.0 <= debug) && (debug <= netCost + 1.0)); + } + + if (_mauka->_verbosity.IsOn()) + { + cout << "...... done" << endl; + } +} + + +bool SimAnnealingPlacer::Iterate() +{ + unsigned accepted = 0; + double sumCost = 0.0; + double sumSquare = 0.0; + double stdDev = 0.0, sucRatio = 0.0; + double oldTemperature = 0.0; + + Move move(this); + + for (unsigned i = 0; i < _iterations; ++i) + { + if (!move.Next(_distance)) + { + if (_mauka->_verbosity.IsOn()) + { + cout << " o No More Mouvement Possible ....." << endl; + } + return false; + } + + double deltaRowCost = move.GetDeltaRowCost(); + double deltaBinCost = move.GetDeltaBinCost(); + double deltaNetCost = move.GetDeltaNetCost(); + + double deltaCost = ComputeCost(deltaRowCost, deltaBinCost, deltaNetCost); + +#if 0 + cerr << deltaRowCost << endl; + cerr << deltaBinCost << endl; + cerr << deltaNetCost << endl; + cerr << deltaCost << endl << endl; +#endif + + if (Accept(deltaCost)) { + move.Accept(); + + accepted += 1; + _rowCost += deltaRowCost; + _binCost += deltaBinCost; + _netCost += deltaNetCost; + double cost = GetCost(); + sumCost += cost; sumSquare += cost * cost; + //sumCost += deltaCost; sumSquare += deltaCost * deltaCost; + } + else + { + move.Reject(); + } + ++_moves; + } + ++_loop; + + oldTemperature = _temperature; + stdDev = ComputeStdDev(sumCost, sumSquare, accepted); + + if (stdDev == 0.0) + _temperature = 0.0; + else + _temperature = _temperature * max(0.5, exp(-0.7 * _temperature / stdDev)); + + sucRatio = accepted / (double)_iterations; + _distance = max(0.1, min(_distance * (1.0 - 0.44 + sucRatio), 1.0)); + + if (_mauka->_verbosity.MajorStatsIsOn()) + { + cout << "Loop = " << _loop << ", NIns = " << _mauka->_instanceOccurrencesVector.size() + << ", Temperature = " << _temperature << ", Cost = " << GetCost() << endl; + cout << " RowCost = " << _rowCost << ", BinCost = " << _binCost + << ", NetCost = " << _netCost << endl; + cout << " Success Ratio = " << sucRatio * 100.0 << "%, Dist = " << _distance << ", Delta = " + << _temperature / oldTemperature << endl; + } + else if (_mauka->_verbosity.IsOn()) + cerr << "."; + + if (false) + { + double debug = DebugNetCost(); + cout << "debug = " << debug << endl; + cout << "NetCost = " << _netCost << endl << endl; + // assert ((netCost - 1.0 <= debug) && (debug <= netCost + 1.0)); + } + return ((_temperature != 0.0) + && ((sucRatio > 0.15) || (stdDev > (0.0001 / GetCost())))); +} + +double SimAnnealingPlacer::GetNetCost() +// ************************************ +{ + double totalNetCost = 0.0; + for (unsigned netid = 0; netid < _mauka->_netInstances.size(); netid++) + { + unsigned lastInstanceId = 0; + unsigned insCount = 0; + Box& netBBox = _netBBoxes[netid][_netFlags[netid]]; + + double& netCost = _netCosts[netid][_netFlags[netid]]; + netCost = 0.0; + for (Mauka::UVector::const_iterator uvit = _mauka->_netInstances[netid].begin(); + uvit != _mauka->_netInstances[netid].end(); + uvit++) + { + unsigned instanceId = *uvit; + lastInstanceId = instanceId; + Bin* bin = _instanceBins[instanceId]; + netBBox.Merge(bin->GetCenter().GetX(), bin->GetCenter().GetY()); + ++insCount; + } + if (_mauka->_hasInitX[netid]) + netBBox.Merge(_mauka->_netInitX[netid], netBBox.GetYMin()); + if (_mauka->_hasInitY[netid]) + netBBox.Merge(netBBox.GetXMin(), _mauka->_netInitY[netid]); + + if (!insCount) + { + if (_mauka->_verbosity.IsOn()) + { + cout << " o Placer Warning : Net " + << _mauka->_nets[netid] << " is not connected..." << endl; + } + } + else + { + Unit width = 0; +#if 0 + if (_mauka->_params.takeSplittersIntoAccountOptimization) + { + Instance* instance = _instanceOccurrences[lastInstanceId]; + Net* net = _nets[netid]; + Plug* netPlug = NULL; + for_each_plug(plug, instance->GetConnectedPlugs()) + { + Net* plugNet = plug->GetNet(); + if (plugNet == net) + { + netPlug = plug; + break; + } + end_for; + } + if (!netPlug) + throw Error("Mauka internal error: no plug"); + Hook* bodyHook = netPlug->GetBodyHook(); + for_each_hook(hook, bodyHook->GetHooks()) + { + Component* component = hook->GetComponent(); + if (SplitterContact* splitterContact = dynamic_cast(component)) + { + if (VFence* vfence = dynamic_cast(splitterContact->GetSplitter()->GetFence())) + { + if (_hasInitX[netid]) + _hasInitX[netid] = false; + else + { + _hasInitX[netid] = true; + _netInitX[netid] = vfence->GetX(); + } + } + else if (HFence* hfence = dynamic_cast(splitterContact->GetSplitter()->GetFence())) + { + if (_hasInitY[netid]) + _hasInitY[netid] = false; + else + { + _hasInitY[netid] = true; + _netInitY[netid] = hfence->GetY(); + } + } + else throw Error("Mauka internal error"); + } + else if (Pin* pin = dynamic_cast(component)) + { + if (!_mauka->_params.ignorePins) + { + netBBox.Merge(pin->GetX(), pin->GetY()); + } + } + end_for; + } + if (_hasInitX[netid]) + netBBox.Merge(_netInitX[netid], netBBox.GetYMin()); + if (_hasInitY[netid]) + netBBox.Merge(netBBox.GetXMin(), _netInitY[netid]); + } +#endif + width = netBBox.GetWidth(); + if (width == 0) + { + //all instances in the same bin... + //take for width half of the bin + Bin* bin = _instanceBins[lastInstanceId]; + width = bin->GetWidth() / 2; + } + double cost = GetValue(netBBox.GetHeight() + width); + netCost = cost; + totalNetCost += cost; + } + } + return totalNetCost; +} + +double SimAnnealingPlacer::DebugNetCost() +// ************************************** +{ + double totalNetCost = 0.0; + for (unsigned netid = 0; netid < _mauka->_netInstances.size(); netid++) + { + unsigned lastInstanceId = 0; + unsigned insCount = 0; + Box box; + for (Mauka::UVector::const_iterator uvit = _mauka->_netInstances[netid].begin(); + uvit != _mauka->_netInstances[netid].end(); + uvit++) + { + unsigned instanceId = *uvit; + lastInstanceId = instanceId; + Bin* bin = _instanceBins[instanceId]; + box.Merge(bin->GetCenter().GetX(), bin->GetCenter().GetY()); + ++insCount; + } + + if (insCount) + { +#if 0 + if (_mauka->_params.takeSplittersIntoAccountOptimization) + { + Occurrence instanceOccurrence = _instanceOccurrences[lastInstanceId]; + Instance* instance = dynamic_cast(instanceOccurrence.GetEntity()); + assert(instance); + Net* net = _nets[netid]; + Plug* netPlug = NULL; + for_each_plug(plug, instance->GetConnectedPlugs()) + { + Net* plugNet = plug->GetNet(); + if (plugNet == net) + { + netPlug = plug; + break; + } + end_for; + } + if (!netPlug) + throw Error("Mauka internal error: no plug"); + Hook* bodyHook = netPlug->GetBodyHook(); + bool hasInitX = false; + bool hasInitY = false; + Unit netInitX = 0; + Unit netInitY = 0; + for_each_hook(hook, bodyHook->GetHooks()) + { + if (SplitterContact* splitterContact = dynamic_cast(hook->GetComponent())) + { + if (VFence* vfence = dynamic_cast(splitterContact->GetSplitter()->GetFence())) + { + if (hasInitX) + hasInitX = false; + else + { + hasInitX = true; + netInitX = vfence->GetX(); + } + } + else if (HFence* hfence = dynamic_cast(splitterContact->GetSplitter()->GetFence())) + { + if (hasInitY) + hasInitY = false; + else + { + hasInitY = true; + netInitY = hfence->GetY(); + } + } + else throw Error("Mauka internal error"); + } + end_for; + } + if (hasInitX) + box.Merge(netInitX, box.GetYMin()); + if (hasInitY) + box.Merge(box.GetXMin(), netInitY); + } +#endif + Unit width = box.GetWidth(); + if (width == 0) + { + //all instances in the same bin... + //take for width half of the bin + Bin* bin = _instanceBins[lastInstanceId]; + width = bin->GetWidth() / 2; + } + totalNetCost += GetValue(box.GetHeight() + width); + } + } + return totalNetCost; +} + +void SimAnnealingPlacer::DisplayResults() const +{ + unsigned totalImpossibleMovements = + _impossibleExchangeMovementNumber + + _sourceEqualTargetMovementNumber + + _surOccupationTargetMovementNumber; + cout << " o Total impossible movements = " << totalImpossibleMovements << endl; + cout << " o " << 100.0 * _surOccupationTargetMovementNumber / totalImpossibleMovements + << " % suroccupied target" << endl; + cout << " o " << 100.0 * _sourceEqualTargetMovementNumber / totalImpossibleMovements + << " % source equal target" << endl; + cout << " o " << 100.0 * _impossibleExchangeMovementNumber / totalImpossibleMovements + << " % impossible exchange" << endl; + + cout << " o Global Placement finished ....." << endl; + cout << " o Gain for RowCost = " + << 100.0 * (_initRowCost - _rowCost) / _initRowCost << "%" << endl; + cout << " o Gain for BinCost = " + << 100.0 * (_initBinCost - _binCost) / _initBinCost << "%" << endl; + cout << " o Gain for NetCost = " + << 100.0 * (_initNetCost - _netCost) / _initNetCost << "%" << endl; + cout << " o NetCost Estimated = " << _netCost << endl; +} + +double SimAnnealingPlacer::GetCost() const +{ + return ComputeCost(_rowCost, _binCost, _netCost); +} + +double SimAnnealingPlacer::ComputeCost(double rowcost, double bincost, double netcost) const +{ + return rowcost / _initRowCost * _rowMult + + bincost / _initBinCost * _binMult + + netcost / _initNetCost * _netMult; +} + +bool SimAnnealingPlacer::Accept(double deltacost) const +{ + if (_mauka->_params.standardSimulatedAnnealing) + { + double doubleRand = (double) (rand() / (RAND_MAX + 1.0)); + return ((deltacost <= 0.0) + || ((_temperature != 0.0) + && (exp(-deltacost / _temperature) > doubleRand))); + } + else + return deltacost <= 0.0; +} + + +void SimAnnealingPlacer::Save() const +{ + OpenUpdateSession(); + for(unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + Occurrence instanceOccurrence = _mauka->_instanceOccurrencesVector[i]; + Instance* instance = static_cast(instanceOccurrence.GetEntity()); + Bin* bin = _instanceBins[i]; + bool rowOrientation = bin->GetSubRow()->GetRow()->GetOrientation(); + if (!bin) + throw Error("No bin for instance"); + Unit xPos = bin->GetCenter().GetX(); + Unit yPos = bin->GetCenter().GetY(); + Box masterABox = instance->GetMasterCell()->GetAbutmentBox(); + Transformation::Orientation orientation; + if (rowOrientation) + orientation = Transformation::Orientation::ID; + else + orientation = Transformation::Orientation::MY; + Transformation instanceTransformation = GetTransformation(masterABox + , xPos - masterABox.GetHalfWidth() + , yPos - masterABox.GetHalfHeight() + , orientation); + instanceOccurrence.GetPath().GetTransformation().Invert().ApplyOn(instanceTransformation); + instance->SetTransformation(instanceTransformation); + instance->SetPlacementStatus(Instance::PlacementStatus::PLACED); + //SetPlacementStatusRecursivelyToPlaced(instance); + } + CloseUpdateSession(); +} + +void SimAnnealingPlacer::Plot(ofstream& out) const +{ + out << "#instances" << endl; + for (unsigned i = 0; i < _mauka->_instanceOccurrencesVector.size(); i++) + { + Instance* instance = static_cast(_mauka->_instanceOccurrencesVector[i].GetEntity()); + const Bin* bin = _instanceBins[i]; + if (!bin) + throw Error("No bin for instance"); + Unit xPos = bin->GetCenter().GetX(); + Unit yPos = bin->GetCenter().GetY(); + Box masterABox = instance->GetMasterCell()->GetAbutmentBox(); + Box instanceBox = Box( + xPos - masterABox.GetWidth() / 2, + yPos - masterABox.GetHeight() / 2, + xPos + masterABox.GetWidth() / 2, + yPos + masterABox.GetHeight() / 2); + out << instanceBox.GetXMin()+0.4 << " " << instanceBox.GetYMin()+0.4 << endl + << instanceBox.GetXMin()+0.4 << " " << instanceBox.GetYMax()-0.4 << endl + << instanceBox.GetXMax()-0.4 << " " << instanceBox.GetYMax()-0.4 << endl + << instanceBox.GetXMax()-0.4 << " " << instanceBox.GetYMin()+0.4 << endl + << instanceBox.GetXMin()+0.4 << " " << instanceBox.GetYMin()+0.4 << endl << endl; + } + out << "EOF" << endl << endl; + + out << "#nets" << endl; + for (unsigned i = 0; i < _mauka->_netInstances.size(); i++) + { + if (_mauka->_hasInitX[i]) + continue; + unsigned nbInstances = 0; + Unit baryX = 0; + Unit baryY = 0; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + ++nbInstances; + const Bin* bin = _instanceBins[instanceId]; + baryX += bin->GetCenter().GetX(); + baryY += bin->GetCenter().GetY(); + } + + baryX = baryX / nbInstances; + baryY = baryY / nbInstances; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + const Bin* bin = _instanceBins[instanceId]; + out << baryX << " " << baryY << endl + << bin->GetCenter().GetX() << " " + << bin->GetCenter().GetY() << endl << endl; + } + } + out << "EOF" << endl << endl; + + out << "#nets with fixed point" << endl; + for (unsigned i = 0; i < _mauka->_netInstances.size(); i++) + { + if (!_mauka->_hasInitX[i]) + continue; + unsigned nbInstances = 1; + Unit baryX = 0; + Unit baryY = 0; + baryX += _mauka->_netInitX[i]; + baryY += _mauka->_netInitY[i]; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + ++nbInstances; + const Bin* bin = _instanceBins[instanceId]; + baryX += bin->GetCenter().GetX(); + baryY += bin->GetCenter().GetY(); + } + + baryX = baryX / nbInstances; + baryY = baryY / nbInstances; + for (unsigned j = 0; j < _mauka->_netInstances[i].size(); j++) + { + unsigned instanceId = _mauka->_netInstances[i][j]; + const Bin* bin = _instanceBins[instanceId]; + out << baryX << " " << baryY << endl + << bin->GetCenter().GetX() << " " + << bin->GetCenter().GetY() << endl << endl; + } + out << baryX << " " << baryY << endl + << _mauka->_netInitX[i] << " " + << _mauka->_netInitY[i] << endl << endl; + } + out << "EOF" << endl << endl; +} + +} diff --git a/mauka/src/SubRow.cpp b/mauka/src/SubRow.cpp new file mode 100644 index 00000000..26731e7b --- /dev/null +++ b/mauka/src/SubRow.cpp @@ -0,0 +1,268 @@ +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag + +#include "crlcore/CellGauge.h" +#include "crlcore/AllianceFramework.h" + +#include "mauka/Bin.h" +#include "mauka/Row.h" +#include "mauka/Surface.h" +#include "mauka/SimAnnealingPlacer.h" +#include "mauka/SubRow.h" + +namespace Mauka { + +using namespace std; +using Hurricane::Error; +using CRL::AllianceFramework; + +SubRow::SubRow(Cell* cell, Surface* surface, const Box& box) + :Inherit(cell, box) + , _surface(surface) + , _row(NULL) + , _binVector() + , _size(0) + , _capa(0) +{} + +SubRow* SubRow::create(Cell* cell, Surface* surface, const Box& box, bool orientation) +{ + SubRow* subRow = new SubRow(cell, surface, box); + subRow->_postCreate(orientation); + return subRow; +} + +void SubRow::_postCreate(bool orientation) +{ + _row = _surface->InsertSubRowInRow(this, orientation); + + unsigned nBins = 0; + if (getWidth() % _surface->_binWidthMax) + nBins = getWidth() / _surface->_binWidthMax + 1; + else + nBins = getWidth() / _surface->_binWidthMax; + + if (nBins == 0) + { + assert (getWidth() >= _surface->_binWidthMin); + nBins = 1; + } + + DbU::Unit pitch = AllianceFramework::get()->getCellGauge()->getPitch(); + DbU::Unit binsWidth = ((getWidth() / pitch) / nBins) * pitch; + + if (getWidth() % pitch) + throw Error("Subrow Width: " + getString(getWidth()) + " is not a multiple of pitch"); + if (binsWidth % pitch) + throw Error("Bins Width not a multiple of pitch"); + + DbU::Unit totalBinsWidth = binsWidth * nBins; + DbU::Unit binsWidthRemain = getWidth() - totalBinsWidth; + + if (binsWidthRemain % pitch) + throw Error("Bins Width not a multiple of pitch"); + + unsigned binsWidthRemainPitch = binsWidthRemain / pitch; + + DbU::Unit xMin = getXMin(); + DbU::Unit xMax = xMin; + + for (unsigned binId = 0; binId < nBins; binId++) + { + if (binsWidthRemainPitch > 0) + { + xMax += binsWidth + pitch; + binsWidthRemainPitch--; + } + else + xMax += binsWidth; + Bin* bin = Bin::create(getCell(), this, Box(xMin, getYMin(), xMax, getYMax())); + _binVector.push_back(bin); + unsigned binIdx = _binVector.size() - 1; + _binXMax[bin->getXMax()] = binIdx; + xMin = xMax; + } + + + Inherit::_postCreate(); +} + +bool SubRow::_MergeBins() +{ + if (_binVector.size() > 1) + { + cerr << "merging " << this << endl; + _size = 0; + Bin* bin = Bin::create(getCell(), this, Box(getXMin(), getYMin(), getXMax(), getYMax())); + for (BinVector::iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + for (MaukaEngine::UList::const_iterator ulit = (*bvit)->_instanceOccurrenceIds.begin(); + ulit != (*bvit)->_instanceOccurrenceIds.end(); + ulit++) + { + _surface->_mauka->_simAnnealingPlacer->_instanceBins[*ulit] = NULL; + } + (*bvit)->destroy(); + } + _binVector.clear(); + _binVector.push_back(bin); + return true; + } + return false; +} + +void SubRow::_computeCapacity(double margin) +{ + for (BinVector::const_iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + (*bvit)->_computeCapacity(margin); + _capa += (*bvit)->_capa; + } +} + +void SubRow::_preDestroy() +{ + Inherit::_preDestroy(); + for (BinVector::iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + (*bvit)->destroy(); + } +} + +void SubRow::DisplayBinHits() const +{ + for (BinVector::const_iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + (*bvit)->DisplayHits(); + } +} + +Bin* SubRow::getBinBetween(DbU::Unit lowerX, DbU::Unit upperX, const Bin* srcbin) +{ + assert(lowerX <= upperX); + assert(lowerX >= getXMin()); + assert(upperX <= getXMax()); + + + if (_binVector.size() == 1) + return _binVector[0]; + + DbU::Unit searchPosition = lowerX + + DbU::lambda((int)(DbU::getLambda(upperX-lowerX) * rand() / (RAND_MAX + 1.0))); + + unsigned binId = _binXMax.upper_bound(searchPosition)->second; + + if (_binVector[binId] == srcbin) + { + if (binId == 0) + return _binVector[1]; + if (binId == _binVector.size() - 1) + return _binVector[_binVector.size() - 2]; + static bool altern = true; + if (altern) + { + altern = false; + return _binVector[binId + 1]; + } + else + { + altern = true; + return _binVector[binId - 1]; + } + } + + return _binVector[binId]; +} + +void SubRow::_AddSize(DbU::Unit value) +{ + _size += value; + _row->_AddSize(value); +} + + +double SubRow::getCost() const +{ + return abs(DbU::getLambda(_size - _capa)); +} + +double SubRow::getBinCost() const +{ + double binCost = 0.0; + for (BinVector::const_iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + binCost += (*bvit)->getCost(); + return binCost; +} + +DbU::Unit SubRow::getBinsSize() const +{ + DbU::Unit totalBinsSize = 0; + for (BinVector::const_iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + totalBinsSize += (*bvit)->getSize(); + } + return totalBinsSize; +} + +DbU::Unit SubRow::getBinsCapa() const +{ + DbU::Unit totalBinsCapa = 0; + for (BinVector::const_iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + totalBinsCapa += (*bvit)->getCapa(); + } + return totalBinsCapa; +} + +Cell* SubRow::getCell() const +{ + return _row->getCell(); +} + +} diff --git a/mauka/src/SubRow.cpp.noRefactor b/mauka/src/SubRow.cpp.noRefactor new file mode 100644 index 00000000..291b4211 --- /dev/null +++ b/mauka/src/SubRow.cpp.noRefactor @@ -0,0 +1,265 @@ +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag + +#include "CDataBase.h" +using namespace CRL; + +#include "Bin.h" +#include "Row.h" +#include "Surface.h" +#include "SimAnnealingPlacer.h" + +#include "SubRow.h" + +namespace MAUKA { + +SubRow::SubRow(const Cell* cell, Surface* surface, const Box& box) + :Inherit(cell, box) + , _surface(surface) + , _row(NULL) + , _binVector() + , _size(0) + , _capa(0) +{} + +SubRow* SubRow::Create(const Cell* cell, Surface* surface, const Box& box, bool orientation) +{ + SubRow* subRow = new SubRow(cell, surface, box); + subRow->_PostCreate(orientation); + return subRow; +} + +void SubRow::_PostCreate(bool orientation) +{ + _row = _surface->InsertSubRowInRow(this, orientation); + + unsigned nBins = 0; + if (GetWidth() % _surface->_binWidthMax) + nBins = GetWidth() / _surface->_binWidthMax + 1; + else + nBins = GetWidth() / _surface->_binWidthMax; + + if (nBins == 0) + { + assert (GetWidth() >= _surface->_binWidthMin); + nBins = 1; + } + + Unit pitch = GetCDataBase()->GetDefaultCGPitch(); + Unit binsWidth = ((GetWidth() / pitch) / nBins) * pitch; + + if (GetWidth() % pitch) + throw Error("Subrow Width: " + GetString(GetWidth()) + " is not a multiple of pitch"); + if (binsWidth % pitch) + throw Error("Bins Width not a multiple of pitch"); + + Unit totalBinsWidth = binsWidth * nBins; + Unit binsWidthRemain = GetWidth() - totalBinsWidth; + + if (binsWidthRemain % pitch) + throw Error("Bins Width not a multiple of pitch"); + + unsigned binsWidthRemainPitch = binsWidthRemain / pitch; + + Unit xMin = GetXMin(); + Unit xMax = xMin; + + for (unsigned binId = 0; binId < nBins; binId++) + { + if (binsWidthRemainPitch > 0) + { + xMax += binsWidth + pitch; + binsWidthRemainPitch--; + } + else + xMax += binsWidth; + Bin* bin = Bin::Create(GetCell(), this, Box(xMin, GetYMin(), xMax, GetYMax())); + _binVector.push_back(bin); + unsigned binIdx = _binVector.size() - 1; + _binXMax[bin->GetXMax()] = binIdx; + xMin = xMax; + } + + + Inherit::_PostCreate(); +} + +bool SubRow::_MergeBins() +{ + if (_binVector.size() > 1) + { + cerr << "merging " << this << endl; + _size = 0; + Bin* bin = Bin::Create(GetCell(), this, Box(GetXMin(), GetYMin(), GetXMax(), GetYMax())); + for (BinVector::iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + for (Mauka::UList::const_iterator ulit = (*bvit)->_instanceOccurrenceIds.begin(); + ulit != (*bvit)->_instanceOccurrenceIds.end(); + ulit++) + { + _surface->_mauka->_simAnnealingPlacer->_instanceBins[*ulit] = NULL; + } + (*bvit)->Delete(); + } + _binVector.clear(); + _binVector.push_back(bin); + return true; + } + return false; +} + +void SubRow::_ComputeCapacity(double margin) +{ + for (BinVector::const_iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + (*bvit)->_ComputeCapacity(margin); + _capa += (*bvit)->_capa; + } +} + +void SubRow::_PreDelete() +{ + Inherit::_PreDelete(); + for (BinVector::iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + (*bvit)->Delete(); + } +} + +void SubRow::DisplayBinHits() const +{ + for (BinVector::const_iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + (*bvit)->DisplayHits(); + } +} + +Bin* SubRow::GetBinBetween(Unit lowerX, Unit upperX, const Bin* srcbin) +{ + assert(lowerX <= upperX); + assert(lowerX >= GetXMin()); + assert(upperX <= GetXMax()); + + + if (_binVector.size() == 1) + return _binVector[0]; + + Unit searchPosition = lowerX + + GetUnit((int)(GetValue(upperX-lowerX) * rand() / (RAND_MAX + 1.0))); + + unsigned binId = _binXMax.upper_bound(searchPosition)->second; + + if (_binVector[binId] == srcbin) + { + if (binId == 0) + return _binVector[1]; + if (binId == _binVector.size() - 1) + return _binVector[_binVector.size() - 2]; + static bool altern = true; + if (altern) + { + altern = false; + return _binVector[binId + 1]; + } + else + { + altern = true; + return _binVector[binId - 1]; + } + } + + return _binVector[binId]; +} + +void SubRow::_AddSize(Unit value) +{ + _size += value; + _row->_AddSize(value); +} + + +double SubRow::GetCost() const +{ + return abs(GetValue(_size - _capa)); +} + +double SubRow::GetBinCost() const +{ + double binCost = 0.0; + for (BinVector::const_iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + binCost += (*bvit)->GetCost(); + return binCost; +} + +Unit SubRow::GetBinsSize() const +{ + Unit totalBinsSize = 0; + for (BinVector::const_iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + totalBinsSize += (*bvit)->GetSize(); + } + return totalBinsSize; +} + +Unit SubRow::GetBinsCapa() const +{ + Unit totalBinsCapa = 0; + for (BinVector::const_iterator bvit = _binVector.begin(); + bvit != _binVector.end(); + bvit++) + { + totalBinsCapa += (*bvit)->GetCapa(); + } + return totalBinsCapa; +} + +Cell* SubRow::GetCell() const +{ + return _row->GetCell(); +} + +} diff --git a/mauka/src/Surface.cpp b/mauka/src/Surface.cpp new file mode 100644 index 00000000..cea9cacf --- /dev/null +++ b/mauka/src/Surface.cpp @@ -0,0 +1,816 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag + +#include "hurricane/Warning.h" +#include "hurricane/Cell.h" +#include "crlcore/CellGauge.h" +#include "crlcore/AllianceFramework.h" +#include "nimbus/NimbusEngine.h" + +#include "mauka/MaukaEngine.h" +#include "mauka/SimAnnealingPlacer.h" +#include "mauka/SubRow.h" +#include "mauka/Row.h" +#include "mauka/Surface.h" + +namespace { + +using namespace std; +using namespace Hurricane; +using namespace Mauka; + +void VerifyInstanceQuadtreeInsertion(Cell *cell) +{ + cerr << "VerifyInstanceQuadtreeInsertion" << endl; + for_each_instance(instance, cell->getInstances()) + { + if (!instance->isMaterialized()) + { + Cell* masterCell = instance->getMasterCell(); + cerr << tab << instance << " of " << masterCell << " is not materialized..." << endl; + tab++; + VerifyInstanceQuadtreeInsertion(masterCell); + tab--; + } + end_for; + } +} + +void DisplayInstanceOccurrence(Occurrence& instanceOccurrence) +{ + cerr << instanceOccurrence << " " << instanceOccurrence.getBoundingBox() << endl; + Instance* instance = static_cast(instanceOccurrence.getEntity()); + Path path = instanceOccurrence.getPath(); + cerr << path.getTransformation() << endl; + cerr << instance->getTransformation() << endl; + while (!path.isEmpty()) + { + cerr << path.getTailInstance() << " " << path.getTailInstance()->getTransformation() << endl; + cerr << path.getTailInstance()->getMasterCell() << endl; + cerr << path.getTailInstance()->getMasterCell()->getAbutmentBox() << endl; + cerr << path.getTailInstance()->getMasterCell()->getBoundingBox() << endl; + cerr << path.getTailInstance()->getAbutmentBox() << endl; + cerr << path.getTailInstance()->getBoundingBox() << endl; + path = path.getHeadPath(); + } +} + +void DisplayNonLeafInstances(Cell* cell, Box area) +{ + ltrace(100) << "display of " << cell << " in " << area << endl; + for_each_instance(instance, cell->getNonLeafInstancesUnder(area)) + { + ltrace(100) << instance << " " << instance->getBoundingBox() << endl; + Cell* masterCell = instance->getMasterCell(); + ltracein(20); + DisplayNonLeafInstances(masterCell, area); + ltraceout(20); + end_for; + } +} + +} // End of anonymous namespace. + +namespace Mauka { + +using CRL::AllianceFramework; +using Nimbus::NimbusEngine; +using Nimbus::GCellLocator; + +Surface::Surface(MaukaEngine* mauka, const Box& placementbox) : + Inherit(mauka->getCell(), placementbox), + _mauka(mauka), + _rowVector(), + _rowYMax(), + _rowYMinInv(), + _rowZeroOrientation(false), + _margin(0.0), + _binWidthMax(0), + _binWidthMin(0), + _searchWidth(0), + _searchHeight(0) +{} + +Surface* Surface::create(MaukaEngine* mauka, const Box& placementbox) { + if (!mauka) { + throw Error("Can't create " + _TName("Surface") + " : empty mauka"); + } + + if (!mauka->getCell()) { + throw Error("Can't create " + _TName("Surface") + " : empty cell on mauka"); + } + + Surface* surface = new Surface(mauka, placementbox); + + surface->_postCreate(); + + return surface; +} + +namespace { + +void PlacementVerification(Cell* cell, Box& box) { + set occurrenceSet; + for_each_occurrence(occurrence, cell->getLeafInstanceOccurrencesUnder(box)) { + occurrenceSet.insert(occurrence); + end_for; + } + // for_each_occurrence(occurrence, cell->getLeafInstanceOccurrences()) { + // if (occurrenceSet.find(occurrence) == occurrenceSet.end()) { + // cerr << occurrence << ":" << occurrence.getBoundingBox() << endl; + // throw Error("occurrence is badly placed"); + // } + // end_for; + // } +} + +typedef list InstanceOccurrencesList; + +class PlacementProblem { + public: GCell* _gcell; + public: InstanceOccurrencesList _fixedInstanceOccurrenceList; + public: MaukaEngine::UVector _toPlaceInstanceOccurrencesUVector; + public: Surface::SubRowList _subRowList; + PlacementProblem(GCell* gcell) + : _gcell(gcell) + , _fixedInstanceOccurrenceList() + , _toPlaceInstanceOccurrencesUVector() + , _subRowList() + {} +}; + +typedef list PlacementProblemList; + +} + + + void Surface::_postCreate () + { + typedef set OccurrenceSet; + + Inherit::_postCreate(); + + NimbusEngine* nimbus = NULL; + if (_box.isEmpty()) { + nimbus = NimbusEngine::get ( getCell() ); + if (nimbus == NULL) { + throw Error("Can't create Mauka::Surface, no Box and no Nimbus"); + } + _box = nimbus->getGrid()->getRoot()->getBox(); + } + + PlacementVerification ( getCell(), _box ); + + DbU::Unit sliceHeight = DbU::lambda(1); + DbU::Unit pitch = DbU::lambda(1); + + AllianceFramework* af = AllianceFramework::get(); + if (af != NULL) { + sliceHeight = af->getCellGauge()->getSliceHeight(); + pitch = af->getCellGauge()->getPitch(); + } else { + // For the moment very stupid method: take the first instantiated Cell. + forEach ( Instance*, iinstance, getCell()->getInstances() ) { + Cell* masterCell = iinstance->getMasterCell(); + sliceHeight = masterCell->getAbutmentBox().getHeight(); + break; + } + } + + if ( _box.isEmpty() or _box.isPonctual() or _box.isFlat()) + throw Error("Wrong Box for Area: %s",getString(_box).c_str()); + + if ( getHeight() % sliceHeight ) + throw Error("Box Height %s must be a multiple of Slice Height %s" + ,DbU::getValueString(getHeight()).c_str() + ,DbU::getValueString(sliceHeight).c_str()); + + DbU::Unit instanceToPlaceWidthMax = 0; + DbU::Unit instanceToPlaceWidthSum = 0; + + for ( unsigned int id = 0; id < _mauka->_instanceWidths.size(); ++id ) { + DbU::Unit instanceWidth = _mauka->_instanceWidths[id]; + instanceToPlaceWidthSum += instanceWidth; + + if ( instanceWidth % pitch ) + throw Error("Width of %s (%s) is not a multiple of pitch (%s)." + ,getString(_mauka->_instanceOccurrencesVector[id]).c_str() + ,DbU::getValueString(instanceWidth).c_str() + ,DbU::getValueString(pitch).c_str()); + + if (instanceWidth > instanceToPlaceWidthMax) + instanceToPlaceWidthMax = instanceWidth; + } + + _binWidthMax = DbU::lambda + ((unsigned)( 2.0 * DbU::getLambda(instanceToPlaceWidthMax) / DbU::getLambda(pitch)) + * DbU::getLambda(pitch)); + + _binWidthMin = DbU::lambda + ((unsigned)(DbU::getLambda(_binWidthMax) / (DbU::getLambda(pitch) * 2)) * DbU::getLambda(pitch)); + + DbU::Unit surfaceTotalWidth = 0; + PlacementProblemList placementProblemList; + OccurrenceSet verifyInstanceOccurrencesSet; + + if ( nimbus ) { + forEach ( GCell*, igcell, nimbus->getPlacementLeaves() ) { + PlacementProblem* placementProblem = new PlacementProblem(*igcell); + placementProblemList.push_back(placementProblem); + + InstanceOccurrencesList toPlaceInstanceOccurrencesList; + // Search for preplaced leaf instances + forEach ( Occurrence + , ioccurrence, _mauka->getCell()->getLeafInstanceOccurrencesUnder(igcell->getBox()) ) { + Instance* instance = static_cast((*ioccurrence).getEntity()); + + if ( instance->isFixed() ) { + placementProblem->_fixedInstanceOccurrenceList.push_back(*ioccurrence); + } else { + MaukaEngine::InstanceOccurrencesMap::const_iterator + iomit = _mauka->_instanceOccurrencesMap.find(*ioccurrence); + + if ( iomit == _mauka->_instanceOccurrencesMap.end() ) + throw Error("Instance occurrence unexpectedly appeared:\n" + " %s",getString(*ioccurrence).c_str()); + + placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(iomit->second); + verifyInstanceOccurrencesSet.insert(*ioccurrence); + } + } + + forEach(Occurrence, ioccurrence, _mauka->getCell()->getLeafInstanceOccurrences()) { + Instance* instance = static_cast((*ioccurrence).getEntity()); + if ( instance->isFixed() ) continue; + + MaukaEngine::InstanceOccurrencesMap::const_iterator iomit + = _mauka->_instanceOccurrencesMap.find(*ioccurrence); + + if (iomit == _mauka->_instanceOccurrencesMap.end()) + throw Error("Instance occurrence unexpectedly appeared:\n" + " %s",getString(*ioccurrence).c_str()); + + placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(iomit->second); + verifyInstanceOccurrencesSet.insert(*ioccurrence); + } + + DbU::Unit searchWidth = DbU::lambda(_mauka->getSearchRatio() * DbU::getLambda(igcell->getWidth())); + if (_searchWidth < searchWidth) _searchWidth = searchWidth; + + DbU::Unit searchHeight = DbU::lambda(_mauka->getSearchRatio() * DbU::getLambda(igcell->getHeight())); + if (_searchHeight < searchHeight) _searchHeight = searchHeight; + } + + for ( PlacementProblemList::iterator pplit = placementProblemList.begin(); + pplit != placementProblemList.end(); pplit++) { + PlacementProblem* placementProblem = *pplit; + GCell* gcell = placementProblem->_gcell; + + if ( placementProblem->_fixedInstanceOccurrenceList.size() != 0 ) { + bool rowZeroOrientation = false; + int width = (unsigned)(gcell->getWidth () / pitch); // Number of X pitch + int height = (unsigned)(gcell->getHeight() / sliceHeight); // Number of Y slices + + + MaukaEngine::PrePlaceTab prePlaceTab(height, MaukaEngine::PrePlaceRow(width, false)); + + InstanceOccurrencesList::const_iterator iolit + = placementProblem->_fixedInstanceOccurrenceList.begin(); + + // Find the orientation of the first row. + Instance* refInstance = static_cast(iolit->getEntity()); + Box refAbutmentBox = refInstance->getAbutmentBox(); + Transformation refTransformation = refInstance->getTransformation(); + + iolit->getPath().getTransformation().applyOn(refAbutmentBox); + iolit->getPath().getTransformation().applyOn(refTransformation); + + Box preplacedBox = gcell->getIntersection(refAbutmentBox); + + // Position en y ramene au slice + int refInsYPos = (int)((preplacedBox.getYMin() - gcell->getYMin()) / sliceHeight); + // Hauteur ramene a la hauteur du slice + int refInsSliceHeight = (int)(preplacedBox.getHeight() / sliceHeight); + Transformation::Orientation orientation = refTransformation.getOrientation(); + + if ( refInsYPos % 2 == 0 ) { + if ( (refInsSliceHeight % 2 == 0) + or (orientation == Transformation::Orientation::ID) + or (orientation == Transformation::Orientation::MX)) + rowZeroOrientation = true; + else + rowZeroOrientation = false; + } else { + if ( (refInsSliceHeight % 2 == 0) + or (orientation == Transformation::Orientation::ID) + or (orientation == Transformation::Orientation::MX)) + rowZeroOrientation = false; + else + rowZeroOrientation = true; + } + + // Tests for each Instance. + for ( InstanceOccurrencesList::iterator iolit = placementProblem->_fixedInstanceOccurrenceList.begin(); + iolit != placementProblem->_fixedInstanceOccurrenceList.end(); iolit++ ) { + Instance* instance = static_cast(iolit->getEntity()); + Box instanceAbutmentBox = instance->getAbutmentBox(); + + iolit->getPath().getTransformation().applyOn(instanceAbutmentBox); + + Box preplacedBox = gcell->getIntersection(instanceAbutmentBox); + DbU::Unit insWidth = preplacedBox.getWidth(); + DbU::Unit insHeight = preplacedBox.getHeight(); + + int insPitchWidth = (int)(insWidth / pitch); // Largeur ramene au pitch + int insSliceHeight = (int)(insHeight / sliceHeight); // Hauteur ramene a la hauteur du slice + + int ypos = (int)((preplacedBox.getYMin() - gcell->getYMin()) / sliceHeight); // Position en Y ramene au slice + int xpos = (int)((preplacedBox.getXMin() - gcell->getXMin()) / pitch); // Position en X ramene au pitch + + for ( int yit = ypos; yit < ypos + insSliceHeight; ++yit ) { + for ( int xit = xpos; xit < xpos + insPitchWidth; ++xit ) { + if ( (xit > width - 1) or (yit > height - 1) or (xit < 0) or (yit < 0) ) + throw Error("%s is out of the abutment box" + ,getString(*iolit).c_str()); + if ( prePlaceTab[yit][xit] == false ) + prePlaceTab[yit][xit] = true; + else + throw Error("%s is badly placed. There is another instance at it's position" + ,getString(*iolit).c_str()); + } + } + } + + bool rowOrientation = rowZeroOrientation; + for ( int y = 0; y < (int)prePlaceTab.size(); ++y ) { + int x = 0; + + while ( x < (int)prePlaceTab[y].size() ) { + while ( (x < (int)prePlaceTab[y].size()) and (prePlaceTab[y][x] == true) ) ++x; + + DbU::Unit subRowXMin = gcell->getXMin() + x * pitch; + + if (x >= (int)prePlaceTab[y].size()) break; + + while ( (x < (int)prePlaceTab[y].size()) and (prePlaceTab[y][x] == false) ) ++x; + + DbU::Unit subRowXMax = gcell->getXMin() + x * pitch; + if ( subRowXMax - subRowXMin > _binWidthMin ) { + SubRow* subRow = SubRow::create ( getCell() + , this + , Box(subRowXMin, gcell->getYMin() + y * sliceHeight + ,subRowXMax, gcell->getYMin() + (y+1) * sliceHeight) + , rowOrientation ); + placementProblem->_subRowList.push_back(subRow); + } + } + rowOrientation = not rowOrientation; + } + } else { + bool rowOrientation = false; + for ( DbU::Unit ymin = gcell->getYMin() + ; ymin <= gcell->getYMax() - sliceHeight + ; ymin += sliceHeight ) { + SubRow* subRow = SubRow::create ( getCell() + , this + , Box(gcell->getXMin(), ymin + ,gcell->getXMax(), ymin + sliceHeight) + , rowOrientation ); + placementProblem->_subRowList.push_back(subRow); + rowOrientation = not rowOrientation; + } + } + } + } else { + PlacementProblem* placementProblem = new PlacementProblem(NULL); + _searchHeight = getHeight(); + _searchWidth = getWidth(); + + bool rowOrientation = false; + unsigned nRows = getHeight() / sliceHeight; + surfaceTotalWidth = getWidth() * nRows; + + for ( DbU::Unit ymin = getYMin(); ymin <= getYMax() - sliceHeight; ymin += sliceHeight ) { + SubRow* subRow = SubRow::create ( getCell() + , this + , Box(getXMin(), ymin,getXMax(), ymin + sliceHeight) + , rowOrientation ); + placementProblem->_subRowList.push_back(subRow); + rowOrientation = not rowOrientation; + } + + for ( unsigned int id=0; id < _mauka->_instanceOccurrencesVector.size(); ++id ) { + placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(id); + } + throw Error("MaukaEngine needs NimbusEngine"); + } + + for (PlacementProblemList::iterator pplit = placementProblemList.begin(); + pplit != placementProblemList.end(); pplit++) { + _DisplayInstances((*pplit)->_toPlaceInstanceOccurrencesUVector, (*pplit)->_subRowList); + delete *pplit; + } + + placementProblemList.clear (); + + if ( verifyInstanceOccurrencesSet.size() != _mauka->_instanceOccurrencesVector.size() ) { + cerr << Error("There are %d Instances not taken into account" + ,(_mauka->_instanceOccurrencesVector.size() - verifyInstanceOccurrencesSet.size())) << endl; + + VerifyInstanceQuadtreeInsertion(_mauka->getCell()); + + for ( MaukaEngine::InstanceOccurrencesVector::iterator iovit = _mauka->_instanceOccurrencesVector.begin(); + iovit != _mauka->_instanceOccurrencesVector.end(); iovit++ ) { + OccurrenceSet::iterator osit = verifyInstanceOccurrencesSet.find(*iovit); + + if ( osit == verifyInstanceOccurrencesSet.end() ) { + cerr << " o Problem with " << *iovit << endl; + DisplayInstanceOccurrence ( *iovit ); + DisplayNonLeafInstances ( _mauka->getCell(), iovit->getBoundingBox() ); + return; + } + } + throw Error("There are %d Instances not taken into account" + ,(_mauka->_instanceOccurrencesVector.size() - verifyInstanceOccurrencesSet.size())); + } + + for ( RowVector::const_iterator rvit = _rowVector.begin(); rvit != _rowVector.end(); rvit++ ) { + surfaceTotalWidth += (*rvit)->getSubRowsWidth(); + } + + _computeRowsAndSubRows(); + + _margin = 1.0 - DbU::getLambda(instanceToPlaceWidthSum) / DbU::getLambda(surfaceTotalWidth); + if ( _margin < 0 ) { + throw Error("There is not enough free space to place the circuit %s < %s" + ,DbU::getValueString(surfaceTotalWidth).c_str() + ,DbU::getValueString(instanceToPlaceWidthSum).c_str() + ); + } + if (_margin < 0.15) + cerr << Warning("Low margin %d, may not be able to complete successfully",_margin) << endl; + + _computeCapacity(); + } + + +void Surface::_preDestroy() +{ + Inherit::_preDestroy(); + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + (*rvit)->destroy(); + _rowVector.clear(); +} + +void Surface::_computeCapacity() +{ + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + (*rvit)->_computeCapacity(_margin); +} + +namespace { + + struct RowSortByY + { + bool operator()(const Container* row1, const Container* row2) const + { + return row1->getYMin() < row2->getYMin(); + } + }; +} + +Row* Surface::InsertSubRowInRow(SubRow* subrow, bool orientation) +{ + //cerr << subrow << endl; + Row* row = NULL; + if (_rowVector.size() == 0) + { + row = Row::create(getCell(), this, subrow->getBox(), orientation); + _rowVector.push_back(row); + } + else + { + RowVector::iterator rvit = lower_bound(_rowVector.begin(), _rowVector.end(), subrow, RowSortByY()); + if (rvit == _rowVector.end()) + { + row = Row::create(getCell(), this, subrow->getBox(), orientation); + _rowVector.push_back(row); + } + else if ((*rvit)->getYMin() == subrow->getYMin()) + { + row = *rvit; + if (row->_orientation != orientation) + { + cerr << "PROBLEM in " << row << " orientation with " << subrow << endl; + } + //assert(row->_orientation == orientation); + } + else + { + row = Row::create(getCell(), this, subrow->getBox(), orientation); + _rowVector.insert(rvit, row); + } + } + row->_InsertSubRow(subrow); + //cerr << row << endl; + return row; +} + +void Surface::_computeRowsAndSubRows() +{ + _rowYMax.clear(); + _rowYMinInv.clear(); + for (unsigned i = 0; i < _rowVector.size(); i++) + { + Row* row = _rowVector[i]; + _rowYMax[row->getYMax()] = i; + _rowYMinInv[row->getYMin()] = i; + row->_computeSubRows(); + } +} + +Bin* Surface::getBinInSurface(Bin* srcbin, double dist) +{ + Point srcPos = srcbin->getCenter(); + + DbU::Unit lowerY = srcPos.getY() - DbU::lambda((dist * DbU::getLambda(_searchHeight))); + if (lowerY < getYMin()) + lowerY = getYMin(); + DbU::Unit upperY = srcPos.getY() + DbU::lambda((dist * DbU::getLambda(_searchHeight))); + if (upperY > getYMax()) + upperY = getYMax(); + + RowYMax::iterator rinf = _rowYMax.upper_bound(lowerY); + RowYMax::iterator rsup = _rowYMinInv.upper_bound(upperY); + + + unsigned randidx = rinf->second + + (unsigned)((rsup->second - rinf->second + 1) * (rand() / (RAND_MAX+1.0))); + + Row* searchRow = _rowVector[randidx]; + + DbU::Unit lowerX = srcPos.getX() - DbU::lambda((dist * DbU::getLambda(_searchWidth))); + if ((lowerX < searchRow->getXMin()) || (lowerX > searchRow->getXMax())) + lowerX = searchRow->getXMin(); + DbU::Unit upperX = srcPos.getX() + DbU::lambda((dist * DbU::getLambda(_searchWidth))); + if ((upperX > searchRow->getXMax()) || (upperX < searchRow->getXMin())) + upperX = searchRow->getXMax(); + + SubRow* subRow = searchRow->getSubRowBetween(lowerX, upperX); + + if ((lowerX < subRow->getXMin()) || (lowerX > subRow->getXMax())) + lowerX = subRow->getXMin(); + if ((upperX > subRow->getXMax()) || (upperX < subRow->getXMin())) + upperX = subRow->getXMax(); + + Bin* dstBin = subRow->getBinBetween(lowerX, upperX, srcbin); + return dstBin; +} + +double Surface::getBinCost() const +{ + double binCost = 0.0; + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + binCost += (*rvit)->getBinCost(); + return binCost; +} + +double Surface::getRowCost() const +{ + double rowCost = 0.0; + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + rowCost += (*rvit)->getCost(); + return rowCost; +} + +DbU::Unit Surface::getBinsSize() const +{ + DbU::Unit totalBinsSize = 0; + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + totalBinsSize += (*rvit)->getBinsSize(); + return totalBinsSize; +} + +DbU::Unit Surface::getBinsCapa() const +{ + DbU::Unit totalBinsCapa = 0; + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + totalBinsCapa += (*rvit)->getBinsCapa(); + return totalBinsCapa; +} + +DbU::Unit Surface::getSubRowsCapa() const +{ + DbU::Unit totalSubRowsCapa = 0; + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + { + totalSubRowsCapa += (*rvit)->getSubRowsCapa(); + } + return totalSubRowsCapa; +} + +namespace { + +class sortInstanceOccurrencesIdsByWidth +{ + private: MaukaEngine* _mauka; + public: sortInstanceOccurrencesIdsByWidth(MaukaEngine* mauka): _mauka(mauka) {} + public: + bool operator()(unsigned instanceoccurrenceid1, unsigned instanceoccurrenceid2) const + { + DbU::Unit width1 = _mauka->getInstanceIdWidth(instanceoccurrenceid1); + DbU::Unit width2 = _mauka->getInstanceIdWidth(instanceoccurrenceid2); + return width1 > width2; + } +}; + +} + + +void Surface::_DisplayInstances(MaukaEngine::UVector& instanceids, SubRowList& subrowlist) +{ + // Insert instances in subrows + sort(instanceids.begin(), instanceids.end(), sortInstanceOccurrencesIdsByWidth(_mauka)); + + SubRowList::iterator srlit = subrowlist.begin(); + MaukaEngine::UVector::const_iterator insIterator = instanceids.begin(); + MaukaEngine::UVector::const_iterator lastLoopInsertedInsIterator = insIterator; + + + while(true) + { + if (insIterator == instanceids.end()) + { + cmess1 << " o Initial placement computing ... done. " << endl; + break; + // end of insertion + } + + if (srlit == subrowlist.end()) + { + srlit = subrowlist.begin(); + if (lastLoopInsertedInsIterator != insIterator) + lastLoopInsertedInsIterator = insIterator; + else + { + // insertion of instances with respect of Bins margin + // did not succed, inserting what's left. + while (insIterator != instanceids.end()) + { + for (SubRow::BinVector::iterator bvit = (*srlit)->_binVector.begin(); + bvit != (*srlit)->_binVector.end(); + bvit++) + { + Bin* bin = *bvit; + unsigned instanceId = *insIterator; + DbU::Unit instanceWidth = _mauka->_instanceWidths[instanceId]; + if (instanceWidth > (*srlit)->getWidthVsSize()) + break; + bin->addInstance(instanceId); + ++insIterator; + if (insIterator == instanceids.end()) + break; + } + if (insIterator == instanceids.end()) + break; + ++srlit; + if (srlit == subrowlist.end()) + { + if (lastLoopInsertedInsIterator == insIterator) + { + //impossible to succeed + // try to merge all bins in subrows + bool merged = false; + for (srlit = subrowlist.begin(); + srlit != subrowlist.end(); + srlit++) + { + merged = (*srlit)->_MergeBins(); + } + + if (merged) + { + insIterator = instanceids.begin(); + } + else + { + //count instances to place + unsigned nbInstancesToPlace = 0; + while (insIterator++ != instanceids.end()) + ++nbInstancesToPlace; + throw Error("Not enough free space to place all the instances.\n" + "Please increase the abutment box: %s (%d instances remains to place)" + ,getString(getBoundingBox()).c_str() + ,nbInstancesToPlace + ); + } + } + srlit = subrowlist.begin(); + lastLoopInsertedInsIterator = insIterator; + } + } + } + } + + if (insIterator != instanceids.end()) + { + SubRow* subRow = *srlit; + for (SubRow::BinVector::iterator bvit = (*srlit)->_binVector.begin(); + bvit != (*srlit)->_binVector.end(); + bvit++) + { + Bin* bin = *bvit; + if (insIterator == instanceids.end()) + break; + unsigned instanceId = *insIterator; + DbU::Unit instanceWidth = _mauka->_instanceWidths[instanceId]; + if (instanceWidth > subRow->getCapaVsSize()) + break; + if (bin->TryAddInstance(instanceId)) + ++insIterator; + } + ++srlit; + } + } +} + +Record* Surface::_getRecord() const +{ + Record* record = Inherit::_getRecord(); + if (record) { + record->add(getSlot("MaukaEngine", _mauka)); + } + return record; +} + +void Surface::DisplayBinHits() const +{ + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + (*rvit)->DisplayBinHits(); +} + +void Surface::PlotBinsStats(ofstream& out) const +{ + out << "plot [:] '-' w l 2" << endl ; +} + +void Surface::Plot(ofstream& out) const +{ + out << getXMin() << " " << getYMin() << endl + << getXMin() << " " << getYMax() << endl + << getXMax() << " " << getYMax() << endl + << getXMax() << " " << getYMin() << endl + << getXMin() << " " << getYMin() << endl << endl; + out << "EOF" << endl; +} + +} diff --git a/mauka/src/Surface.cpp.noRefactor b/mauka/src/Surface.cpp.noRefactor new file mode 100644 index 00000000..48d634fc --- /dev/null +++ b/mauka/src/Surface.cpp.noRefactor @@ -0,0 +1,895 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#include "CEditor.h" +using namespace CRL; + +#include "Nimbus.h" +using namespace NIMBUS; +#include "Mauka.h" +#include "SimAnnealingPlacer.h" +#include "SubRow.h" +#include "Row.h" +#include "Surface.h" + +namespace MAUKA { + +namespace { +void VerifyInstanceQuadtreeInsertion(Cell *cell) +{ + cerr << "VerifyInstanceQuadtreeInsertion" << endl; + for_each_instance(instance, cell->GetInstances()) + { + if (!instance->IsMaterialized()) + { + Cell* masterCell = instance->GetMasterCell(); + cerr << tab << instance << " of " << masterCell << " is not materialized..." << endl; + tab++; + VerifyInstanceQuadtreeInsertion(masterCell); + tab--; + } + end_for; + } +} + +void DisplayInstanceOccurrence(Occurrence& instanceOccurrence) +{ + cerr << instanceOccurrence << " " << instanceOccurrence.GetBoundingBox() << endl; + Instance* instance = static_cast(instanceOccurrence.GetEntity()); + Path path = instanceOccurrence.GetPath(); + cerr << path.GetTransformation() << endl; + cerr << instance->GetTransformation() << endl; + while (!path.IsEmpty()) + { + cerr << path.GetTailInstance() << " " << path.GetTailInstance()->GetTransformation() << endl; + cerr << path.GetTailInstance()->GetMasterCell() << endl; + cerr << path.GetTailInstance()->GetMasterCell()->GetAbutmentBox() << endl; + cerr << path.GetTailInstance()->GetMasterCell()->GetBoundingBox() << endl; + cerr << path.GetTailInstance()->GetAbutmentBox() << endl; + cerr << path.GetTailInstance()->GetBoundingBox() << endl; + path = path.GetHeadPath(); + } +} + +void DisplayNonLeafInstances(Cell* cell, Box area) +{ + ltrace(100) << "display of " << cell << " in " << area << endl; + for_each_instance(instance, cell->GetNonLeafInstancesUnder(area)) + { + ltrace(100) << instance << " " << instance->GetBoundingBox() << endl; + Cell* masterCell = instance->GetMasterCell(); + ltracein(20); + DisplayNonLeafInstances(masterCell, area); + ltraceout(20); + end_for; + } +} + +} + +Surface::Surface(Mauka* mauka, const Box& placementbox, double searchratio) : + Inherit(mauka->GetCell(), placementbox), + _mauka(mauka), + _rowVector(), + _rowYMax(), + _rowYMinInv(), + _rowZeroOrientation(false), + _margin(0.0), + _binWidthMax(0), + _binWidthMin(0), + _searchRatio(searchratio), + _searchWidth(0), + _searchHeight(0) +{} + +Surface* Surface::Create(Mauka* mauka, const Box& placementbox, double searchratio) { + if (!mauka) { + throw Error("Can't create " + _TName("Surface") + " : empty mauka"); + } + + if (!mauka->GetCell()) { + throw Error("Can't create " + _TName("Surface") + " : empty cell on mauka"); + } + + Surface* surface = new Surface(mauka, placementbox, searchratio); + + surface->_PostCreate(); + + return surface; +} + +namespace { + +void PlacementVerification(Cell* cell, Box& box) { + set occurrenceSet; + for_each_occurrence(occurrence, cell->GetLeafInstanceOccurrencesUnder(box)) { + occurrenceSet.insert(occurrence); + end_for; + } + for_each_occurrence(occurrence, cell->GetLeafInstanceOccurrences()) { + if (occurrenceSet.find(occurrence) == occurrenceSet.end()) { + cerr << occurrence << ":" << occurrence.GetBoundingBox() << endl; + throw Error("occurrence is badly placed"); + } + end_for; + } +} + +typedef list InstanceOccurrencesList; + +class PlacementProblem { + public: GCell* _gcell; + public: InstanceOccurrencesList _fixedInstanceOccurrenceList; + public: Mauka::UVector _toPlaceInstanceOccurrencesUVector; + public: Surface::SubRowList _subRowList; + PlacementProblem(GCell* gcell) + : _gcell(gcell) + , _fixedInstanceOccurrenceList() + , _toPlaceInstanceOccurrencesUVector() + , _subRowList() + {} +}; + +typedef list PlacementProblemList; + +} + +void Surface::_PostCreate() { + typedef set OccurrenceSet; + Inherit::_PostCreate(); + + Nimbus* nimbus = NULL; + if (_box.IsEmpty()) { + nimbus = GetNimbus(GetCell()); + if (!nimbus) { + throw Error("Can't create " + _TName("Surface") + " : no Box and no Nimbus"); + } + _box = nimbus->GetGrid()->GetRoot()->GetBox(); + } + + PlacementVerification(GetCell(), _box); + + + Unit sliceHeight = GetUnit(1); + Unit pitch = GetUnit(1); + + CDataBase* cdb = GetCDataBase(); + if (cdb != NULL) { + sliceHeight = GetCDataBase()->GetDefaultCGSliceHeight(); + pitch = GetCDataBase()->GetDefaultCGPitch(); + } else { + //for the moment very stupid method... take the first instantiated cell + for_each_instance(instance, GetCell()->GetInstances()) { + Cell* masterCell = instance->GetMasterCell(); + sliceHeight = masterCell->GetAbutmentBox().GetHeight(); + break; + end_for; + } + + } + + if (_box.IsEmpty() || _box.IsPonctual() ||_box.IsFlat()) { + throw Error("Wrong Box for Area"); + } + if (GetHeight() % sliceHeight) { + throw Error("Box Height must be a multiple of Slice Height"); + } + + + + Unit instanceToPlaceWidthMax = 0; + Unit instanceToPlaceWidthSum = 0; + + for (unsigned id = 0; id < _mauka->_instanceWidths.size(); id++) + { + Unit instanceWidth = _mauka->_instanceWidths[id]; + instanceToPlaceWidthSum += instanceWidth; + if (instanceWidth % pitch) + { + cerr << _mauka->_instanceOccurrencesVector[id] << endl; + throw Error("Instance width (" + GetString(instanceWidth) + ") is not a multiple of pitch (" + GetString(pitch) + ")."); + } + if (instanceWidth > instanceToPlaceWidthMax) + instanceToPlaceWidthMax = instanceWidth; + } + + _binWidthMax = GetUnit((unsigned)( + 2.0 * GetValue(instanceToPlaceWidthMax) / GetValue(pitch)) * GetValue(pitch)); + _binWidthMin = GetUnit((unsigned)( + GetValue(_binWidthMax) / (GetValue(pitch) * 2)) * GetValue(pitch)); + + Unit surfaceTotalWidth = 0; + + + PlacementProblemList placementProblemList; + OccurrenceSet verifyInstanceOccurrencesSet; + + if (nimbus) + { + // cerr << "verif" << endl; + for_each_gcell(gcell, nimbus->GetPlacementLeaves()) + { + // cerr << gcell << endl; + PlacementProblem* placementProblem = new PlacementProblem(gcell); + placementProblemList.push_back(placementProblem); + + InstanceOccurrencesList toPlaceInstanceOccurrencesList; + //search for preplaced leaf instances + for_each_occurrence(occurrence, _mauka->GetCell()->GetLeafInstanceOccurrencesUnder(gcell->GetBox())) + { + Instance* instance = static_cast(occurrence.GetEntity()); + if (instance->IsFixed()) + { + placementProblem->_fixedInstanceOccurrenceList.push_back(occurrence); + //cerr << "Fixed : " << occurrence << endl; + } + else + { + Mauka::InstanceOccurrencesMap::const_iterator + iomit = _mauka->_instanceOccurrencesMap.find(occurrence); + if (iomit == _mauka->_instanceOccurrencesMap.end()) + { + throw Error("bug"); + } + // cerr << occurrence << endl; + placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(iomit->second); + verifyInstanceOccurrencesSet.insert(occurrence); + } + end_for; + } + // cerr << endl << endl; + +// Unit searchWidth = GetUnit(floor(0.3 * GetValue(gcell->GetWidth()))); + Unit searchWidth = GetUnit(_searchRatio * GetValue(gcell->GetWidth())); + if (_searchWidth < searchWidth) + _searchWidth = searchWidth; +// Unit searchHeight = GetUnit(floor(0.3 * GetValue(gcell->GetHeight()))); + Unit searchHeight = GetUnit(_searchRatio * GetValue(gcell->GetHeight())); + if (_searchHeight < searchHeight) + _searchHeight = searchHeight; + end_for; + } + + + for (PlacementProblemList::iterator pplit = placementProblemList.begin(); + pplit != placementProblemList.end(); + pplit++) + { + PlacementProblem* placementProblem = *pplit; + GCell* gcell = placementProblem->_gcell; + + if (placementProblem->_fixedInstanceOccurrenceList.size() != 0) + { + bool rowZeroOrientation = false; + int width = (unsigned)(gcell->GetWidth() / pitch); //number of x pitch + int height = (unsigned)(gcell->GetHeight() / sliceHeight); //number of y slices + + + Mauka::PrePlaceTab prePlaceTab(height, Mauka::PrePlaceRow(width, false)); + + InstanceOccurrencesList::const_iterator iolit = placementProblem->_fixedInstanceOccurrenceList.begin(); + + // find the orientation of the first row. + Instance* refInstance = static_cast(iolit->GetEntity()); + Box refAbutmentBox = refInstance->GetAbutmentBox(); + Transformation refTransformation = refInstance->GetTransformation(); + iolit->GetPath().GetTransformation().ApplyOn(refAbutmentBox); + iolit->GetPath().GetTransformation().ApplyOn(refTransformation); + + Box preplacedBox = gcell->GetIntersection(refAbutmentBox); + + // position en y ramene au slice + int refInsYPos = (int)((preplacedBox.GetYMin() - gcell->GetYMin()) / sliceHeight); + // hauteur ramene a la hauteur du slice + int refInsSliceHeight = (int)(preplacedBox.GetHeight() / sliceHeight); + Transformation::Orientation orientation = refTransformation.GetOrientation(); + //cerr << "refInstance : " << *iolit << " : " << preplacedBox << ":" << refTransformation << endl; + + if (refInsYPos % 2 == 0) + { + if ((refInsSliceHeight % 2 == 0) + || (orientation == Transformation::Orientation::ID) + || (orientation == Transformation::Orientation::MX)) + rowZeroOrientation = true; + else + rowZeroOrientation = false; + } + else + { + if ((refInsSliceHeight % 2 == 0) + || (orientation == Transformation::Orientation::ID) + || (orientation == Transformation::Orientation::MX)) + rowZeroOrientation = false; + else + rowZeroOrientation = true; + } + + // tests for each instance + for (InstanceOccurrencesList::iterator iolit = placementProblem->_fixedInstanceOccurrenceList.begin(); + iolit != placementProblem->_fixedInstanceOccurrenceList.end(); + iolit++) + { + Instance* instance = static_cast(iolit->GetEntity()); + Box instanceAbutmentBox = instance->GetAbutmentBox(); + iolit->GetPath().GetTransformation().ApplyOn(instanceAbutmentBox); + + Box preplacedBox = gcell->GetIntersection(instanceAbutmentBox); + + Unit insWidth = preplacedBox.GetWidth(); + Unit insHeight = preplacedBox.GetHeight(); + + int insPitchWidth = (int)(insWidth / pitch); // largeur ramene au pitch + int insSliceHeight = (int)(insHeight / sliceHeight); // hauteur ramene a la hauteur du slice + + int ypos = (int)((preplacedBox.GetYMin() - gcell->GetYMin()) / sliceHeight); // position en y ramene au slice + int xpos = (int)((preplacedBox.GetXMin() - gcell->GetXMin()) / pitch); // position en x ramene au pitch + +#if 0 + + if ((pins->YINS - _dy) % 50 != 0) + { + cerr << " o ERROR : in preplacement file : y position of " + << pins->INSNAME << " is incorrect" << endl; + exit (1); + } + + if ((pins->XINS - _dx) % 5 != 0) + { + cerr << " o ERROR : in preplacement file : x position of " + << pins->INSNAME << " is incorrect" << endl; + exit (1); + } + + if ( (pins->TRANSF == ROT_P) || (pins->TRANSF == ROT_M) + || (pins->TRANSF == SY_RP) || (pins->TRANSF == SY_RM) ) + { + cerr << " o ERROR : " << pins->INSNAME << " : incorrect rotation" << endl; + exit(1); + } + + // check if orientation of instance matches + bool insOrient; + if ((pinsheightrow == 2) || (pins->TRANSF == NOSYM) || (pins->TRANSF == SYM_X)) + insOrient = true; + else + insOrient = false; + + if ( ((ycoord % 2 == 0) && (insOrient != rowZeroOrientation)) + || ((ycoord % 2 != 0) && (insOrient == rowZeroOrientation)) ) + { + cerr << " o ERROR : " << pins->INSNAME << " badly oriented" << endl + << " Incoherence with " << refpins->INSNAME << endl; + exit(1); + } +#endif + + for (int yit = ypos; yit < ypos + insSliceHeight; yit++) + { + for (int xit = xpos; xit < xpos + insPitchWidth; xit++) + { + if ( (xit > width - 1) || (yit > height - 1) + || (xit < 0 ) || (yit < 0 ) ) + { + cerr << " o ERROR : " << *iolit + << " out of the abutment box" << endl; + exit(1); + } + if (prePlaceTab[yit][xit] == false) + { + prePlaceTab[yit][xit] = true; + } + else + { + cerr << " o ERROR : " << *iolit + << " badly placed .... There is already an instance at its position ...." + << endl; + exit (1); + } + } + } + } + + + bool rowOrientation = rowZeroOrientation; + for (int y = 0; y < (int)prePlaceTab.size(); y++) + { + int x = 0; + while (x < (int)prePlaceTab[y].size()) + { + while ((x < (int)prePlaceTab[y].size()) && (prePlaceTab[y][x] == true)) + ++x; + Unit subRowXMin = gcell->GetXMin() + x * pitch; + + if (x >= (int)prePlaceTab[y].size()) + break; + + while ((x < (int)prePlaceTab[y].size()) && (prePlaceTab[y][x] == false)) + ++x; + Unit subRowXMax = gcell->GetXMin() + x * pitch; + if (subRowXMax - subRowXMin > _binWidthMin) + { + //cerr << "orientation " << rowOrientation << endl; + SubRow* subRow = SubRow::Create(GetCell(), this, + Box(subRowXMin, gcell->GetYMin() + y * sliceHeight + , subRowXMax, gcell->GetYMin() + (y+1) * sliceHeight) + , rowOrientation); + //cerr << "after create : " << subRow << endl; + placementProblem->_subRowList.push_back(subRow); + } + + } + rowOrientation = !rowOrientation; + } + } + else + { + bool rowOrientation = false; + for (Unit ymin = gcell->GetYMin(); ymin <= gcell->GetYMax() - sliceHeight; ymin += sliceHeight) + { + SubRow* subRow = SubRow::Create(GetCell(), this + , Box(gcell->GetXMin(), ymin, gcell->GetXMax(), ymin + sliceHeight), rowOrientation); + placementProblem->_subRowList.push_back(subRow); + rowOrientation = !rowOrientation; + } + } + } + } + else + { + PlacementProblem* placementProblem = new PlacementProblem(NULL); + _searchHeight = GetHeight(); + _searchWidth = GetWidth(); + bool rowOrientation = false; + unsigned nRows = GetHeight() / sliceHeight; + surfaceTotalWidth = GetWidth() * nRows; + + for (Unit ymin = GetYMin(); ymin <= GetYMax() - sliceHeight; ymin += sliceHeight) + { + SubRow* subRow = SubRow::Create(GetCell(), this + , Box(GetXMin(), ymin, GetXMax(), ymin + sliceHeight), rowOrientation); + placementProblem->_subRowList.push_back(subRow); + rowOrientation = !rowOrientation; + } + + for (unsigned id = 0; id < _mauka->_instanceOccurrencesVector.size(); id++) + { + placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(id); + } + throw Error("Mauka needs Nimbus"); + } + + for (PlacementProblemList::iterator pplit = placementProblemList.begin(); + pplit != placementProblemList.end(); + pplit++) + { + _DisplayInstances((*pplit)->_toPlaceInstanceOccurrencesUVector, (*pplit)->_subRowList); + delete *pplit; + } + + placementProblemList.clear(); + + + + if (verifyInstanceOccurrencesSet.size() != _mauka->_instanceOccurrencesVector.size()) + { + cerr << "error " << + _mauka->_instanceOccurrencesVector.size() - verifyInstanceOccurrencesSet.size() + << " not taken into account" << endl; + VerifyInstanceQuadtreeInsertion(_mauka->GetCell()); + for (Mauka::InstanceOccurrencesVector::iterator iovit = _mauka->_instanceOccurrencesVector.begin(); + iovit != _mauka->_instanceOccurrencesVector.end(); + iovit++) + { + OccurrenceSet::iterator osit = verifyInstanceOccurrencesSet.find(*iovit); + if (osit == verifyInstanceOccurrencesSet.end()) + { + cerr << " o problem with " << *iovit << endl; + DisplayInstanceOccurrence(*iovit); + cerr << "display" << endl; + DisplayNonLeafInstances(_mauka->GetCell(), iovit->GetBoundingBox()); +#if 0 + for_each_occurrence(occurrence, + _mauka->GetCell()->GetLeafInstanceOccurrencesUnder(_mauka->GetCell()->GetAbutmentBox())) + { + if (occurrence == *iovit) + { + cerr << occurrence << "found " << occurrence.GetBoundingBox() << endl; + cerr << "ounce again" << endl; + DisplayNonLeafInstances(_mauka->GetCell(), occurrence.GetBoundingBox()); + break; + } + end_for; + } +#endif + return; + } + } + throw Error(""); + } + + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + { + surfaceTotalWidth += (*rvit)->GetSubRowsWidth(); + } + + _ComputeRowsAndSubRows(); + + + _margin = 1.0 - GetValue(instanceToPlaceWidthSum) / GetValue(surfaceTotalWidth); + if (_margin < 0) + { + cerr << "Surface Free Space = " << surfaceTotalWidth << endl; + cerr << "To Place Instances Width = " << instanceToPlaceWidthSum << endl; + throw Error(" o Mauka Error : there is not enough free space to place the circuit"); + } + if (_margin < 0.15) + cerr << _margin << " margin in area: possible problems" << endl; + + _ComputeCapacity(); + +} + +void Surface::_PreDelete() +{ + Inherit::_PreDelete(); + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + (*rvit)->Delete(); + _rowVector.clear(); +} + +void Surface::_ComputeCapacity() +{ + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + (*rvit)->_ComputeCapacity(_margin); +} + +namespace { + + struct RowSortByY + { + bool operator()(const Container* row1, const Container* row2) const + { + return row1->GetYMin() < row2->GetYMin(); + } + }; +} + +Row* Surface::InsertSubRowInRow(SubRow* subrow, bool orientation) +{ + //cerr << subrow << endl; + Row* row = NULL; + if (_rowVector.size() == 0) + { + row = Row::Create(GetCell(), this, subrow->GetBox(), orientation); + _rowVector.push_back(row); + } + else + { + RowVector::iterator rvit = lower_bound(_rowVector.begin(), _rowVector.end(), subrow, RowSortByY()); + if (rvit == _rowVector.end()) + { + row = Row::Create(GetCell(), this, subrow->GetBox(), orientation); + _rowVector.push_back(row); + } + else if ((*rvit)->GetYMin() == subrow->GetYMin()) + { + row = *rvit; + if (row->_orientation != orientation) + { + cerr << "PROBLEM in " << row << " orientation with " << subrow << endl; + } + //assert(row->_orientation == orientation); + } + else + { + row = Row::Create(GetCell(), this, subrow->GetBox(), orientation); + _rowVector.insert(rvit, row); + } + } + row->_InsertSubRow(subrow); + //cerr << row << endl; + return row; +} + +void Surface::_ComputeRowsAndSubRows() +{ + _rowYMax.clear(); + _rowYMinInv.clear(); + for (unsigned i = 0; i < _rowVector.size(); i++) + { + Row* row = _rowVector[i]; + _rowYMax[row->GetYMax()] = i; + _rowYMinInv[row->GetYMin()] = i; + row->_ComputeSubRows(); + } +} + +Bin* Surface::GetBinInSurface(Bin* srcbin, double dist) +{ + Point srcPos = srcbin->GetCenter(); + + Unit lowerY = srcPos.GetY() - GetUnit((dist * GetValue(_searchHeight))); + if (lowerY < GetYMin()) + lowerY = GetYMin(); + Unit upperY = srcPos.GetY() + GetUnit((dist * GetValue(_searchHeight))); + if (upperY > GetYMax()) + upperY = GetYMax(); + + RowYMax::iterator rinf = _rowYMax.upper_bound(lowerY); + RowYMax::iterator rsup = _rowYMinInv.upper_bound(upperY); + + + unsigned randidx = rinf->second + + (unsigned)((rsup->second - rinf->second + 1) * (rand() / (RAND_MAX+1.0))); + + Row* searchRow = _rowVector[randidx]; + + Unit lowerX = srcPos.GetX() - GetUnit((dist * GetValue(_searchWidth))); + if ((lowerX < searchRow->GetXMin()) || (lowerX > searchRow->GetXMax())) + lowerX = searchRow->GetXMin(); + Unit upperX = srcPos.GetX() + GetUnit((dist * GetValue(_searchWidth))); + if ((upperX > searchRow->GetXMax()) || (upperX < searchRow->GetXMin())) + upperX = searchRow->GetXMax(); + + SubRow* subRow = searchRow->GetSubRowBetween(lowerX, upperX); + + if ((lowerX < subRow->GetXMin()) || (lowerX > subRow->GetXMax())) + lowerX = subRow->GetXMin(); + if ((upperX > subRow->GetXMax()) || (upperX < subRow->GetXMin())) + upperX = subRow->GetXMax(); + + Bin* dstBin = subRow->GetBinBetween(lowerX, upperX, srcbin); + return dstBin; +} + +double Surface::GetBinCost() const +{ + double binCost = 0.0; + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + binCost += (*rvit)->GetBinCost(); + return binCost; +} + +double Surface::GetRowCost() const +{ + double rowCost = 0.0; + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + rowCost += (*rvit)->GetCost(); + return rowCost; +} + +Unit Surface::GetBinsSize() const +{ + Unit totalBinsSize = 0; + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + totalBinsSize += (*rvit)->GetBinsSize(); + return totalBinsSize; +} + +Unit Surface::GetBinsCapa() const +{ + Unit totalBinsCapa = 0; + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + totalBinsCapa += (*rvit)->GetBinsCapa(); + return totalBinsCapa; +} + +Unit Surface::GetSubRowsCapa() const +{ + Unit totalSubRowsCapa = 0; + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + { + totalSubRowsCapa += (*rvit)->GetSubRowsCapa(); + } + return totalSubRowsCapa; +} + +namespace { + +class SortInstanceOccurrencesIdsByWidth +{ + private: Mauka* _mauka; + public: SortInstanceOccurrencesIdsByWidth(Mauka* mauka): _mauka(mauka) {} + public: + bool operator()(unsigned instanceoccurrenceid1, unsigned instanceoccurrenceid2) const + { + Unit width1 = _mauka->GetInstanceIdWidth(instanceoccurrenceid1); + Unit width2 = _mauka->GetInstanceIdWidth(instanceoccurrenceid2); + return width1 > width2; + } +}; + +} + + +void Surface::_DisplayInstances(Mauka::UVector& instanceids, SubRowList& subrowlist) +{ + // Insert instances in subrows + sort(instanceids.begin(), instanceids.end(), SortInstanceOccurrencesIdsByWidth(_mauka)); + + SubRowList::iterator srlit = subrowlist.begin(); + Mauka::UVector::const_iterator insIterator = instanceids.begin(); + Mauka::UVector::const_iterator lastLoopInsertedInsIterator = insIterator; + + + while(1) + { + if (insIterator == instanceids.end()) + { + if (_mauka->_verbosity.ActionIsOn()) + { + cout << " o Initial Placement Computing ... done. " << endl; + } + break; + // end of insertion + } + + if (srlit == subrowlist.end()) + { + srlit = subrowlist.begin(); + if (lastLoopInsertedInsIterator != insIterator) + lastLoopInsertedInsIterator = insIterator; + else + { + // insertion of instances with respect of Bins margin + // did not succed, inserting what's left. + while (insIterator != instanceids.end()) + { + for (SubRow::BinVector::iterator bvit = (*srlit)->_binVector.begin(); + bvit != (*srlit)->_binVector.end(); + bvit++) + { + Bin* bin = *bvit; + unsigned instanceId = *insIterator; + Unit instanceWidth = _mauka->_instanceWidths[instanceId]; + if (instanceWidth > (*srlit)->GetWidthVsSize()) + break; + bin->AddInstance(instanceId); + ++insIterator; + if (insIterator == instanceids.end()) + break; + } + if (insIterator == instanceids.end()) + break; + ++srlit; + if (srlit == subrowlist.end()) + { + if (lastLoopInsertedInsIterator == insIterator) + { + //impossible to succeed + // try to merge all bins in subrows + bool merged = false; + for (srlit = subrowlist.begin(); + srlit != subrowlist.end(); + srlit++) + { + merged = (*srlit)->_MergeBins(); + } + + if (merged) + { + insIterator = instanceids.begin(); + } + else + { + //count instances to place + unsigned nbInstancesToPlace = 0; + while (insIterator++ != instanceids.end()) + ++nbInstancesToPlace; + cerr << " o There is not enough free space, I need a bigger abutment box ......" << endl; + cerr << " o There are still " + << nbInstancesToPlace + << " Instances to place ..." << endl; + throw Error(""); + } + } + srlit = subrowlist.begin(); + lastLoopInsertedInsIterator = insIterator; + } + } + } + } + + if (insIterator != instanceids.end()) + { + SubRow* subRow = *srlit; + for (SubRow::BinVector::iterator bvit = (*srlit)->_binVector.begin(); + bvit != (*srlit)->_binVector.end(); + bvit++) + { + Bin* bin = *bvit; + if (insIterator == instanceids.end()) + break; + unsigned instanceId = *insIterator; + Unit instanceWidth = _mauka->_instanceWidths[instanceId]; + if (instanceWidth > subRow->GetCapaVsSize()) + break; + if (bin->TryAddInstance(instanceId)) + ++insIterator; + } + ++srlit; + } + } +} + +Record* Surface::_GetRecord() const +{ + Record* record = Inherit::_GetRecord(); + if (record) { + record->Add(GetSlot("Mauka", _mauka)); + } + return record; +} + +void Surface::DisplayBinHits() const +{ + for (RowVector::const_iterator rvit = _rowVector.begin(); + rvit != _rowVector.end(); + rvit++) + (*rvit)->DisplayBinHits(); +} + +void Surface::PlotBinsStats(ofstream& out) const +{ + out << "plot [:] '-' w l 2" << endl ; +} + +void Surface::Plot(ofstream& out) const +{ + out << GetXMin() << " " << GetYMin() << endl + << GetXMin() << " " << GetYMax() << endl + << GetXMax() << " " << GetYMax() << endl + << GetXMax() << " " << GetYMin() << endl + << GetXMin() << " " << GetYMin() << endl << endl; + out << "EOF" << endl; +} + +} diff --git a/mauka/src/mauka/BBPlacer.h b/mauka/src/mauka/BBPlacer.h new file mode 100644 index 00000000..bd46557c --- /dev/null +++ b/mauka/src/mauka/BBPlacer.h @@ -0,0 +1,126 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __BBPLACER_H +#define __BBPLACER_H + +#include "hurricane/Instance.h" +#include "mauka/SubRow.h" +#include "mauka/MaukaEngine.h" + +namespace Mauka { + + using Hurricane::DbU; + +// **************************************************************************************************** +// BBPlacer declaration +// **************************************************************************************************** + +class BBPlacer { +// ************* + + friend class MaukaEngine; + +// Types +// ***** + public: typedef std::vector SubRowVector; +// Attributes +// ********** + private: MaukaEngine* _mauka; + private: SubRowVector _subRowVector; + private: MaukaEngine::UTable _subRowInstances; + private: MaukaEngine::UnitVector _instanceMarginWidth; + private: MaukaEngine::UnitVector _instanceX; // Left Corner X position + private: MaukaEngine::UnitVector _instanceY; + private: MaukaEngine::BVector _instancePlaced; + private: MaukaEngine::NetVector _netVector; + private: MaukaEngine::BBoxes _netBBoxes; + private: MaukaEngine::Costs _netCosts; + private: MaukaEngine::UVector _netCurrCostMark; + private: MaukaEngine::UVector _netFlags; + // For the optimization engine itself + private: MaukaEngine::UVector _instanceToOptimize; + private: DbU::Unit _leftEdge; + private: DbU::Unit _rightEdge; + private: double _oldCost; + private: double _cost; + private: double _bestCost; + // _costFlag is for computing nets costs + // Each net must be visited only one time + private: unsigned _costFlag; + private: unsigned _saveFlag; + private: std::deque _queue; // ordering + private: MaukaEngine::UVector _stack; + private: MaukaEngine::UVector _loopVect; // use for loop + private: MaukaEngine::UnitVector _bestSolution; + private: int _idx; + +// Constructors +// ************ + public: BBPlacer(MaukaEngine* mauka); + +// Accessors +// ********* + public: DbU::Unit getInstanceIdX(unsigned id) const { return _instanceX[id]; } + +// Updators +// ******** + +// Others +// ****** + + public: void Run(); + public: void Save(); + private: bool Optimize(); + private: double initCost(); + private: double CurrentCost(); + private: void PlaceAll(); + private: void UnplaceAll(); + private: void addIns(); + private: void removeIns(); + private: double UpdateInstanceCost(unsigned instanceid); + private: double UpdateNetCost(unsigned netid); + private: double computeCost(const Box& box) const; + private: double initInstanceCost(unsigned instanceid); + private: double CurrentInstanceCost(unsigned instanceid); + private: void computeNetBBox(unsigned netid); + private: void SaveNetTempValue(unsigned netid); + private: double CurrentNetCost(unsigned netid); + private: void Plot(std::ofstream& out) const; +}; + +} + +#endif // __BBPLACER_H diff --git a/mauka/src/mauka/BBPlacer.h.noRefactor b/mauka/src/mauka/BBPlacer.h.noRefactor new file mode 100644 index 00000000..1d5cfed9 --- /dev/null +++ b/mauka/src/mauka/BBPlacer.h.noRefactor @@ -0,0 +1,126 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __BBPLACER_H +#define __BBPLACER_H + +#include "Instance.h" +USING_NAMESPACE_HURRICANE + +#include "SubRow.h" +#include "Mauka.h" + +namespace MAUKA { + +// **************************************************************************************************** +// BBPlacer declaration +// **************************************************************************************************** + +class BBPlacer { +// ************* + + friend class Mauka; + +// Types +// ***** + public: typedef vector SubRowVector; +// Attributes +// ********** + private: Mauka* _mauka; + private: SubRowVector _subRowVector; + private: Mauka::UTable _subRowInstances; + private: Mauka::UnitVector _instanceMarginWidth; + private: Mauka::UnitVector _instanceX; //Left Corner X position + private: Mauka::UnitVector _instanceY; + private: Mauka::BVector _instancePlaced; + private: Mauka::NetVector _netVector; + private: Mauka::BBoxes _netBBoxes; + private: Mauka::Costs _netCosts; + private: Mauka::UVector _netCurrCostMark; + private: Mauka::UVector _netFlags; + // For the optimization engine itself + private: Mauka::UVector _instanceToOptimize; + private: Unit _leftEdge; + private: Unit _rightEdge; + private: double _oldCost; + private: double _cost; + private: double _bestCost; + // _costFlag is for computing nets costs + // Each net must be visited only one time + private: unsigned _costFlag; + private: unsigned _saveFlag; + private: deque _queue; // ordering + private: Mauka::UVector _stack; + private: Mauka::UVector _loopVect; // use for loop + private: Mauka::UnitVector _bestSolution; + private: int _idx; + +// Constructors +// ************ + public: BBPlacer(Mauka* mauka); + +// Accessors +// ********* + public: Unit GetInstanceIdX(unsigned id) const { return _instanceX[id]; } + +// Updators +// ******** + +// Others +// ****** + + public: void Run(); + public: void Save(); + private: bool Optimize(); + private: double InitCost(); + private: double CurrentCost(); + private: void PlaceAll(); + private: void UnplaceAll(); + private: void AddIns(); + private: void RemoveIns(); + private: double UpdateInstanceCost(unsigned instanceid); + private: double UpdateNetCost(unsigned netid); + private: double ComputeCost(const Box& box) const; + private: double InitInstanceCost(unsigned instanceid); + private: double CurrentInstanceCost(unsigned instanceid); + private: void ComputeNetBBox(unsigned netid); + private: void SaveNetTempValue(unsigned netid); + private: double CurrentNetCost(unsigned netid); + private: void Plot(ofstream& out) const; +}; + +} + +#endif // __BBPLACER_H diff --git a/mauka/src/mauka/Bin.h b/mauka/src/mauka/Bin.h new file mode 100644 index 00000000..d80ebe94 --- /dev/null +++ b/mauka/src/mauka/Bin.h @@ -0,0 +1,126 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __BIN_H +#define __BIN_H + +#include "hurricane/Occurrences.h" +#include "mauka/Container.h" +#include "mauka/MaukaEngine.h" + +namespace Mauka { + +using Hurricane::DbU; +using Hurricane::Box; +using Hurricane::Cell; +using Hurricane::Occurrence; +using Hurricane::Occurrences; + +class SubRow; +class SimAnnealingPlacer; + +// **************************************************************************************************** +// Bin declaration +// **************************************************************************************************** + +class Bin : public Container { +// ************************* + +// Friends +// ******* + friend class BBPlacer; + friend class SubRow; + +// Types +// ***** + public: typedef Container Inherit; + +// Attributes +// ********** + private: static const Name _goName; + private: SubRow* _subRow; + private: MaukaEngine* _mauka; + private: MaukaEngine::UList _instanceOccurrenceIds; + private: DbU::Unit _size; // sum of the contained instances width + private: DbU::Unit _capa; // ideal occupation of the bin + private: unsigned _sourceHits; + private: unsigned _targetHits; + +// Constructors +// ************ + protected: Bin(Cell* cell, SubRow* subrow, const Box& box); + public: static Bin* create(Cell* cell, SubRow* subrow, const Box& box); + +// Accessors +// ********* + public: static const Name& getStaticName(); + public: virtual const Name& getName() const; + public: virtual Cell* getCell() const; + public: DbU::Unit getCapaVsSize() const { return (_capa - _size);} + public: DbU::Unit getSize() const { return _size; } + public: DbU::Unit getCapa() const { return _capa; } + public: SubRow* getSubRow() { return _subRow; } + public: unsigned getFirstInstanceOccurrenceId() const { return _instanceOccurrenceIds.front(); } + public: double getCost() const; + public: unsigned getInstanceOccurrenceIdSize() const { return _instanceOccurrenceIds.size(); } + public: const MaukaEngine::UList::const_iterator InstanceOccurrenceIdsBegin() const { return _instanceOccurrenceIds.begin(); } + public: const MaukaEngine::UList::const_iterator InstanceOccurrenceIdsEnd() const { return _instanceOccurrenceIds.end(); } + public: Occurrences getInstanceOccurrences() const; + +// Updators +// ******** + public: void removeInstance(unsigned instanceid); + public: void removeFrontInstance(unsigned instanceid); + public: void removeBackInstance(unsigned instanceid); + public: void addInstance(unsigned instanceid); + private:void _AddSize(DbU::Unit value); + +// Others +// ****** + private: void _computeCapacity(double margin); + public: void DisplayHits() const; + public: void incrementSourceHits(); + public: void incrementTargetHits(); + public: bool TryAddInstance(unsigned instanceid); + public: bool UnderOccupied() const; + protected: virtual void _postCreate(); + public: virtual std::string _getTypeName() const {return "Bin";}; + public: void PlotStats(std::ofstream& out) const; + public: void Plot(std::ofstream& out) const; +}; + +} + +#endif // __BIN_H diff --git a/mauka/src/mauka/Bin.h.noRefactor b/mauka/src/mauka/Bin.h.noRefactor new file mode 100644 index 00000000..d64aa8c3 --- /dev/null +++ b/mauka/src/mauka/Bin.h.noRefactor @@ -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 +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __BIN_H +#define __BIN_H + +#include "Occurrences.h" +USING_NAMESPACE_HURRICANE + +#include "Container.h" +#include "Mauka.h" + +namespace MAUKA { + +class SubRow; +class SimAnnealingPlacer; + +// **************************************************************************************************** +// Bin declaration +// **************************************************************************************************** + +class Bin : public Container { +// ************************* + +// Friends +// ******* + friend class BBPlacer; + friend class SubRow; + +// Types +// ***** + public: typedef Container Inherit; + +// Attributes +// ********** + private: SubRow* _subRow; + private: Mauka* _mauka; + private: Mauka::UList _instanceOccurrenceIds; + private: Unit _size; // sum of the contained instances width + private: Unit _capa; // ideal occupation of the bin + private: unsigned _sourceHits; + private: unsigned _targetHits; + +// Constructors +// ************ + protected: Bin(const Cell* cell, SubRow* subrow, const Box& box); + public: static Bin* Create(const Cell* cell, SubRow* subrow, const Box& box); + +// Accessors +// ********* + public: virtual Cell* GetCell() const; + public: Unit GetCapaVsSize() const { return (_capa - _size);} + public: Unit GetSize() const { return _size; } + public: Unit GetCapa() const { return _capa; } + public: SubRow* GetSubRow() { return _subRow; } + public: unsigned GetFirstInstanceOccurrenceId() const { return _instanceOccurrenceIds.front(); } + public: double GetCost() const; + public: unsigned GetInstanceOccurrenceIdSize() const { return _instanceOccurrenceIds.size(); } + public: const Mauka::UList::const_iterator InstanceOccurrenceIdsBegin() const { return _instanceOccurrenceIds.begin(); } + public: const Mauka::UList::const_iterator InstanceOccurrenceIdsEnd() const { return _instanceOccurrenceIds.end(); } + public: Occurrences GetInstanceOccurrences() const; + +// Updators +// ******** + public: void RemoveInstance(unsigned instanceid); + public: void RemoveFrontInstance(unsigned instanceid); + public: void RemoveBackInstance(unsigned instanceid); + public: void AddInstance(unsigned instanceid); + private:void _AddSize(Unit value); + +// Others +// ****** + private: void _ComputeCapacity(double margin); + public: void DisplayHits() const; + public: void IncrementSourceHits(); + public: void IncrementTargetHits(); + public: bool TryAddInstance(unsigned instanceid); + public: bool UnderOccupied() const; + protected: virtual void _PostCreate(); + public: virtual string _GetTypeName() const {return _TName("Bin");}; + public: void PlotStats(ofstream& out) const; + public: void Plot(ofstream& out) const; +}; + +} + +#endif // __BIN_H diff --git a/mauka/src/mauka/Configuration.h b/mauka/src/mauka/Configuration.h new file mode 100644 index 00000000..396cb87b --- /dev/null +++ b/mauka/src/mauka/Configuration.h @@ -0,0 +1,120 @@ + +// -*- 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 a u k a - P l a c 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 __MAUKA_CONFIGURATION__ +#define __MAUKA_CONFIGURATION__ + +#include + +namespace Hurricane { + class Record; + class Cell; +} + + +namespace Mauka { + + using Hurricane::Cell; + using Hurricane::Record; + + +// ------------------------------------------------------------------- +// Class : "Katabatic::Configuration". + + + class Configuration { + public: + static Configuration* getDefault (); + public: + // Constructor & Destructor. + Configuration (); + ~Configuration (); + Configuration* clone () const; + // Methods. + inline bool useStandardSimulatedAnnealing () const; + inline bool doIgnorePins () const; + inline bool doPlotBins () const; + inline double getSearchRatio () const; + inline double getAnnealingNetMult () const; + inline double getAnnealingBinMult () const; + inline double getAnnealingRowMult () const; + void print ( Cell* ) const; + inline void setStandardSimulatedAnnealing ( bool ); + inline void setIgnorePins ( bool ); + inline void setPlotBins ( bool ); + inline void setSearchRatio ( double ); + inline void setAnnealingNetMult ( double ); + inline void setAnnealingBinMult ( double ); + inline void setAnnealingRowMult ( double ); + inline static double _normPercentage ( double ratio, double min=0.0, double max=1.0 ); + Record* _getRecord () const; + std::string _getString () const; + std::string _getTypeName () const; + private: + // Attributes. + static Configuration* _default; + bool _standardSimulatedAnnealing; + bool _ignorePins; + bool _plotBins; // Plot bins utilisation. + double _searchRatio; + double _annealingNetMult; + double _annealingBinMult; + double _annealingRowMult; + private: + Configuration ( const Configuration& ); + Configuration& operator= ( const Configuration& ); + }; + + +// Inline Methods. + inline bool Configuration::useStandardSimulatedAnnealing () const { return _standardSimulatedAnnealing; } + inline bool Configuration::doIgnorePins () const { return _ignorePins; } + inline bool Configuration::doPlotBins () const { return _plotBins; } + inline double Configuration::getSearchRatio () const { return _searchRatio; } + inline double Configuration::getAnnealingNetMult () const { return _annealingNetMult; } + inline double Configuration::getAnnealingBinMult () const { return _annealingBinMult; } + inline double Configuration::getAnnealingRowMult () const { return _annealingRowMult; } + inline void Configuration::setStandardSimulatedAnnealing ( bool state ) { _standardSimulatedAnnealing=state; } + inline void Configuration::setIgnorePins ( bool state ) { _ignorePins=state; } + inline void Configuration::setPlotBins ( bool state ) { _plotBins=state; } + inline void Configuration::setSearchRatio ( double ratio ) { _searchRatio=_normPercentage(ratio,0.1); } + inline void Configuration::setAnnealingNetMult ( double mult ) { _annealingNetMult=_normPercentage(mult); } + inline void Configuration::setAnnealingBinMult ( double mult ) { _annealingBinMult=_normPercentage(mult); } + inline void Configuration::setAnnealingRowMult ( double mult ) { _annealingRowMult=_normPercentage(mult); } + + inline double Configuration::_normPercentage ( double ratio, double min, double max ) { + if ( ratio < min ) return min; + if ( ratio > max ) return max; + return ratio; + } + + +} // End of Mauka namespace. + + +INSPECTOR_P_SUPPORT(Mauka::Configuration); + + +#endif // __MAUKA_CONFIGURATION__ diff --git a/mauka/src/mauka/ConfigurationWidget.h b/mauka/src/mauka/ConfigurationWidget.h new file mode 100644 index 00000000..d687555d --- /dev/null +++ b/mauka/src/mauka/ConfigurationWidget.h @@ -0,0 +1,84 @@ + +// -*- 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 a u k a - P l a c e r | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./ConfigurationWidget.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + +#ifndef __MAUKA_CONFIGURATION_WIDGET__ +#define __MAUKA_CONFIGURATION_WIDGET__ + +#include +class QLineEdit; +class QCheckBox; + +namespace Nimbus { + class Configuration; +} + +namespace Mauka { + + class Configuration; + + +// ------------------------------------------------------------------- +// Class : "Kite::ConfigurationWidget". + + + class ConfigurationWidget : public QWidget { + Q_OBJECT; + public: + ConfigurationWidget ( QWidget* parent=NULL ); + public slots: + void setConfiguration ( Nimbus::Configuration*, Configuration* ); + void _applySettings (); + void _updateStandardAnnealingState (); + void _updateIgnorePinsState (); + void _updatePlotBinsState (); + void _updatePinsPlacementState (); + void _updateSearchRatio (); + void _updateAnnealingNetMult (); + void _updateAnnealingBinMult (); + void _updateAnnealingRowMult (); + void _updateAspectRatio (); + void _updateMargin (); + private: + Nimbus::Configuration* _nimbusConfiguration; + Configuration* _maukaConfiguration; + QCheckBox* _standardAnnealingState; + QCheckBox* _ignorePinsState; + QCheckBox* _plotBinsState; + QCheckBox* _pinsPlacementState; + QLineEdit* _searchRatioEdit; + QLineEdit* _annealingNetMultEdit; + QLineEdit* _annealingBinMultEdit; + QLineEdit* _annealingRowMultEdit; + QLineEdit* _aspectRatioEdit; + QLineEdit* _marginEdit; + }; + + + +} // End of Mauka namespace. + + +#endif // __MAUKA_CONFIGURATION_WIDGET__ diff --git a/mauka/src/mauka/Container.h b/mauka/src/mauka/Container.h new file mode 100644 index 00000000..385a4196 --- /dev/null +++ b/mauka/src/mauka/Container.h @@ -0,0 +1,98 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __CONTAINER_H +#define __CONTAINER_H + +#include "hurricane/Box.h" +#include "hurricane/ExtensionGo.h" + +namespace Mauka { + +using Hurricane::Record; +using Hurricane::Name; +using Hurricane::DbU; +using Hurricane::Point; +using Hurricane::Box; +using Hurricane::Cell; +using Hurricane::ExtensionGo; + +class Container: public ExtensionGo { +// ******************************** + +// Types +// ***** + public: typedef ExtensionGo Inherit; + +// Attributes +// ********** + private: static const Name _goName; + protected: Box _box; + +// Constructors +// ************ + protected: Container(Cell* cell, const Box& box); +// +// Accessors +// ********* + + public: static const Name& getStaticName(); + public: virtual const Name& getName() const; + public: Box getBoundingBox() const { return _box; }; + public: const Box& getBox() const { return _box; }; + public: const DbU::Unit& getXMin() const { return _box.getXMin(); }; + public: const DbU::Unit& getYMin() const { return _box.getYMin(); }; + public: const DbU::Unit& getXMax() const { return _box.getXMax(); }; + public: const DbU::Unit& getYMax() const { return _box.getYMax(); }; + public: DbU::Unit getHeight() const { return _box.getHeight(); }; + public: DbU::Unit getWidth() const { return _box.getWidth(); }; + public: Point getCenter() const { return _box.getCenter(); } + +// Updators +// ******** + + public: virtual void translate(const DbU::Unit& dx, const DbU::Unit& dy) {} + +// Others +// ****** + public: virtual std::string _getTypeName() const {return "Container";}; + public: virtual std::string _getString() const; + public: virtual Record* _getRecord() const; + +}; + +} + +#endif // __CONTAINER_H diff --git a/mauka/src/mauka/Container.h.noRefactor b/mauka/src/mauka/Container.h.noRefactor new file mode 100644 index 00000000..889beafb --- /dev/null +++ b/mauka/src/mauka/Container.h.noRefactor @@ -0,0 +1,92 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __CONTAINER_H +#define __CONTAINER_H + +#include "Box.h" +#include "UserGo.h" +USING_NAMESPACE_HURRICANE + +namespace MAUKA { + +class Container: public UserGo { +// ****************************** + +// Types +// ***** + public: typedef UserGo Inherit; + +// Attributes +// ********** + protected: Box _box; + +// Constructors +// ************ + protected: Container(const Cell* cell, const Box& box); +// +// Accessors +// ********* + + public: Box GetBoundingBox() const { return _box; }; + public: const Box& GetBox() const { return _box; }; + public: const Unit& GetXMin() const { return _box.GetXMin(); }; + public: const Unit& GetYMin() const { return _box.GetYMin(); }; + public: const Unit& GetXMax() const { return _box.GetXMax(); }; + public: const Unit& GetYMax() const { return _box.GetYMax(); }; + public: Unit GetHeight() const { return _box.GetHeight(); }; + public: Unit GetWidth() const { return _box.GetWidth(); }; + public: Point GetCenter() const { return _box.GetCenter(); } + +// Updators +// ******** + + public: virtual void Translate(const Unit& dx, const Unit& dy) {} + +// Others +// ****** + public: virtual bool _IsInterceptedBy(View* view, const Point& point, const Unit& aperture) const; + public: virtual void _Draw(View* view, BasicLayer* basiclayer, const Box& updatearea, const Transformation& transformation); + public: virtual void _Highlight(View* view, const Box& updatearea, const Transformation& transformation); + + public: virtual string _GetTypeName() const {return _TName("Container");}; + public: virtual string _GetString() const; + public: virtual Record* _GetRecord() const; + +}; + +} + +#endif // __CONTAINER_H diff --git a/mauka/src/mauka/GraphicMaukaEngine.h b/mauka/src/mauka/GraphicMaukaEngine.h new file mode 100644 index 00000000..d952b61f --- /dev/null +++ b/mauka/src/mauka/GraphicMaukaEngine.h @@ -0,0 +1,96 @@ + +// -*- 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 a u k a - P l a c e r | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./GraphicMaukaEngine.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + +#ifndef __MAUKA_GRAPHIC_MAUKA_ENGINE__ +#define __MAUKA_GRAPHIC_MAUKA_ENGINE__ + +#include + +namespace Hurricane { + class Go; + class BasicLayer; + class Transformation; + class CellWidget; + class CellViewer; +} + +#include "crlcore/GraphicToolEngine.h" + +#include "mauka/MaukaEngine.h" + + +namespace Mauka { + + using Hurricane::Go; + using Hurricane::Box; + using Hurricane::BasicLayer; + using Hurricane::Transformation; + using Hurricane::CellWidget; + using Hurricane::CellViewer; + using CRL::GraphicTool; + + +// ------------------------------------------------------------------- +// Class : "Mauka::GraphicMaukaEngine". + + + class GraphicMaukaEngine : public GraphicTool { + Q_OBJECT; + + public: + MaukaEngine* createEngine (); + MaukaEngine* getForFramework (); + static void initMaukaContainer ( CellWidget* ); + static void drawMaukaContainer ( CellWidget* + , const Go* + , const BasicLayer* + , const Box& + , const Transformation& + ); + static GraphicMaukaEngine* grab (); + virtual const Name& getName () const; + Cell* getCell (); + virtual size_t release (); + virtual void addToMenu ( CellViewer* ); + void postEvent (); + public slots: + void run (); + void save (); + + protected: + static size_t _references; + static GraphicMaukaEngine* _singleton; + CellViewer* _viewer; + protected: + GraphicMaukaEngine (); + virtual ~GraphicMaukaEngine (); + }; + + +} // End of Mauka namespace. + + +#endif // __MAUKA_GRAPHIC_MAUKA_ENGINE__ diff --git a/mauka/src/mauka/Mauka.h.noRefactor b/mauka/src/mauka/Mauka.h.noRefactor new file mode 100644 index 00000000..c1c3a7df --- /dev/null +++ b/mauka/src/mauka/Mauka.h.noRefactor @@ -0,0 +1,152 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag + +#ifndef __MAUKA_H +#define __MAUKA_H + +#include "Instance.h" +USING_NAMESPACE_HURRICANE + +#include "CEngine.h" +using namespace CRL; + +#include "GCell.h" +using namespace NIMBUS; + +namespace MAUKA { + +class Surface; +class SimAnnealingPlacer; +class BBPlacer; + +class Mauka: public CEngine +// ************************ +{ + //Mauka: a cool, light, Hawaiian wind descending from the montains. + friend class Surface; + friend class SimAnnealingPlacer; + friend class Move; + friend class Bin; + friend class SubRow; + friend class BBPlacer; +// Types +// ***** + public: typedef CEngine Inherit; + public: typedef vector InstanceOccurrencesVector; + public: typedef map InstanceOccurrencesMap; + public: typedef vector UVector; + public: typedef list UList; + public: typedef vector UTable; + public: typedef vector BVector; + public: typedef vector UnitVector; + public: typedef vector NetVector; + public: typedef vector BoxVector; + public: typedef vector BBoxes; + public: typedef vector > Costs; + public: typedef vector PrePlaceRow; + public: typedef vector PrePlaceTab; + public: + class Parameters + { + public: bool standardSimulatedAnnealing; + public: bool ignorePins; + public: bool plotBins; //plot bins utilisation + public: Parameters() + : standardSimulatedAnnealing(false) + , ignorePins(false) + , plotBins(true) + {} + }; + +// Attributes +// ********** + public: Parameters _params; + private: DisplaySlot* _displaySlot; + private: InstanceOccurrencesVector _instanceOccurrencesVector; + private: InstanceOccurrencesMap _instanceOccurrencesMap; + private: UnitVector _instanceWidths; + private: UTable _instanceNets; + private: NetVector _nets; + private: UTable _netInstances; + private: UVector _netInitX; + private: UVector _netInitY; + private: BVector _hasInitX; + private: BVector _hasInitY; + private: Surface* _surface; + private: SimAnnealingPlacer* _simAnnealingPlacer; + private: BBPlacer* _bbPlacer; + + +// Constructor +// *********** + private: Mauka(Cell* cell); + public: static Mauka* Create(Cell* cell, double searchratio = 0.5, Box placementbox = Box()); + +// Accessors +// ********* + public: virtual const Name& GetName() const; + private: Surface* _GetSurface() const { return _surface; } + public: Unit GetInstanceIdWidth(unsigned id) const { return _instanceWidths[id]; } + public: unsigned GetRandomInstanceId() const; + +// Others +// ****** + private: void _PostCreate(Box& placementbox, double searchratio); + private: void _PreDelete(); + //public: void ReInit(); + public: bool Iterate(); + public: void Run(); + public: void Test(); + public: virtual string _GetTypeName() const {return _TName("Mauka");}; + public: virtual Record* _GetRecord() const; + public: void Save() const; + public: void PlotBinsStats() const; + public: void Plot() const; + private: Box PlotFixedPointsLabels(ofstream& out) const; + private: void Construct(); + public: void Hide(); + public: void Show(); + +}; + +void SetPlacementStatusRecursivelyToPlaced(Instance* instance); + +Mauka* GetMauka (const Cell* cell); +bool TestMaukaConstruction(Cell* cell, GCell* gcell); + +} + +#endif /* __MAUKA_H */ diff --git a/mauka/src/mauka/MaukaBox.h b/mauka/src/mauka/MaukaBox.h new file mode 100644 index 00000000..f57e1ecf --- /dev/null +++ b/mauka/src/mauka/MaukaBox.h @@ -0,0 +1,50 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __MAUKABOX_H +#define __MAUKABOX_H + +#include "hurricane/Box.h" + +namespace Mauka { + +using Hurricane::Box; +using Hurricane::Point; + +Box& Update(Box& box, const Point& src, const Point& dst); + +} + +#endif /* __MAUKABOX_H */ diff --git a/mauka/src/mauka/MaukaBox.h.noRefactor b/mauka/src/mauka/MaukaBox.h.noRefactor new file mode 100644 index 00000000..6896d050 --- /dev/null +++ b/mauka/src/mauka/MaukaBox.h.noRefactor @@ -0,0 +1,48 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __MAUKABOX_H +#define __MAUKABOX_H + +#include "Box.h" +USING_NAMESPACE_HURRICANE + +namespace MAUKA { + +Box& Update(Box& box, const Point& src, const Point& dst); + +} + +#endif /* __MAUKABOX_H */ diff --git a/mauka/src/mauka/MaukaEngine.h b/mauka/src/mauka/MaukaEngine.h new file mode 100644 index 00000000..40a4003c --- /dev/null +++ b/mauka/src/mauka/MaukaEngine.h @@ -0,0 +1,158 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag + +#ifndef __MAUKA_H +#define __MAUKA_H + +#include "hurricane/Instance.h" +#include "crlcore/ToolEngine.h" +#include "nimbus/GCell.h" + +#include "mauka/Configuration.h" + + +namespace Mauka { + +using Hurricane::Record; +using Hurricane::Name; +using Hurricane::DbU; +using Hurricane::Box; +using Hurricane::Net; +using Hurricane::Cell; +using Hurricane::Instance; +using Hurricane::Occurrence; +using CRL::ToolEngine; +using Nimbus::GCell; + +class Surface; +class SimAnnealingPlacer; +class BBPlacer; + +class MaukaEngine: public ToolEngine +// ********************************* +{ + //Mauka: a cool, light, Hawaiian wind descending from the montains. + friend class Surface; + friend class SimAnnealingPlacer; + friend class Move; + friend class Bin; + friend class SubRow; + friend class BBPlacer; +// Types +// ***** + public: typedef ToolEngine Inherit; + public: typedef std::vector InstanceOccurrencesVector; + public: typedef std::map InstanceOccurrencesMap; + public: typedef std::vector UVector; + public: typedef std::list UList; + public: typedef std::vector UTable; + public: typedef std::vector BVector; + public: typedef std::vector UnitVector; + public: typedef std::vector NetVector; + public: typedef std::vector BoxVector; + public: typedef std::vector BBoxes; + public: typedef std::vector< std::vector > Costs; + public: typedef std::vector PrePlaceRow; + public: typedef std::vector PrePlaceTab; + +// Attributes +// ********** + private: static Name _toolName; + private: Configuration* _configuration; + private: InstanceOccurrencesVector _instanceOccurrencesVector; + private: InstanceOccurrencesMap _instanceOccurrencesMap; + private: UnitVector _instanceWidths; + private: UTable _instanceNets; + private: NetVector _nets; + private: UTable _netInstances; + private: UVector _netInitX; + private: UVector _netInitY; + private: BVector _hasInitX; + private: BVector _hasInitY; + private: Surface* _surface; + private: SimAnnealingPlacer* _simAnnealingPlacer; + private: BBPlacer* _bbPlacer; + + +// Constructor +// *********** + private: MaukaEngine(Cell* cell); + public: static MaukaEngine* create(Cell* cell, Box placementbox = Box()); + +// Accessors +// ********* + public: + static MaukaEngine* get (Cell*); + static const Name& staticGetName (); + virtual const Name& getName () const; + inline Configuration* getConfiguration () const { return _configuration; } + inline bool useStandardSimulatedAnnealing () const { return _configuration->useStandardSimulatedAnnealing(); } + inline bool doIgnorePins () const { return _configuration->doIgnorePins(); } + inline bool doPlotBins () const { return _configuration->doPlotBins(); } + inline double getSearchRatio () const { return _configuration->getSearchRatio(); } + inline double getAnnealingNetMult () const { return _configuration->getAnnealingNetMult(); } + inline double getAnnealingBinMult () const { return _configuration->getAnnealingBinMult(); } + inline double getAnnealingRowMult () const { return _configuration->getAnnealingRowMult(); } + DbU::Unit getInstanceIdWidth (unsigned id) const { return _instanceWidths[id]; } + unsigned getRandomInstanceId () const; + private: + inline Surface* _getSurface () const { return _surface; } + +// Others +// ****** + private: void _postCreate(Box& placementbox); + private: void _preDestroy(); + public: static MaukaEngine* get ( const Cell* ); + //public: void ReInit(); + public: bool Iterate(); + public: void Run(); + public: void Test(); + public: virtual std::string _getTypeName() const {return "MaukaEngine";}; + public: virtual Record* _getRecord() const; + public: void Save() const; + public: void PlotBinsStats() const; + public: void Plot() const; + private: Box PlotFixedPointsLabels(std::ofstream& out) const; + private: void Construct(); + +}; + +void setPlacementStatusRecursivelyToPlaced(Instance* instance); +bool TestMaukaConstruction(Cell* cell, GCell* gcell); + +} // Enf of Mauka namespace. + +#endif /* __MAUKA_H */ diff --git a/mauka/src/mauka/MaukaEngine.h.noRefactor b/mauka/src/mauka/MaukaEngine.h.noRefactor new file mode 100644 index 00000000..8cfd3900 --- /dev/null +++ b/mauka/src/mauka/MaukaEngine.h.noRefactor @@ -0,0 +1,152 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag + +#ifndef __MAUKA_H +#define __MAUKA_H + +#include "Instance.h" +USING_NAMESPACE_HURRICANE + +#include "ToolEngine.h" +using namespace CRL; + +#include "GCell.h" +using namespace NIMBUS; + +namespace MAUKA { + +class Surface; +class SimAnnealingPlacer; +class BBPlacer; + +class Mauka: public ToolEngine +// ************************ +{ + //Mauka: a cool, light, Hawaiian wind descending from the montains. + friend class Surface; + friend class SimAnnealingPlacer; + friend class Move; + friend class Bin; + friend class SubRow; + friend class BBPlacer; +// Types +// ***** + public: typedef ToolEngine Inherit; + public: typedef vector InstanceOccurrencesVector; + public: typedef map InstanceOccurrencesMap; + public: typedef vector UVector; + public: typedef list UList; + public: typedef vector UTable; + public: typedef vector BVector; + public: typedef vector DbU::UnitVector; + public: typedef vector NetVector; + public: typedef vector BoxVector; + public: typedef vector BBoxes; + public: typedef vector > Costs; + public: typedef vector PrePlaceRow; + public: typedef vector PrePlaceTab; + public: + class Parameters + { + public: bool standardSimulatedAnnealing; + public: bool ignorePins; + public: bool plotBins; //plot bins utilisation + public: Parameters() + : standardSimulatedAnnealing(false) + , ignorePins(false) + , plotBins(true) + {} + }; + +// Attributes +// ********** + public: Parameters _params; + private: DisplaySlot* _displaySlot; + private: InstanceOccurrencesVector _instanceOccurrencesVector; + private: InstanceOccurrencesMap _instanceOccurrencesMap; + private: DbU::UnitVector _instanceWidths; + private: UTable _instanceNets; + private: NetVector _nets; + private: UTable _netInstances; + private: UVector _netInitX; + private: UVector _netInitY; + private: BVector _hasInitX; + private: BVector _hasInitY; + private: Surface* _surface; + private: SimAnnealingPlacer* _simAnnealingPlacer; + private: BBPlacer* _bbPlacer; + + +// Constructor +// *********** + private: Mauka(Cell* cell); + public: static Mauka* create(Cell* cell, double searchratio = 0.5, Box placementbox = Box()); + +// Accessors +// ********* + public: virtual const Name& getName() const; + private: Surface* _getSurface() const { return _surface; } + public: DbU::Unit getInstanceIdWidth(unsigned id) const { return _instanceWidths[id]; } + public: unsigned getRandomInstanceId() const; + +// Others +// ****** + private: void _postCreate(Box& placementbox, double searchratio); + private: void _preDestroy(); + //public: void ReInit(); + public: bool Iterate(); + public: void Run(); + public: void Test(); + public: virtual string _getTypeName() const {return _TName("Mauka");}; + public: virtual Record* _getRecord() const; + public: void Save() const; + public: void PlotBinsStats() const; + public: void Plot() const; + private: Box PlotFixedPointsLabels(ofstream& out) const; + private: void Construct(); + public: void hide(); + public: void show(); + +}; + +void setPlacementStatusRecursivelyToPlaced(Instance* instance); + +Mauka* getMauka (const Cell* cell); +bool TestMaukaConstruction(Cell* cell, GCell* gcell); + +} + +#endif /* __MAUKA_H */ diff --git a/mauka/src/mauka/Move.h b/mauka/src/mauka/Move.h new file mode 100644 index 00000000..a768815c --- /dev/null +++ b/mauka/src/mauka/Move.h @@ -0,0 +1,104 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __MOVE_H +#define __MOVE_H +#include + +#include "hurricane/Instance.h" +#include "hurricane/Net.h" + +// **************************************************************************************************** +// Move declaration +// **************************************************************************************************** + +namespace Mauka { + +using Hurricane::DbU; + +class Bin; +class Row; +class SubRow; + +class Move { +// ********* + +// Types +// ***** + public: typedef std::map AffectedNets; + +// Attributes +// ********** + private: SimAnnealingPlacer* _simAnnealingPlacer; + private: MaukaEngine* _mauka; + private: Surface* _surface; + private: bool _exchange; + private: unsigned _srcIns; + private: Bin* _srcBin; + private: double _srcBinInitCost; + private: SubRow* _srcSubRow; + private: Row* _srcRow; + private: double _srcRowInitCost; + private: DbU::Unit _srcWidth; + private: Bin* _dstBin; + private: double _dstBinInitCost; + private: SubRow* _dstSubRow; + private: Row* _dstRow; + private: double _dstRowInitCost; + private: unsigned _dstIns; + private: DbU::Unit _dstWidth; + private: AffectedNets _affectedNets; + +// Constructors +// ************ + public: Move(SimAnnealingPlacer* simannealingplacer); + +// Accessors +// ********* + public: double getDeltaRowCost() const; + public: double getDeltaBinCost() const; + public: double getDeltaNetCost(); + +// Others +// ****** + public: bool Next(const double dist); + public: void accept(); + public: void Reject(); + public: void TryMove(); +}; + +} + +#endif /* __MOVE_H */ diff --git a/mauka/src/mauka/Move.h.noRefactor b/mauka/src/mauka/Move.h.noRefactor new file mode 100644 index 00000000..1eaeca25 --- /dev/null +++ b/mauka/src/mauka/Move.h.noRefactor @@ -0,0 +1,104 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __MOVE_H +#define __MOVE_H +#include +using namespace std; + +#include "Instance.h" +#include "Net.h" +USING_NAMESPACE_HURRICANE + +// **************************************************************************************************** +// Move declaration +// **************************************************************************************************** + +namespace MAUKA { + +class Bin; +class Row; +class SubRow; + +class Move { +// ********* + +// Types +// ***** + public: typedef map AffectedNets; + +// Attributes +// ********** + private: SimAnnealingPlacer* _simAnnealingPlacer; + private: Mauka* _mauka; + private: Surface* _surface; + private: bool _exchange; + private: unsigned _srcIns; + private: Bin* _srcBin; + private: double _srcBinInitCost; + private: SubRow* _srcSubRow; + private: Row* _srcRow; + private: double _srcRowInitCost; + private: Unit _srcWidth; + private: Bin* _dstBin; + private: double _dstBinInitCost; + private: SubRow* _dstSubRow; + private: Row* _dstRow; + private: double _dstRowInitCost; + private: unsigned _dstIns; + private: Unit _dstWidth; + private: AffectedNets _affectedNets; + +// Constructors +// ************ + public: Move(SimAnnealingPlacer* simannealingplacer); + +// Accessors +// ********* + public: double GetDeltaRowCost() const; + public: double GetDeltaBinCost() const; + public: double GetDeltaNetCost(); + +// Others +// ****** + public: bool Next(const double dist); + public: void Accept(); + public: void Reject(); + public: void TryMove(); +}; + +} + +#endif /* __MOVE_H */ diff --git a/mauka/src/mauka/Row.h b/mauka/src/mauka/Row.h new file mode 100644 index 00000000..b6100479 --- /dev/null +++ b/mauka/src/mauka/Row.h @@ -0,0 +1,109 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __ROW_H +#define __ROW_H + +#include "mauka/Container.h" +#include "mauka/SubRow.h" + +namespace Mauka { + +using Hurricane::DbU; +using Hurricane::Box; + +class Surface; + +// **************************************************************************************************** +// Row declaration +// **************************************************************************************************** + +class Row : public Container { +// ************************* + friend class Surface; + friend class SubRow; + friend class BBPlacer; + +// Types +// ***** + public: typedef Container Inherit; + public: typedef std::vector SubRowVector; + public: typedef std::map< DbU::Unit, unsigned, std::less > SubRowXMax; + public: typedef std::map< DbU::Unit, unsigned, std::greater > SubRowXMinInv; + +// Attributes +// ********** + private: Surface* _surface; + private: SubRowVector _subRowVector; + private: SubRowXMax _subRowXMax; + private: SubRowXMinInv _subRowXMinInv; + private: bool _orientation; + private: DbU::Unit _size; // sum of the subrows size + private: DbU::Unit _capa; + +// Constructors +// ************ + protected: Row(Cell* cell, Surface* surface, const Box& box, bool orientation); + public: static Row* create(Cell* cell, Surface* surface, const Box& box, bool orientation); + +// Accessors +// ********* + public: SubRow* getSubRowBetween(DbU::Unit x1, DbU::Unit x2); + public: double getCost() const; + public: bool getOrientation() const { return _orientation; } + public: DbU::Unit getSubRowsWidth() const; + public: DbU::Unit getSubRowsCapa() const; + public: double getBinCost() const; + public: DbU::Unit getBinsSize() const; + public: DbU::Unit getBinsCapa() const; + +// Updators +// ******** + private: void _computeCapacity(double margin); + private: void _AddSize(DbU::Unit value); + +// Others +// ****** + public: virtual Cell* getCell() const; + protected: virtual void _preDestroy(); + private: void _InsertSubRow(SubRow* subrow); + private: void _computeSubRows(); + public: virtual std::string _getTypeName() const {return "Row";}; + public: void DisplayBinHits() const; +}; + +} + +#endif // __ROW_H diff --git a/mauka/src/mauka/Row.h.noRefactor b/mauka/src/mauka/Row.h.noRefactor new file mode 100644 index 00000000..14f6dd9b --- /dev/null +++ b/mauka/src/mauka/Row.h.noRefactor @@ -0,0 +1,106 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __ROW_H +#define __ROW_H + +#include "Container.h" +#include "SubRow.h" + +namespace MAUKA { + +class Surface; + +// **************************************************************************************************** +// Row declaration +// **************************************************************************************************** + +class Row : public Container { +// ************************* + friend class Surface; + friend class SubRow; + friend class BBPlacer; + +// Types +// ***** + public: typedef Container Inherit; + public: typedef vector SubRowVector; + public: typedef map > SubRowXMax; + public: typedef map > SubRowXMinInv; + +// Attributes +// ********** + private: Surface* _surface; + private: SubRowVector _subRowVector; + private: SubRowXMax _subRowXMax; + private: SubRowXMinInv _subRowXMinInv; + private: bool _orientation; + private: Unit _size; // sum of the subrows size + private: Unit _capa; + +// Constructors +// ************ + protected: Row(Cell* cell, Surface* surface, const Box& box, bool orientation); + public: static Row* Create(Cell* cell, Surface* surface, const Box& box, bool orientation); + +// Accessors +// ********* + public: SubRow* GetSubRowBetween(Unit x1, Unit x2); + public: double GetCost() const; + public: bool GetOrientation() const { return _orientation; } + public: Unit GetSubRowsWidth() const; + public: Unit GetSubRowsCapa() const; + public: double GetBinCost() const; + public: Unit GetBinsSize() const; + public: Unit GetBinsCapa() const; + +// Updators +// ******** + private: void _ComputeCapacity(double margin); + private: void _AddSize(Unit value); + +// Others +// ****** + public: virtual Cell* GetCell() const; + protected: virtual void _PreDelete(); + private: void _InsertSubRow(SubRow* subrow); + private: void _ComputeSubRows(); + public: virtual string _GetTypeName() const {return _TName("Row");}; + public: void DisplayBinHits() const; +}; + +} + +#endif // __ROW_H diff --git a/mauka/src/mauka/SimAnnealingPlacer.h b/mauka/src/mauka/SimAnnealingPlacer.h new file mode 100644 index 00000000..41d41812 --- /dev/null +++ b/mauka/src/mauka/SimAnnealingPlacer.h @@ -0,0 +1,122 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __SIMANNEALINGPLACER_H +#define __SIMANNEALINGPLACER_H + +#include "hurricane/Instance.h" +#include "crlcore/Utilities.h" +#include "mauka/MaukaEngine.h" + +namespace Mauka { + +class MaukaEngine; +class Bin; + +class SimAnnealingPlacer { +// *********************** + friend class MaukaEngine; + friend class Move; + friend class Bin; + friend class SubRow; + +// Types +// ***** + public: typedef std::vector InstanceBins; + +// Attributes +// ********** + private: MaukaEngine* _mauka; + private: InstanceBins _instanceBins; + private: MaukaEngine::BBoxes _netBBoxes; + private: MaukaEngine::Costs _netCosts; + private: MaukaEngine::UVector _netFlags; + private: double _netCost; + private: double _binCost; + private: double _rowCost; + private: double _initNetCost; + private: double _initBinCost; + private: double _initRowCost; + private: double _netMult; + private: double _binMult; + private: double _rowMult; + private: double _temperature; + private: double _distance; + private: unsigned _loop; + private: unsigned _iterationsFactor; + private: unsigned _iterations; + private: unsigned _moves; + private: unsigned _sourceEqualTargetMovementNumber; + private: unsigned _surOccupationTargetMovementNumber; + private: unsigned _impossibleExchangeMovementNumber; + + +// Constructor +// *********** + public: SimAnnealingPlacer(MaukaEngine* mauka); + +// Accessors +// ********* + public: double getNetCost(); + public: double getCost() const; + public: double& _getNetIdCost(unsigned netid) { return _netCosts[netid][_netFlags[netid]]; } + public: double& _getNetIdTmpCost(unsigned netid) { return _netCosts[netid][!_netFlags[netid]]; } + public: Box& _getNetIdBBox(unsigned netid) { return _netBBoxes[netid][_netFlags[netid]]; } + public: Box& _getNetTmpBBox(unsigned netid) { return _netBBoxes[netid][!_netFlags[netid]]; } + public: MaukaEngine* getMauka() { return _mauka; } + public: unsigned getMoves() const { return _moves; } + public: unsigned getRandInstance(); + +// Others +// ****** + public: bool Iterate(); + private: bool accept(double deltacost) const; + public: double DebugNetCost(); + public: void DisplayResults() const; + public: void _setInstanceIdBin(unsigned instanceid, Bin* bin) { _instanceBins[instanceid] = bin; } + public: void _InvertNetIdFlag(unsigned netid) { _netFlags[netid] = !_netFlags[netid]; } + public: double computeCost(double rowcost, double bincost, double netcost) const; + public: void incrImpossibleExchangeMovementNumber() { ++_impossibleExchangeMovementNumber; } + public: void incrSourceEqualTargetMovementNumber() { ++_sourceEqualTargetMovementNumber; } + public: void incrSurOccupationTargetMovementNumber() { ++_surOccupationTargetMovementNumber; } + public: void init(); + public: void Save() const; + private: void Plot(std::ofstream& out) const; + +}; + +} + +#endif /* __SIMANNEALINGPLACER_H */ diff --git a/mauka/src/mauka/SimAnnealingPlacer.h.noRefactor b/mauka/src/mauka/SimAnnealingPlacer.h.noRefactor new file mode 100644 index 00000000..23bdc4bd --- /dev/null +++ b/mauka/src/mauka/SimAnnealingPlacer.h.noRefactor @@ -0,0 +1,126 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __SIMANNEALINGPLACER_H +#define __SIMANNEALINGPLACER_H + +#include "Instance.h" +USING_NAMESPACE_HURRICANE + +#include "CVerbosity.h" +using namespace CRL; + +#include "Mauka.h" + +namespace MAUKA { + +class Mauka; +class Bin; + +class SimAnnealingPlacer { +// *********************** + friend class Mauka; + friend class Move; + friend class Bin; + friend class SubRow; + +// Types +// ***** + public: typedef vector InstanceBins; + +// Attributes +// ********** + private: Mauka* _mauka; + private: InstanceBins _instanceBins; + private: Mauka::BBoxes _netBBoxes; + private: Mauka::Costs _netCosts; + private: Mauka::UVector _netFlags; + private: double _netCost; + private: double _binCost; + private: double _rowCost; + private: double _initNetCost; + private: double _initBinCost; + private: double _initRowCost; + private: double _netMult; + private: double _binMult; + private: double _rowMult; + private: double _temperature; + private: double _distance; + private: unsigned _loop; + private: unsigned _iterationsFactor; + private: unsigned _iterations; + private: unsigned _moves; + private: unsigned _sourceEqualTargetMovementNumber; + private: unsigned _surOccupationTargetMovementNumber; + private: unsigned _impossibleExchangeMovementNumber; + + +// Constructor +// *********** + public: SimAnnealingPlacer(Mauka* mauka, double netmult = 0.8, double binmult = 0.1, double rowmult = 0.1); + +// Accessors +// ********* + public: double GetNetCost(); + public: double GetCost() const; + public: double& _GetNetIdCost(unsigned netid) { return _netCosts[netid][_netFlags[netid]]; } + public: double& _GetNetIdTmpCost(unsigned netid) { return _netCosts[netid][!_netFlags[netid]]; } + public: Box& _GetNetIdBBox(unsigned netid) { return _netBBoxes[netid][_netFlags[netid]]; } + public: Box& _GetNetTmpBBox(unsigned netid) { return _netBBoxes[netid][!_netFlags[netid]]; } + public: Mauka* GetMauka() { return _mauka; } + public: unsigned GetMoves() const { return _moves; } + public: unsigned GetRandInstance(); + +// Others +// ****** + public: bool Iterate(); + private: bool Accept(double deltacost) const; + public: double DebugNetCost(); + public: void DisplayResults() const; + public: void _SetInstanceIdBin(unsigned instanceid, Bin* bin) { _instanceBins[instanceid] = bin; } + public: void _InvertNetIdFlag(unsigned netid) { _netFlags[netid] = !_netFlags[netid]; } + public: double ComputeCost(double rowcost, double bincost, double netcost) const; + public: void IncrImpossibleExchangeMovementNumber() { ++_impossibleExchangeMovementNumber; } + public: void IncrSourceEqualTargetMovementNumber() { ++_sourceEqualTargetMovementNumber; } + public: void IncrSurOccupationTargetMovementNumber() { ++_surOccupationTargetMovementNumber; } + public: void Init(); + public: void Save() const; + private: void Plot(ofstream& out) const; + +}; + +} + +#endif /* __SIMANNEALINGPLACER_H */ diff --git a/mauka/src/mauka/SubRow.h b/mauka/src/mauka/SubRow.h new file mode 100644 index 00000000..1966d668 --- /dev/null +++ b/mauka/src/mauka/SubRow.h @@ -0,0 +1,114 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __SUBROW_H +#define __SUBROW_H + +#include "mauka/Container.h" +#include "mauka/Bin.h" + +namespace Mauka { + +using Hurricane::DbU; +using Hurricane::Box; +using Hurricane::Cell; +using Hurricane::Instance; + +class Surface; +class Row; + +// **************************************************************************************************** +// SubRow declaration +// **************************************************************************************************** + +class SubRow : public Container { +// ************************* + friend class Surface; + friend class Bin; + friend class Row; + friend class BBPlacer; +// Types +// ***** + public: typedef Container Inherit; + public: typedef std::vector BinVector; + public: typedef std::map BinXMax; + public: typedef std::vector InstanceVector; // for bbplacer + +// Attributes +// ********** + private: Surface* _surface; + private: Row* _row; + private: BinVector _binVector; + private: BinXMax _binXMax; + private: DbU::Unit _size; // sum of the bins size + private: DbU::Unit _capa; // ideal occupation of the subrow + +// Constructors +// ************ + protected: SubRow(Cell* cell, Surface* surface, const Box& box); + public: static SubRow* create(Cell* cell, Surface* surface, const Box& box, bool orientation); + +// Accessors +// ********* + public: virtual Cell* getCell() const; + public: Row* getRow() { return _row; } + public: Surface* getSurface() { return _surface; } + public: DbU::Unit getCapa() const { return _capa; } + public: DbU::Unit getSize() const { return _size; } + public: DbU::Unit getCapaVsSize() const { return (_capa - _size);} + public: DbU::Unit getWidthVsSize() const { return (getWidth() - _size);} + public: Bin* getBinBetween(DbU::Unit lowerX, DbU::Unit upperX, const Bin* srcbin); + +// Updators +// ******** + private: void _AddSize(DbU::Unit value); + +// Others +// ****** + private: void _computeCapacity(double margin); + private: bool _MergeBins(); + public: void DisplayBinHits() const; + protected: virtual void _postCreate(bool orientation); + protected: virtual void _preDestroy(); + public: double getBinCost() const; + public: DbU::Unit getBinsSize() const; + public: DbU::Unit getBinsCapa() const; + public: double getCost() const; + public: virtual std::string _getTypeName() const {return "SubRow";}; +}; + +} + +#endif // __SUBROW_H diff --git a/mauka/src/mauka/SubRow.h.noRefactor b/mauka/src/mauka/SubRow.h.noRefactor new file mode 100644 index 00000000..7efa1436 --- /dev/null +++ b/mauka/src/mauka/SubRow.h.noRefactor @@ -0,0 +1,109 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 19/07/2006 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __SUBROW_H +#define __SUBROW_H + +#include "Container.h" +#include "Bin.h" + +namespace MAUKA { + +class Surface; +class Row; + +// **************************************************************************************************** +// SubRow declaration +// **************************************************************************************************** + +class SubRow : public Container { +// ************************* + friend class Surface; + friend class Bin; + friend class Row; + friend class BBPlacer; +// Types +// ***** + public: typedef Container Inherit; + public: typedef vector BinVector; + public: typedef map BinXMax; + public: typedef vector InstanceVector; // for bbplacer + +// Attributes +// ********** + private: Surface* _surface; + private: Row* _row; + private: BinVector _binVector; + private: BinXMax _binXMax; + private: Unit _size; // sum of the bins size + private: Unit _capa; // ideal occupation of the subrow + +// Constructors +// ************ + protected: SubRow(const Cell* cell, Surface* surface, const Box& box); + public: static SubRow* Create(const Cell* cell, Surface* surface, const Box& box, bool orientation); + +// Accessors +// ********* + public: virtual Cell* GetCell() const; + public: Row* GetRow() { return _row; } + public: Surface* GetSurface() { return _surface; } + public: Unit GetCapa() const { return _capa; } + public: Unit GetSize() const { return _size; } + public: Unit GetCapaVsSize() const { return (_capa - _size);} + public: Unit GetWidthVsSize() const { return (GetWidth() - _size);} + public: Bin* GetBinBetween(Unit lowerX, Unit upperX, const Bin* srcbin); + +// Updators +// ******** + private: void _AddSize(Unit value); + +// Others +// ****** + private: void _ComputeCapacity(double margin); + private: bool _MergeBins(); + public: void DisplayBinHits() const; + protected: virtual void _PostCreate(bool orientation); + protected: virtual void _PreDelete(); + public: double GetBinCost() const; + public: Unit GetBinsSize() const; + public: Unit GetBinsCapa() const; + public: double GetCost() const; + public: virtual string _GetTypeName() const {return _TName("SubRow");}; +}; + +} + +#endif // __SUBROW_H diff --git a/mauka/src/mauka/Surface.h b/mauka/src/mauka/Surface.h new file mode 100644 index 00000000..c8d8783b --- /dev/null +++ b/mauka/src/mauka/Surface.h @@ -0,0 +1,121 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __SURFACE_H +#define __SURFACE_H + +#include "mauka/Container.h" +#include "mauka/MaukaEngine.h" + +namespace Mauka { + +using Hurricane::DbU; +using Hurricane::Box; +using Hurricane::Cell; + +class Bin; +class Row; +class SubRow; +class MaukaEngine; + +class Surface: public Container { +// **************************** + friend class MaukaEngine; + friend class SimAnnealingPlacer; + friend class Row; + friend class SubRow; + friend class BBPlacer; + +// Types +// ***** + public: typedef Container Inherit; + public: typedef std::vector RowVector; + public: typedef std::list SubRowList; + public: typedef std::map > RowYMax; + public: typedef std::map > RowYMinInv; + //public: typedef map RowMap; + +// Attributes +// ********** + private: MaukaEngine* _mauka; + //private: RowMap _rowMap; + private: RowVector _rowVector; + private: RowYMax _rowYMax; + private: RowYMinInv _rowYMinInv; + private: bool _rowZeroOrientation; + private: double _margin; + private: DbU::Unit _binWidthMax; + private: DbU::Unit _binWidthMin; + private: DbU::Unit _searchWidth; + private: DbU::Unit _searchHeight; + +// Constructors +// ************ + protected: Surface(MaukaEngine* mauka, const Box& placementbox); + public: static Surface* create(MaukaEngine* mauka, const Box& placementbox); + +// Accessors +// ********* + public: virtual Cell* getCell() const { return _mauka->getCell(); } + public: Bin* getBinInSurface(Bin* srcbin, double dist); + public: double getBinCost() const; + public: double getRowCost() const; + public: DbU::Unit getBinsSize() const; + public: DbU::Unit getBinsCapa() const; + public: DbU::Unit getSubRowsCapa() const; + public: double getMargin() const { return _margin; }; + public: MaukaEngine* getMauka() { return _mauka; }; + +// Others +// ****** + public: void DisplayBinHits() const; + protected: virtual void _preDestroy(); + private: void InsertRow(Row* row); + private: void removeRow(Row* row); + private: Row* InsertSubRow(SubRow* subrow, bool orientation); + private: void removeSubRow(SubRow* subrow); + private: void PlotBinsStats(std::ofstream& out) const; + private: void Plot(std::ofstream& out) const; + public: virtual std::string _getTypeName() const {return "Surface";}; + public: virtual Record* _getRecord() const; + private: Row* InsertSubRowInRow(SubRow* subrow, bool orientation); + private: void _computeRowsAndSubRows(); + private: void _DisplayInstances(MaukaEngine::UVector& instanceids, SubRowList& subrowlist); + private: void _computeCapacity(); + private: void _postCreate(); +}; + +} +#endif /* __SURFACE_H */ diff --git a/mauka/src/mauka/Surface.h.noRefactor b/mauka/src/mauka/Surface.h.noRefactor new file mode 100644 index 00000000..de3627ea --- /dev/null +++ b/mauka/src/mauka/Surface.h.noRefactor @@ -0,0 +1,118 @@ + +// This file is part of the Coriolis Project. +// Copyright (C) Laboratoire LIP6 - Departement ASIM +// Universite Pierre et Marie Curie +// +// Main contributors : +// Christophe Alexandre +// Sophie Belloeil +// Hugo Clément +// Jean-Paul Chaput +// Damien Dupuis +// Christian Masson +// Marek Sroka +// +// The Coriolis Project is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// The Coriolis Project is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the Coriolis Project; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// License-Tag +// +// Date : 29/01/2004 +// Author : Christophe Alexandre +// +// Authors-Tag +#ifndef __SURFACE_H +#define __SURFACE_H + +#include "Container.h" +#include "Mauka.h" + +namespace MAUKA{ + +class Bin; +class Row; +class SubRow; +class Mauka; + +class Surface: public Container { +// **************************** + friend class Mauka; + friend class SimAnnealingPlacer; + friend class Row; + friend class SubRow; + friend class BBPlacer; + +// Types +// ***** + public: typedef Container Inherit; + public: typedef vector RowVector; + public: typedef list SubRowList; + public: typedef map > RowYMax; + public: typedef map > RowYMinInv; + //public: typedef map RowMap; + +// Attributes +// ********** + private: Mauka* _mauka; + //private: RowMap _rowMap; + private: RowVector _rowVector; + private: RowYMax _rowYMax; + private: RowYMinInv _rowYMinInv; + private: bool _rowZeroOrientation; + private: double _margin; + private: Unit _binWidthMax; + private: Unit _binWidthMin; + private: double _searchRatio; + private: Unit _searchWidth; + private: Unit _searchHeight; + +// Constructors +// ************ + protected: Surface(Mauka* mauka, const Box& placementbox, double searchratio); + public: static Surface* Create(Mauka* mauka, const Box& placementbox, double searchratio); + +// Accessors +// ********* + public: virtual Cell* GetCell() const { return _mauka->GetCell(); } + public: Bin* GetBinInSurface(Bin* srcbin, double dist); + public: double GetBinCost() const; + public: double GetRowCost() const; + public: Unit GetBinsSize() const; + public: Unit GetBinsCapa() const; + public: Unit GetSubRowsCapa() const; + public: double GetMargin() const { return _margin; }; + public: Mauka* GetMauka() { return _mauka; }; + +// Others +// ****** + public: void DisplayBinHits() const; + protected: virtual void _PreDelete(); + private: void InsertRow(Row* row); + private: void RemoveRow(Row* row); + private: Row* InsertSubRow(SubRow* subrow, bool orientation); + private: void RemoveSubRow(SubRow* subrow); + private: void PlotBinsStats(ofstream& out) const; + private: void Plot(ofstream& out) const; + public: virtual string _GetTypeName() const {return _TName("Surface");}; + public: virtual Record* _GetRecord() const; + private: Row* InsertSubRowInRow(SubRow* subrow, bool orientation); + private: void _ComputeRowsAndSubRows(); + private: void _DisplayInstances(Mauka::UVector& instanceids, SubRowList& subrowlist); + private: void _ComputeCapacity(); + private: void _PostCreate(); +}; + +} +#endif /* __SURFACE_H */