// 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); } } }