543 lines
18 KiB
C++
543 lines
18 KiB
C++
|
|
// This file is part of the Coriolis Project.
|
|
// Copyright (C) Laboratoire LIP6 - Departement ASIM
|
|
// Universite Pierre et Marie Curie
|
|
//
|
|
// Main contributors :
|
|
// Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
|
// Sophie Belloeil <Sophie.Belloeil@lip6.fr>
|
|
// Hugo Clément <Hugo.Clement@lip6.fr>
|
|
// Jean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
|
|
// Damien Dupuis <Damien.Dupuis@lip6.fr>
|
|
// Christian Masson <Christian.Masson@lip6.fr>
|
|
// Marek Sroka <Marek.Sroka@lip6.fr>
|
|
//
|
|
// The Coriolis Project is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License as
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// The Coriolis Project is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with the Coriolis Project; if not, write to the Free Software
|
|
// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
//
|
|
// License-Tag
|
|
//
|
|
// Date : 29/01/2004
|
|
// Author : Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
|
//
|
|
// Authors-Tag
|
|
#include <cmath>
|
|
#include <cstdlib>
|
|
#include <climits>
|
|
|
|
#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 <<endl;
|
|
cerr << " SrcPos = " << _srcBin->getCenter() << endl;
|
|
cerr << " DstPos = " << _dstBin->getCenter() << endl;
|
|
cerr << "netTmpCost(netSrc) " << netTmpCost << endl << endl;
|
|
#endif
|
|
delta += netTmpCost - netCost;
|
|
|
|
#if 0 // code pour debug ....
|
|
Box checkBox;
|
|
for (MaukaEngine::UVector::const_iterator uvit = _mauka->_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<CEditor*>(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<CEditor*>(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<CEditor*>(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);
|
|
}
|
|
}
|
|
|
|
}
|