896 lines
32 KiB
Plaintext
896 lines
32 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 "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<Instance*>(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<Occurrence> 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<Occurrence> 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<PlacementProblem*> PlacementProblemList;
|
|
|
|
}
|
|
|
|
void Surface::_PostCreate() {
|
|
typedef set<Occurrence> 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<Instance*>(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<Instance*>(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<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
|
|
|
|
#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;
|
|
}
|
|
|
|
}
|