coriolis/mauka/src/SimAnnealingPlacer.cpp.noRe...

683 lines
24 KiB
Plaintext

// 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 <math.h>
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<Box> bboxes(2);
_netBBoxes.push_back(bboxes);
vector<double> 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<SplitterContact*>(component))
{
if (VFence* vfence = dynamic_cast<VFence*>(splitterContact->GetSplitter()->GetFence()))
{
if (_hasInitX[netid])
_hasInitX[netid] = false;
else
{
_hasInitX[netid] = true;
_netInitX[netid] = vfence->GetX();
}
}
else if (HFence* hfence = dynamic_cast<HFence*>(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<Pin*>(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<Instance*>(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<SplitterContact*>(hook->GetComponent()))
{
if (VFence* vfence = dynamic_cast<VFence*>(splitterContact->GetSplitter()->GetFence()))
{
if (hasInitX)
hasInitX = false;
else
{
hasInitX = true;
netInitX = vfence->GetX();
}
}
else if (HFence* hfence = dynamic_cast<HFence*>(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<Instance*>(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<Instance*>(_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;
}
}