coriolis/mauka/src/Surface.cpp

858 lines
32 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 "hurricane/Warning.h"
#include "hurricane/Cell.h"
#include "nimbus/NimbusEngine.h"
#include "mauka/MaukaEngine.h"
#include "mauka/SimAnnealingPlacer.h"
#include "mauka/SubRow.h"
#include "mauka/Row.h"
#include "mauka/Surface.h"
namespace {
using namespace std;
using namespace Hurricane;
using namespace Mauka;
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;
}
}
} // End of anonymous namespace.
namespace Mauka {
using Nimbus::NimbusEngine;
using Nimbus::GCellLocator;
Surface::Surface(MaukaEngine* mauka, const Box& placementbox) :
Inherit(mauka->getCell(), placementbox),
_mauka(mauka),
_rowVector(),
_rowYMax(),
_rowYMinInv(),
_rowZeroOrientation(false),
_margin(0.0),
_binWidthMax(0),
_binWidthMin(0),
_searchWidth(0),
_searchHeight(0)
{}
Surface* Surface::create(MaukaEngine* mauka, const Box& placementbox) {
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);
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: MaukaEngine::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();
bool partitionned = false;
NimbusEngine* nimbus = NULL;
if (_box.isEmpty()) {
nimbus = NimbusEngine::get ( getCell() );
if (nimbus == NULL) {
throw Error("Can't create Mauka::Surface, no Box and no Nimbus");
}
_box = nimbus->getGrid()->getRoot()->getBox();
partitionned = (nimbus->getDepth() > 1);
if ( partitionned )
cmess2 << " - Design is partionned (depth:" << nimbus->getDepth() << ")" << endl;
}
PlacementVerification ( getCell(), _box );
DbU::Unit sliceHeight = _mauka->getSliceHeight();
DbU::Unit pitch = _mauka->getPitch();
if ( _box.isEmpty() or _box.isPonctual() or _box.isFlat())
throw Error("Wrong Box for Area: %s",getString(_box).c_str());
if ( getHeight() % sliceHeight )
throw Error("Box Height %s must be a multiple of Slice Height %s"
,DbU::getValueString(getHeight()).c_str()
,DbU::getValueString(sliceHeight).c_str());
DbU::Unit instanceToPlaceWidthMax = 0;
double instanceToPlaceWidthSum = 0.0;
for ( unsigned int id = 0; id < _mauka->_instanceWidths.size(); ++id ) {
DbU::Unit instanceWidth = _mauka->_instanceWidths[id];
instanceToPlaceWidthSum += (double)instanceWidth;
if ( instanceWidth % pitch )
throw Error("Width of %s (%s) is not a multiple of pitch (%s)."
,getString(_mauka->_instanceOccurrencesVector[id]).c_str()
,DbU::getValueString(instanceWidth).c_str()
,DbU::getValueString(pitch).c_str());
if (instanceWidth > instanceToPlaceWidthMax)
instanceToPlaceWidthMax = instanceWidth;
}
// _binWidthMax = DbU::lambda
// ((unsigned)( 3.0 * DbU::getLambda(instanceToPlaceWidthMax) / DbU::getLambda(pitch))
// * DbU::getLambda(pitch));
// _binWidthMin = DbU::lambda
// ((unsigned)(DbU::getLambda(_binWidthMax) / (DbU::getLambda(pitch) * 2)) * DbU::getLambda(pitch));
_binWidthMax = 2 * (instanceToPlaceWidthMax / pitch) * pitch;
_binWidthMin = (_binWidthMax / (pitch * 2)) * pitch;
// cerr << "_binWidthMax:" << DbU::getValueString(_binWidthMax) << endl;
// cerr << "_binWidthMin:" << DbU::getValueString(_binWidthMin) << endl;
double surfaceTotalWidth = 0.0;
PlacementProblemList placementProblemList;
OccurrenceSet verifyInstanceOccurrencesSet;
if ( nimbus ) {
forEach ( GCell*, igcell, nimbus->getPlacementLeaves() ) {
PlacementProblem* placementProblem = new PlacementProblem(*igcell);
placementProblemList.push_back(placementProblem);
InstanceOccurrencesList toPlaceInstanceOccurrencesList;
// Search for preplaced leaf instances
forEach ( Occurrence
, ioccurrence, _mauka->getCell()->getLeafInstanceOccurrencesUnder(igcell->getBox()) ) {
Instance* instance = static_cast<Instance*>((*ioccurrence).getEntity());
if ( instance->isFixed() ) {
placementProblem->_fixedInstanceOccurrenceList.push_back(*ioccurrence);
} else {
MaukaEngine::InstanceOccurrencesMap::const_iterator
iomit = _mauka->_instanceOccurrencesMap.find(*ioccurrence);
if ( iomit == _mauka->_instanceOccurrencesMap.end() )
throw Error("Instance occurrence unexpectedly appeared:\n"
" %s",getString(*ioccurrence).c_str());
placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(iomit->second);
verifyInstanceOccurrencesSet.insert(*ioccurrence);
}
}
// Special case: no Nimbus run, Instances are *not* in the quadtree yet.
if ( not partitionned ) {
forEach(Occurrence, ioccurrence, _mauka->getCell()->getLeafInstanceOccurrences() ) {
Instance* instance = static_cast<Instance*>((*ioccurrence).getEntity());
if ( instance->isFixed() ) continue;
MaukaEngine::InstanceOccurrencesMap::const_iterator iomit
= _mauka->_instanceOccurrencesMap.find(*ioccurrence);
if (iomit == _mauka->_instanceOccurrencesMap.end())
throw Error("Instance occurrence unexpectedly appeared:\n"
" %s",getString(*ioccurrence).c_str());
placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(iomit->second);
verifyInstanceOccurrencesSet.insert(*ioccurrence);
}
}
DbU::Unit searchWidth = DbU::lambda(_mauka->getSearchRatio() * DbU::getLambda(igcell->getWidth()));
if (_searchWidth < searchWidth) _searchWidth = searchWidth;
DbU::Unit searchHeight = DbU::lambda(_mauka->getSearchRatio() * DbU::getLambda(igcell->getHeight()));
if (_searchHeight < searchHeight) _searchHeight = searchHeight;
}
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
MaukaEngine::PrePlaceTab prePlaceTab(height, MaukaEngine::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();
if ( refInsYPos % 2 == 0 ) {
if ( (refInsSliceHeight % 2 == 0)
or (orientation == Transformation::Orientation::ID)
or (orientation == Transformation::Orientation::MX))
rowZeroOrientation = false;
else
rowZeroOrientation = true;
} else {
if ( (refInsSliceHeight % 2 == 0)
or (orientation == Transformation::Orientation::ID)
or (orientation == Transformation::Orientation::MX))
rowZeroOrientation = true;
else
rowZeroOrientation = false;
}
// 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);
DbU::Unit insWidth = preplacedBox.getWidth();
DbU::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) or (yit > height - 1) or (xit < 0) or (yit < 0) )
throw Error("%s is out of the abutment box"
,getString(*iolit).c_str());
if ( prePlaceTab[yit][xit] == false )
prePlaceTab[yit][xit] = true;
else
throw Error("%s is badly placed. There is another instance at it's position"
,getString(*iolit).c_str());
}
}
}
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()) and (prePlaceTab[y][x] == true) ) ++x;
DbU::Unit subRowXMin = gcell->getXMin() + x * pitch;
if (x >= (int)prePlaceTab[y].size()) break;
while ( (x < (int)prePlaceTab[y].size()) and (prePlaceTab[y][x] == false) ) ++x;
DbU::Unit subRowXMax = gcell->getXMin() + x * pitch;
if ( subRowXMax - subRowXMin > _binWidthMin ) {
SubRow* subRow = SubRow::create ( getCell()
, this
, Box(subRowXMin, gcell->getYMin() + y * sliceHeight
,subRowXMax, gcell->getYMin() + (y+1) * sliceHeight)
, rowOrientation );
placementProblem->_subRowList.push_back(subRow);
}
}
rowOrientation = not rowOrientation;
}
} else {
bool rowOrientation = false;
for ( DbU::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 = not rowOrientation;
}
}
}
} else {
PlacementProblem* placementProblem = new PlacementProblem(NULL);
_searchHeight = getHeight();
_searchWidth = getWidth();
bool rowOrientation = false;
unsigned int nRows = getHeight() / sliceHeight;
surfaceTotalWidth = ((double)getWidth()) * nRows;
for ( DbU::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 = not rowOrientation;
}
for ( unsigned int id=0; id < _mauka->_instanceOccurrencesVector.size(); ++id ) {
placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(id);
}
throw Error("MaukaEngine needs NimbusEngine");
}
_computeCapacity();
linefill output (" ",cmess2);
for (PlacementProblemList::iterator pplit = placementProblemList.begin();
pplit != placementProblemList.end(); pplit++) {
//cmess2 << " - Initial placement of " << (*pplit)->_gcell->getBox() << endl;
output << (*pplit)->_gcell->getBox();
_DisplayInstances((*pplit)->_toPlaceInstanceOccurrencesUVector, (*pplit)->_subRowList);
delete *pplit;
}
output << endl;
placementProblemList.clear ();
if ( verifyInstanceOccurrencesSet.size() != _mauka->_instanceOccurrencesVector.size() ) {
cerr << Error("There are %d Instances not taken into account"
,(_mauka->_instanceOccurrencesVector.size() - verifyInstanceOccurrencesSet.size())) << endl;
VerifyInstanceQuadtreeInsertion(_mauka->getCell());
for ( MaukaEngine::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 );
DisplayNonLeafInstances ( _mauka->getCell(), iovit->getBoundingBox() );
return;
}
}
throw Error("There are %d Instances not taken into account"
,(_mauka->_instanceOccurrencesVector.size() - verifyInstanceOccurrencesSet.size()));
}
for ( RowVector::const_iterator rvit = _rowVector.begin(); rvit != _rowVector.end(); rvit++ ) {
surfaceTotalWidth += (double)((*rvit)->getSubRowsWidth());
}
_computeRowsAndSubRows();
_margin = 1.0 - instanceToPlaceWidthSum / surfaceTotalWidth;
if ( _margin < 0.0 ) {
throw Error("There is not enough free space to place the circuit %s < %s"
,DbU::getValueString(surfaceTotalWidth).c_str()
,DbU::getValueString(instanceToPlaceWidthSum).c_str()
);
}
if (_margin < 0.15)
cerr << Warning("Low margin %d, may not be able to complete successfully",_margin) << endl;
_computeCapacity();
}
void Surface::_preDestroy()
{
Inherit::_preDestroy();
for (RowVector::const_iterator rvit = _rowVector.begin();
rvit != _rowVector.end();
rvit++)
(*rvit)->destroy();
_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)
{
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);
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();
DbU::Unit lowerY = srcPos.getY() - DbU::lambda((dist * DbU::getLambda(_searchHeight)));
if (lowerY < getYMin())
lowerY = getYMin();
DbU::Unit upperY = srcPos.getY() + DbU::lambda((dist * DbU::getLambda(_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];
DbU::Unit lowerX = srcPos.getX() - DbU::lambda((dist * DbU::getLambda(_searchWidth)));
if ((lowerX < searchRow->getXMin()) || (lowerX > searchRow->getXMax()))
lowerX = searchRow->getXMin();
DbU::Unit upperX = srcPos.getX() + DbU::lambda((dist * DbU::getLambda(_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;
}
double Surface::getBinsSize() const
{
double totalBinsSize = 0.0;
for (RowVector::const_iterator rvit = _rowVector.begin();
rvit != _rowVector.end();
rvit++)
totalBinsSize += (double)(*rvit)->getBinsSize();
return totalBinsSize;
}
double Surface::getBinsCapa() const
{
double totalBinsCapa = 0.0;
for (RowVector::const_iterator rvit = _rowVector.begin();
rvit != _rowVector.end();
rvit++)
totalBinsCapa += (double)(*rvit)->getBinsCapa();
return totalBinsCapa;
}
double Surface::getSubRowsCapa() const
{
double totalSubRowsCapa = 0.0;
for (RowVector::const_iterator rvit = _rowVector.begin();
rvit != _rowVector.end();
rvit++)
{
totalSubRowsCapa += (double)(*rvit)->getSubRowsCapa();
}
return totalSubRowsCapa;
}
namespace {
class sortInstanceOccurrencesIdsByWidth
{
private: MaukaEngine* _mauka;
public: sortInstanceOccurrencesIdsByWidth(MaukaEngine* mauka): _mauka(mauka) {}
public:
bool operator()(unsigned instanceoccurrenceid1, unsigned instanceoccurrenceid2) const
{
DbU::Unit width1 = _mauka->getInstanceIdWidth(instanceoccurrenceid1);
DbU::Unit width2 = _mauka->getInstanceIdWidth(instanceoccurrenceid2);
return width1 > width2;
}
};
}
void Surface::_DisplayInstances(MaukaEngine::UVector& instanceids, SubRowList& subrowlist)
{
// Insert instances in subrows
sort(instanceids.begin(), instanceids.end(), sortInstanceOccurrencesIdsByWidth(_mauka));
SubRowList::iterator srlit = subrowlist.begin();
MaukaEngine::UVector::const_iterator insIterator = instanceids.begin();
MaukaEngine::UVector::const_iterator lastLoopInsertedInsIterator = insIterator;
size_t nbInstancesPlaced = 0;
// First instance.
// if ( insIterator != instanceids.end() ) {
// Cell* master = (static_cast<Instance*>(_mauka->_instanceOccurrencesVector[*insIterator].getEntity()))->getMasterCell();
// DbU::Unit instanceWidth = _mauka->_instanceWidths[*insIterator];
// cerr << " Trying to add #0 id:" << *insIterator
// << " w:" << DbU::getValueString(instanceWidth)<< " " << master << endl;
// }
while (true)
{
if (insIterator == instanceids.end())
{
break;
// end of insertion
}
if (srlit == subrowlist.end())
{
if ( cmess2.enabled() ) cerr << "\n";
cerr << Warning("Mauka::_DisplayInstances(): Cannot honor Bin margin, bypassing.") << endl;
srlit = subrowlist.begin();
if (lastLoopInsertedInsIterator != insIterator)
lastLoopInsertedInsIterator = insIterator;
else
{
// insertion of instances with respect of Bins margin
// did not succeed, 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;
DbU::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 << "Box: " << getBoundingBox() << endl;
throw Error("Not enough free space to place all the instances.<br>\n"
"Please increase the abutment box: %s %d placeds (%d instances remains to place)"
,getString(getBoundingBox()).c_str()
,nbInstancesPlaced
,(nbInstancesToPlace - nbInstancesPlaced)
);
}
}
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;
// cerr << " Bin: " << bin->getBoundingBox()
// << " capa:" << DbU::getValueString(bin->getCapa())
// << " size:" << DbU::getValueString(bin->getSize())
// << " SubRow:"
// << " capa:" << DbU::getValueString(subRow->getCapa())
// << " size:" << DbU::getValueString(subRow->getSize())
// << endl;
if (insIterator == instanceids.end()) break;
unsigned instanceId = *insIterator;
DbU::Unit instanceWidth = _mauka->_instanceWidths[instanceId];
if (instanceWidth > subRow->getCapaVsSize()) {
// cerr << " SubRow capacity exceeded" << endl;
break;
}
if (bin->TryAddInstance(instanceId)) {
srlit = subrowlist.begin();
++nbInstancesPlaced;
++insIterator;
// if ( insIterator != instanceids.end() ) {
// Instance* instance = static_cast<Instance*>(_mauka->_instanceOccurrencesVector[instanceId].getEntity());
// instanceWidth = _mauka->_instanceWidths[instanceId];
// cerr << " Trying to add #" << nbInstancesPlaced
// << " id:" << *insIterator
// << " w:" << DbU::getValueString(instanceWidth)<< " " << instance << endl;
// cerr << " " << _mauka->_instanceOccurrencesVector[instanceId]<< endl;
// }
break;
}
}
++srlit;
// if ( srlit != subrowlist.end() ) {
// cerr << " SubRow capaVsSize: " << DbU::getValueString((*srlit)->getCapaVsSize()) << endl;
// }
}
}
}
Record* Surface::_getRecord() const
{
Record* record = Inherit::_getRecord();
if (record) {
record->add(getSlot("MaukaEngine", _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;
}
}