coriolis/knik/src/MatrixVertex.cpp

447 lines
18 KiB
C++

#include <algorithm>
#include "hurricane/Cell.h"
#include "hurricane/Box.h"
#include "crlcore/AllianceFramework.h"
#include "crlcore/CellGauge.h"
#include "knik/Graph.h"
#include "knik/MatrixVertex.h"
#include "knik/KnikEngine.h"
namespace Knik {
using namespace std;
using namespace CRL;
MatrixVertex::MatrixVertex ( Graph* routingGraph )
// ***********************************************
: _xInit(false)
, _yInit(false)
, _xRegular(false)
, _yRegular(false)
, _nbXTiles(0)
, _nbYTiles(0)
, _tileWidth(0)
, _tileHeight(0)
, _boundingBox(0,0,1,1)
, _routingGraph(routingGraph)
{
}
MatrixVertex* MatrixVertex::create ( Graph* routingGraph )
// *******************************************************
{
MatrixVertex* matrixVertex = new MatrixVertex(routingGraph);
return matrixVertex;
}
MatrixVertex::~MatrixVertex()
// **************************
{
}
void MatrixVertex::destroy()
// ************************
{
_preDestroy();
delete ( this );
}
void MatrixVertex::_preDestroy()
// ****************************
{
}
//void MatrixVertex::createXRegular ( RoutingGrid* routingGrid )
//// ***********************************************************
//{
//
// if ( _xInit )
// throw Error ("MatrixVertex::createXRegular(): cannot initialize X vector twice.");
// _lowerLeftX = routingGrid->getLowerLeftX();
// _nbXTiles = routingGrid->getNbXTiles();
// _tileWidth = routingGrid->getTileWidth();
// _xRegular = true;
// _xInit = true;
//
// if ( _xInit && _yInit )
// createMatrix();
//}
//void MatrixVertex::createYRegular ( RoutingGrid* routingGrid )
//// ***********************************************************
//{
// if ( _yInit )
// throw Error ("MatrixVertex::createYRegular(): cannot initialize Y vector twice.");
// _boundingBox.getYMin() = routingGrid->getLowerLeftY();
// _nbYTiles = routingGrid->getNbYTiles();
// _tileHeight = routingGrid->getTileHeight();
// _yRegular = true;
// _yInit = true;
//
// if ( _xInit && _yInit )
// createMatrix();
//}
Vertex* MatrixVertex::createRegularMatrix ( RoutingGrid* routingGrid )
// *******************************************************************
{
if ( _xInit || _yInit )
throw Error ("MatrixVertex::createRegularMatrix(): cannot initialize matrix twice.");
_boundingBox = routingGrid->getBoundingBox();
_nbXTiles = routingGrid->getNbXTiles();
_nbYTiles = routingGrid->getNbYTiles();
_tileWidth = routingGrid->getTileWidth();
_tileHeight = routingGrid->getTileHeight();
_xInit = true; // XXX Nécessaire pour les fonctions comme getLineIndex
_yInit = true;
_xRegular = true; // XXX Nécessaire pour les fonctions comme getLineIndex
_yRegular = true;
DbU::Unit halfWidth = _tileWidth / 2;
DbU::Unit halfHeight = _tileHeight / 2;
// On cree les vecteurs de vertex en meme temps que les vertex et aussi les edges !
for ( unsigned j = 0 ; j < _nbYTiles ; j++ ) {
vector<Vertex*> vect;
for ( unsigned i = 0 ; i < _nbXTiles ; i++ ) {
Point position ( _boundingBox.getXMin()+(i*_tileWidth)+halfWidth, _boundingBox.getYMin()+(j*_tileHeight)+halfHeight );
// on cree le vertex
Vertex* vertex = _routingGraph->createVertex ( position, halfWidth, halfHeight );
assert ( vertex );
// on l'ajoute dans la matrice
vect.push_back ( vertex );
// si i > 0 alors on peut creer une edge horizontale entre matrix[i-1][j] et matrix[i][j] c'est a dire vect[i-1] et vect[i]
if ( i > 0 ) {
Vertex* from = vect[i-1];
assert(from);
Vertex* to = vect[i];
assert(to);
_routingGraph->createHEdge ( from, to );
}
// si j > 0 alors on peut creer une edge verticale entre matrix[i][j-1] et matrix[i][j] c'est a dire _matrix[j-1][i] et vect[i]
if ( j > 0 ) { // _matrix est un vecteur de vecteur represantant les lignes -> _matrix[ligne][colonne]
Vertex* from = _matrix[j-1][i];
assert(from);
Vertex* to = vect[i];
assert(to);
_routingGraph->createVEdge ( from, to );
}
}
_matrix.push_back ( vect );
}
return _matrix[0][0];
}
Vertex* MatrixVertex::createRegularMatrix ()
// *****************************************
{
if ( _xInit || _yInit )
throw Error ("MatrixVertex::createRegularMatrix(): cannot initialize matrix twice.");
Cell* cell = _routingGraph->getCell();
DbU::Unit sliceHeight = AllianceFramework::get()->getCellGauge()->getSliceHeight();
DbU::Unit cellWidth = cell->getAbutmentBox().getWidth();
DbU::Unit cellHeight = cell->getAbutmentBox().getHeight();
_boundingBox = cell->getAbutmentBox();
_nbXTiles = (unsigned int)ceil(float(cellWidth) / float(sliceHeight));
_nbYTiles = (unsigned int)ceil(float(cellHeight) / float(sliceHeight));
_tileWidth = sliceHeight;
_tileHeight = sliceHeight;
DbU::Unit _latestTileWidth = cellWidth - ((_nbXTiles - 1) * _tileWidth);
DbU::Unit _latestTileHeight = cellHeight - ((_nbYTiles - 1) * _tileHeight);
_xInit = true; // XXX Nécessaire pour les fonctions comme getLineIndex
_yInit = true;
_xRegular = true; // XXX Nécessaire pour les fonctions comme getLineIndex
_yRegular = true;
// cerr << "Resume :" << endl
// << " - this : " << (void*)this << endl
// << " - cellWidth : " << cellWidth << endl
// << " - cellHeight : " << cellHeight << endl
// << " - boundingBox : " << _boundingBox << endl
// << " - nbXTiles : " << _nbXTiles << endl
// << " - nbYTiles : " << _nbYTiles << endl
// << " - tileWidth : " << _tileWidth << endl
// << " - tileHieght : " << _tileHeight << endl
// << " - latestTileWidth : " << _latestTileWidth << endl
// << " - latestTileHeight : " << _latestTileHeight << endl;
// On cree les vecteurs de vertex en meme temps que les vertex et aussi les edges !
size_t hreserved = KnikEngine::get( cell )->getHEdgeReservedLocal();
size_t vreserved = KnikEngine::get( cell )->getVEdgeReservedLocal();
for ( unsigned j = 0 ; j < _nbYTiles ; j++ ) {
vector<Vertex*> vect;
for ( unsigned i = 0 ; i < _nbXTiles ; i++ ) {
DbU::Unit halfWidth = (i == _nbXTiles - 1)?_latestTileWidth/2:_tileWidth/2;
DbU::Unit halfHeight = (j == _nbYTiles - 1)?_latestTileHeight/2:_tileHeight/2;
Point position ( _boundingBox.getXMin()+(i*_tileWidth)+halfWidth, _boundingBox.getYMin()+(j*_tileHeight)+halfHeight );
// on cree le vertex
Vertex* vertex = _routingGraph->createVertex ( position, halfWidth, halfHeight );
assert ( vertex );
//cerr << ". .. " << vertex << endl;
// on l'ajoute dans la matrice
vect.push_back ( vertex );
// si i > 0 alors on peut creer une edge horizontale entre matrix[i-1][j] et matrix[i][j] c'est a dire vect[i-1] et vect[i]
if ( i > 0 ) {
Vertex* from = vect[i-1];
assert(from);
Vertex* to = vect[i];
assert(to);
_routingGraph->createHEdge ( from, to, hreserved );
}
// si j > 0 alors on peut creer une edge verticale entre matrix[i][j-1] et matrix[i][j] c'est a dire _matrix[j-1][i] et vect[i]
if ( j > 0 ) { // _matrix est un vecteur de vecteur represantant les lignes -> _matrix[ligne][colonne]
Vertex* from = _matrix[j-1][i];
assert(from);
Vertex* to = vect[i];
assert(to);
_routingGraph->createVEdge ( from, to, vreserved );
}
}
_matrix.push_back ( vect );
}
//cerr << "---------------------------" << endl;
//print();
return _matrix[0][0];
}
//void MatrixVertex::createXIrregular ( NimbusEngine* nimbus )
//// *********************************************************
//{
// if ( _xInit )
// throw Error ("MatrixVertex::createXIrregular(): cannot initialize X vector twice.");
// GCell* gcell = nimbus->getGrid()->getLowerLeftCorner ( nimbus->getDepth() );
// assert(gcell);
// unsigned index = 0;
// _columnsIndexes.push_back ( pair<DbU::Unit,unsigned>(gcell->getXMin(),index++) );
// while ( gcell ) {
// //if ( gcell->getRightFence() ) pour la dernière gcell, on veut récupérer la fence virtuelle de droite
// _columnsIndexes.push_back ( pair<DbU::Unit,unsigned>(gcell->getXMax(),index++) );
// gcell = gcell->getRightOfMe();
// }
// _nbXTiles = index-1;
// //assert ( is_sorted(vertiCutLines.begin(), vertiCutLines.end()) );
// //for ( unsigned i = 0 ; i < vertiCutLines.size() ; i++ )
// // _columnsIndexes.push_back ( pair<DbU::Unit,unsigned> (vertiCutLines[i], i) );
// assert ( is_sorted(_columnsIndexes.begin(), _columnsIndexes.end(), IndexComp()) );
// //_nbXTiles = _columnsIndexes.size()-1;
// _xRegular = false;
// _xInit = true;
//
// if ( _xInit && _yInit )
// createMatrix();
//}
//void MatrixVertex::createYIrregular ( NimbusEngine* nimbus )
//// *********************************************************
//{
// if ( _yInit )
// throw Error ("MatrixVertex::createYIrregular(): cannot initialize Y vector twice.");
//
// GCell* gcell = nimbus->getGrid()->getLowerLeftCorner ( nimbus->getDepth() );
// assert(gcell);
// unsigned index = 0;
// _linesIndexes.push_back ( pair<DbU::Unit,unsigned>(gcell->getYMin(),index++) );
// while ( gcell ) {
// _linesIndexes.push_back ( pair<DbU::Unit,unsigned>(gcell->getYMax(),index++) );
// gcell = gcell->getUpOfMe();
// }
// assert ( is_sorted(_linesIndexes.begin(), _linesIndexes.end(), IndexComp()) );
// _nbYTiles = index-1;
// _yRegular = false;
// _yInit = true;
//
// if ( _xInit && _yInit )
// createMatrix();
//}
//void MatrixVertex::createMatrix()
//// ******************************
//{
// assert ( _xInit && _yInit );
// for ( unsigned j = 0 ; j < _nbYTiles ; j++ ) {
// vector<Vertex*> vect;
// for ( unsigned i = 0 ; i < _nbXTiles ; i++ ) {
// Vertex* vertex (NULL);
// vect.push_back ( vertex );
// }
// _matrix.push_back ( vect );
// }
//}
void MatrixVertex::setVertex ( pair<unsigned int,unsigned int> indexes, Vertex* vertex )
// *************************************************************************************
{
_matrix[indexes.second][indexes.first] = vertex;
}
void MatrixVertex::setVertex ( Point point, Vertex* vertex )
// *********************************************************
{
pair<unsigned int,unsigned int> indexes = getIJ ( point );
setVertex ( indexes, vertex );
}
unsigned int MatrixVertex::getLineIndex ( DbU::Unit y )
// ***********************************************
{
assert(_yInit );
if ( _yRegular ) {
// cerr << "y:" << DbU::getValueString(y-_boundingBox.getYMin()) << "/" << DbU::getValueString(_tileHeight)
// << "=" << (DbU::getLambda(y-_boundingBox.getYMin())/_tileHeight)
// << "<=>" << (unsigned int)floor((y-_boundingBox.getYMin())/_tileHeight) << endl;
if ( (y < _boundingBox.getYMin()) or (y > _boundingBox.getYMax()) )
throw Error ("MatrixVertex::getLineIndex(): search value (%s) is out of bounds [%s,%s]."
,DbU::getValueString(y).c_str()
,DbU::getValueString(_boundingBox.getYMin()).c_str()
,DbU::getValueString(_boundingBox.getYMax()).c_str());
unsigned int index = (unsigned int)floor((y-_boundingBox.getYMin())/_tileHeight);
if ( y == _boundingBox.getYMax() ) --index;
return index;
}
assert(is_sorted(_linesIndexes.begin(), _linesIndexes.end()));
if ( _linesIndexes.empty() )
throw Error ( "MatrixVertex::getLineIndex(): Indexes map is empty." );
pair<pairIterator,pairIterator> result = equal_range (_linesIndexes.begin(), _linesIndexes.end()
, pair<DbU::Unit,unsigned>(y,0), MatrixVertex::IndexComp());
if ( result.second == _linesIndexes.begin() )
throw Error ("MatrixVertex::getLineIndex(): search value (%s) is lower than lowest bound (%s)."
,DbU::getValueString(y).c_str()
,DbU::getValueString((*_linesIndexes.begin()).first).c_str());
if ( result.second == _linesIndexes.end() )
throw Error ("MatrixVertex::getLineIndex(): search value (%s) is upper than uppest bound (%s)."
,DbU::getValueString(y).c_str()
,DbU::getValueString((*_linesIndexes.rbegin()).first).c_str());
return ((*result.second).second-1);
}
unsigned int MatrixVertex::getColumnIndex ( DbU::Unit x )
// *************************************************
{
assert(_xInit );
if ( _xRegular ) {
// cerr << "x:" << DbU::getValueString(x-DbU::lambda(_boundingBox.getXMin())) << "/" << _tileWidth << "=" << (DbU::getLambda(x-DbU::lambda(_lowerLeftX))/_tileWidth)
// << "<=>" << (unsigned int)floor(DbU::getLambda(x-DbU::lambda(_boundingBox.getXMin()))/_tileWidth) << endl;
if ( (x < _boundingBox.getXMin()) or (x > _boundingBox.getXMax()) )
throw Error ("MatrixVertex::getColumnIndex(): search value (%s) is out of bounds [%s,%s]."
,DbU::getValueString(x).c_str()
,DbU::getValueString(_boundingBox.getXMin()).c_str()
,DbU::getValueString(_boundingBox.getXMax()).c_str());
unsigned int index = (unsigned int)floor((x-_boundingBox.getXMin())/_tileWidth);
if ( x == _boundingBox.getXMax() ) --index;
return index;
}
assert(is_sorted(_columnsIndexes.begin(),_columnsIndexes.end()));
if ( _columnsIndexes.empty() )
throw Error ( "MatrixVertex::getColumnIndex(): Indexes map is empty." );
pair<pairIterator,pairIterator> result = equal_range (_columnsIndexes.begin(), _columnsIndexes.end()
, pair<DbU::Unit,unsigned>(x,0), MatrixVertex::IndexComp());
if ( result.second == _columnsIndexes.begin() )
throw Error ("MatrixVertex::getColumnIndex(): search value is lower than lowest bound.");
if ( result.second == _columnsIndexes.end() )
throw Error ("MatrixVertex::getColumnIndex(): search value is upper than uppest bound.");
return ((*result.second).second-1);
}
pair<unsigned int,unsigned int> MatrixVertex::getIJ ( DbU::Unit x, DbU::Unit y )
// *******************************************************************
{
return pair<unsigned int,unsigned int> (getColumnIndex(x),getLineIndex(y));
}
pair<unsigned int,unsigned int> MatrixVertex::getIJ ( const Point& point )
// ***********************************************************************
{
return pair<unsigned int,unsigned int> (getColumnIndex(point.getX()),getLineIndex(point.getY()));
}
Vertex* MatrixVertex::getVertex ( pair<unsigned int,unsigned int> indexes )
// ************************************************************************
{
return _matrix[indexes.second][indexes.first];
}
Vertex* MatrixVertex::getVertex ( Point point )
// ********************************************
{
pair<unsigned int,unsigned int> indexes = getIJ ( point );
Vertex* vertex = getVertex ( indexes );
cdebug_log(139,0) << "MatrixVertex::getVertex(): " << vertex << endl;
if (vertex and vertex->isBlocked()) {
cdebug_log(139,0) << "Vertex is blocked, looking for neighbor." << endl;
Vertex* neighbor = NULL;
for ( size_t i=0; i<4 ; ++i ) {
neighbor = vertex->getFirstEdges(i)->getOpposite( vertex );
if (neighbor and not neighbor->isBlocked())
return neighbor;
}
}
if (not vertex) {
cerr << Error( "MatrixVertex::getVertex(Point): On %s,\n"
" blocked and it's neighbors are also blocked (vertex unreachable)."
, getString(vertex).c_str() ) << endl;
}
return vertex;
}
Vertex* MatrixVertex::getVertex ( DbU::Unit x, DbU::Unit y )
// *********************************************************
{
pair<unsigned int,unsigned int> indexes = getIJ ( x, y );
return getVertex ( indexes );
}
Vertex* MatrixVertex::getVertexFromIndexes ( unsigned lineIdx, unsigned columnIdx )
// ********************************************************************************
{
return _matrix[lineIdx][columnIdx];
}
void MatrixVertex::print()
// ***********************
{
//cerr << "\'_linesIndexes\';" << endl;
//for ( unsigned i = 0 ; i < _linesIndexes.size() ; ) {
// cerr << "\'<" << _linesIndexes[i].first << "," << _linesIndexes[i].second << ">\'";
// if ( ++i %10 )
// cerr << ",";
// else
// cerr << ";" << endl;
//}
//cerr << ";" << endl;
//cerr << "\'_columnsIndexes\';" << endl;
//for ( unsigned i = 0 ; i < _columnsIndexes.size() ; ) {
// cerr << "\'<" << _columnsIndexes[i].first << "," << _columnsIndexes[i].second << ">\'";
// if ( ++i %10 )
// cerr << ",";
// else
// cerr << ";" << endl;
//}
//cerr << ";" << endl;
for ( unsigned j = 0 ; j < _nbYTiles ; j++ )
for ( unsigned i = 0 ; i < _nbXTiles ; i++ )
cerr << i << "," << j << " " << _matrix[j][i] << endl;
}
} // end namespace