coriolis/mauka/src/Mauka.cpp.noRefactor

679 lines
22 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 "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<Occurrence, unsigned> InstanceOccurrenceMap;
typedef set<Instance*> InstanceSet;
typedef map<Net*, unsigned> NetMap;
InstanceSet instanceSet;
NetMap netMap;
unsigned instanceId = 0;
unsigned netId = 0;
Unit standardCellHeight = 0;
for_each_occurrence(occurrence, GetCell()->GetLeafInstanceOccurrences())
{
Instance* instance = static_cast<Instance*>(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<Net*> NetSet;
NetSet treatedNets;
for (InstanceOccurrencesVector::const_iterator iovit = _instanceOccurrencesVector.begin();
iovit != _instanceOccurrencesVector.end();
iovit++)
{
Instance* instance = static_cast<Instance*>(iovit->GetEntity());
for_each_plug(plug, instance->GetConnectedPlugs())
{
Net* net = plug->GetNet();
if (net->IsGlobal())
continue;
typedef list<Occurrence> InstanceOccurrenceList;
InstanceOccurrenceList instanceOccurrenceList;
Occurrence rootNetOccurrence = GetHyperNetRootNetOccurrence(Occurrence(net, iovit->GetPath()));
Net* rootNet = static_cast<Net*>(rootNetOccurrence.GetEntity());
NetSet::iterator snit = treatedNets.find(rootNet);
if (snit != treatedNets.end())
continue;
treatedNets.insert(rootNet);
HyperNet hyperNet(rootNetOccurrence);
typedef list<Point> 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<Mauka*>(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<TestSubRow*> TestSubRowsList;
typedef vector<Occurrence> InstanceOccurrencesVector;
typedef list<Occurrence> 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<Instance*>(occurrence1.GetEntity());
Instance* instance2 = static_cast<Instance*>(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<Instance*>(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<Instance*>(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<Instance*>(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;
}
}