// This file is part of the Coriolis Project. // Copyright (C) Laboratoire LIP6 - Departement ASIM // Universite Pierre et Marie Curie // // Main contributors : // Christophe Alexandre // Sophie Belloeil // Hugo Clément // Jean-Paul Chaput // Damien Dupuis // Christian Masson // Marek Sroka // // 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 : 19/07/2006 // Author : Christophe Alexandre // // Authors-Tag #include "crlcore/CellGauge.h" #include "crlcore/AllianceFramework.h" #include "mauka/Bin.h" #include "mauka/Row.h" #include "mauka/Surface.h" #include "mauka/SimAnnealingPlacer.h" #include "mauka/SubRow.h" namespace Mauka { using namespace std; using Hurricane::Error; using CRL::AllianceFramework; SubRow::SubRow(Cell* cell, Surface* surface, const Box& box) :Inherit(cell, box) , _surface(surface) , _row(NULL) , _binVector() , _size(0) , _capa(0) {} SubRow* SubRow::create(Cell* cell, Surface* surface, const Box& box, bool orientation) { SubRow* subRow = new SubRow(cell, surface, box); subRow->_postCreate(orientation); return subRow; } void SubRow::_postCreate(bool orientation) { _row = _surface->InsertSubRowInRow(this, orientation); unsigned nBins = 0; if (getWidth() % _surface->_binWidthMax) nBins = getWidth() / _surface->_binWidthMax + 1; else nBins = getWidth() / _surface->_binWidthMax; if (nBins == 0) { assert (getWidth() >= _surface->_binWidthMin); nBins = 1; } DbU::Unit pitch = AllianceFramework::get()->getCellGauge()->getPitch(); DbU::Unit binsWidth = ((getWidth() / pitch) / nBins) * pitch; if (getWidth() % pitch) throw Error("Subrow Width: " + getString(getWidth()) + " is not a multiple of pitch"); if (binsWidth % pitch) throw Error("Bins Width not a multiple of pitch"); DbU::Unit totalBinsWidth = binsWidth * nBins; DbU::Unit binsWidthRemain = getWidth() - totalBinsWidth; if (binsWidthRemain % pitch) throw Error("Bins Width not a multiple of pitch"); unsigned binsWidthRemainPitch = binsWidthRemain / pitch; DbU::Unit xMin = getXMin(); DbU::Unit xMax = xMin; for (unsigned binId = 0; binId < nBins; binId++) { if (binsWidthRemainPitch > 0) { xMax += binsWidth + pitch; binsWidthRemainPitch--; } else xMax += binsWidth; Bin* bin = Bin::create(getCell(), this, Box(xMin, getYMin(), xMax, getYMax())); _binVector.push_back(bin); unsigned binIdx = _binVector.size() - 1; _binXMax[bin->getXMax()] = binIdx; xMin = xMax; } Inherit::_postCreate(); } bool SubRow::_MergeBins() { if (_binVector.size() > 1) { cerr << "merging " << this << endl; _size = 0; Bin* bin = Bin::create(getCell(), this, Box(getXMin(), getYMin(), getXMax(), getYMax())); for (BinVector::iterator bvit = _binVector.begin(); bvit != _binVector.end(); bvit++) { for (MaukaEngine::UList::const_iterator ulit = (*bvit)->_instanceOccurrenceIds.begin(); ulit != (*bvit)->_instanceOccurrenceIds.end(); ulit++) { _surface->_mauka->_simAnnealingPlacer->_instanceBins[*ulit] = NULL; } (*bvit)->destroy(); } _binVector.clear(); _binVector.push_back(bin); return true; } return false; } void SubRow::_computeCapacity(double margin) { for (BinVector::const_iterator bvit = _binVector.begin(); bvit != _binVector.end(); bvit++) { (*bvit)->_computeCapacity(margin); _capa += (*bvit)->_capa; } } void SubRow::_preDestroy() { Inherit::_preDestroy(); for (BinVector::iterator bvit = _binVector.begin(); bvit != _binVector.end(); bvit++) { (*bvit)->destroy(); } } void SubRow::DisplayBinHits() const { for (BinVector::const_iterator bvit = _binVector.begin(); bvit != _binVector.end(); bvit++) { (*bvit)->DisplayHits(); } } Bin* SubRow::getBinBetween(DbU::Unit lowerX, DbU::Unit upperX, const Bin* srcbin) { assert(lowerX <= upperX); assert(lowerX >= getXMin()); assert(upperX <= getXMax()); if (_binVector.size() == 1) return _binVector[0]; DbU::Unit searchPosition = lowerX + DbU::lambda((int)(DbU::getLambda(upperX-lowerX) * rand() / (RAND_MAX + 1.0))); unsigned binId = _binXMax.upper_bound(searchPosition)->second; if (_binVector[binId] == srcbin) { if (binId == 0) return _binVector[1]; if (binId == _binVector.size() - 1) return _binVector[_binVector.size() - 2]; static bool altern = true; if (altern) { altern = false; return _binVector[binId + 1]; } else { altern = true; return _binVector[binId - 1]; } } return _binVector[binId]; } void SubRow::_AddSize(DbU::Unit value) { _size += value; _row->_AddSize(value); } double SubRow::getCost() const { return abs(DbU::getLambda(_size - _capa)); } double SubRow::getBinCost() const { double binCost = 0.0; for (BinVector::const_iterator bvit = _binVector.begin(); bvit != _binVector.end(); bvit++) binCost += (*bvit)->getCost(); return binCost; } DbU::Unit SubRow::getBinsSize() const { DbU::Unit totalBinsSize = 0; for (BinVector::const_iterator bvit = _binVector.begin(); bvit != _binVector.end(); bvit++) { totalBinsSize += (*bvit)->getSize(); } return totalBinsSize; } DbU::Unit SubRow::getBinsCapa() const { DbU::Unit totalBinsCapa = 0; for (BinVector::const_iterator bvit = _binVector.begin(); bvit != _binVector.end(); bvit++) { totalBinsCapa += (*bvit)->getCapa(); } return totalBinsCapa; } Cell* SubRow::getCell() const { return _row->getCell(); } }