| /*===================================================================*/ |
| // |
| // place_bin.c |
| // |
| // Aaron P. Hurst, 2007 |
| // ahurst@eecs.berkeley.edu |
| // |
| /*===================================================================*/ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <limits.h> |
| #include <assert.h> |
| |
| //#define DEBUG |
| |
| #include "place_base.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| // -------------------------------------------------------------------- |
| // Global variables |
| // |
| // -------------------------------------------------------------------- |
| |
| |
| // -------------------------------------------------------------------- |
| // Function prototypes and local data structures |
| // |
| // -------------------------------------------------------------------- |
| |
| void spreadDensityX(int numBins, float maxMovement); |
| void spreadDensityY(int numBins, float maxMovement); |
| |
| |
| // -------------------------------------------------------------------- |
| // globalFixDensity() |
| // |
| /// Doesn't deal well with fixed cells in the core area. |
| // -------------------------------------------------------------------- |
| void globalFixDensity(int numBins, float maxMovement) { |
| |
| printf("QCLN-10 : \tbin-based density correction\n"); |
| |
| spreadDensityX(numBins, maxMovement); |
| // spreadDensityY(numBins, maxMovement); |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| // spreadDensityX() |
| // |
| // -------------------------------------------------------------------- |
| void spreadDensityX(int numBins, float maxMovement) { |
| |
| int c, c2, c3, x, y; |
| float totalArea = 0; |
| int moveableCells = 0; |
| float yBinArea = 0, yCumArea = 0; |
| int yBinStart = 0, yBinCount = 0; |
| int xBinCount, xBinStart; |
| float xBinArea, xCumArea; |
| float lastOldEdge; |
| float lastNewEdge; |
| float curOldEdge, curNewEdge; |
| float stretch, w; |
| ConcreteCell *xCell, *yCell; |
| ConcreteCell **binCells; |
| ConcreteCell **allCells; |
| |
| binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); |
| allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); |
| |
| for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) { |
| ConcreteCell *cell = g_place_concreteCells[c]; |
| if (!cell->m_fixed && !cell->m_parent->m_pad) { |
| allCells[moveableCells++] = cell; |
| totalArea += getCellArea(cell); |
| } |
| } |
| |
| // spread X |
| qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByY); |
| |
| y = 0; |
| |
| // for each y-bin... |
| for(c=0; c<moveableCells; c++) { |
| yCell = allCells[c]; |
| yBinArea += getCellArea(yCell); |
| yCumArea += getCellArea(yCell); |
| yBinCount++; |
| |
| // have we filled up a y-bin? |
| if (yCumArea >= totalArea*(y+1)/numBins && yBinArea > 0) { |
| memcpy(binCells, &(allCells[yBinStart]), sizeof(ConcreteCell*)*yBinCount); |
| qsort(binCells, yBinCount, sizeof(ConcreteCell*), cellSortByX); |
| |
| #if defined(DEBUG) |
| printf("y-bin %d count=%d area=%f\n",y,yBinCount, yBinArea); |
| #endif |
| |
| x = 0; |
| xBinCount = 0, xBinStart = 0; |
| xBinArea = 0, xCumArea = 0; |
| lastOldEdge = g_place_coreBounds.x; |
| lastNewEdge = g_place_coreBounds.x; |
| |
| // for each x-bin... |
| for(c2=0; c2<yBinCount; c2++) { |
| xCell = binCells[c2]; |
| xBinArea += getCellArea(xCell); |
| xCumArea += getCellArea(xCell); |
| xBinCount++; |
| curOldEdge = xCell->m_x; |
| |
| printf("%.3f ", xCell->m_x); |
| |
| // have we filled up an x-bin? |
| if (xCumArea >= yBinArea*(x+1)/numBins && xBinArea > 0) { |
| curNewEdge = lastNewEdge + g_place_coreBounds.w*xBinArea/yBinArea; |
| |
| if (curNewEdge > g_place_coreBounds.x+g_place_coreBounds.w) |
| curNewEdge = g_place_coreBounds.x+g_place_coreBounds.w; |
| if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement; |
| if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement; |
| |
| #if defined(DEBUG) |
| printf("->\tx-bin %d count=%d area=%f (%f,%f)->(%f,%f)\n",x, xBinCount, xBinArea, |
| curOldEdge, lastOldEdge, curNewEdge, lastNewEdge); |
| #endif |
| |
| stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge); |
| |
| // stretch! |
| for(c3=xBinStart; c3<xBinStart+xBinCount; c3++) { |
| if (curOldEdge == lastOldEdge) |
| binCells[c3]->m_x = lastNewEdge+(c3-xBinStart)*(curNewEdge-lastNewEdge); |
| else |
| binCells[c3]->m_x = lastNewEdge+(binCells[c3]->m_x-lastOldEdge)*stretch; |
| |
| // force within core |
| w = binCells[c3]->m_parent->m_width*0.5; |
| if (binCells[c3]->m_x-w < g_place_coreBounds.x) |
| binCells[c3]->m_x = g_place_coreBounds.x+w; |
| if (binCells[c3]->m_x+w > g_place_coreBounds.x+g_place_coreBounds.w) |
| binCells[c3]->m_x = g_place_coreBounds.x+g_place_coreBounds.w-w; |
| } |
| |
| lastOldEdge = curOldEdge; |
| lastNewEdge = curNewEdge; |
| x++; |
| xBinCount = 0; |
| xBinArea = 0; |
| xBinStart = c2+1; |
| } |
| } |
| |
| y++; |
| yBinCount = 0; |
| yBinArea = 0; |
| yBinStart = c+1; |
| } |
| } |
| |
| free(binCells); |
| free(allCells); |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| // spreadDensityY() |
| // |
| // -------------------------------------------------------------------- |
| void spreadDensityY(int numBins, float maxMovement) { |
| |
| int c, c2, c3, x, y; |
| float totalArea = 0; |
| int moveableCells = 0; |
| float xBinArea = 0, xCumArea = 0; |
| int xBinStart = 0, xBinCount = 0; |
| int yBinCount, yBinStart; |
| float yBinArea, yCumArea; |
| float lastOldEdge; |
| float lastNewEdge; |
| float curOldEdge, curNewEdge; |
| float stretch, h; |
| ConcreteCell *xCell, *yCell; |
| ConcreteCell **binCells; |
| ConcreteCell **allCells; |
| |
| binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); |
| allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); |
| |
| for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) { |
| ConcreteCell *cell = g_place_concreteCells[c]; |
| if (!cell->m_fixed && !cell->m_parent->m_pad) { |
| allCells[moveableCells++] = cell; |
| totalArea += getCellArea(cell); |
| } |
| } |
| |
| // spread Y |
| qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByX); |
| |
| x = 0; |
| |
| // for each x-bin... |
| for(c=0; c<moveableCells; c++) { |
| xCell = allCells[c]; |
| xBinArea += getCellArea(xCell); |
| xCumArea += getCellArea(xCell); |
| xBinCount++; |
| |
| // have we filled up an x-bin? |
| if (xCumArea >= totalArea*(x+1)/numBins && xBinArea > 0) { |
| memcpy(binCells, &(allCells[xBinStart]), sizeof(ConcreteCell*)*xBinCount); |
| qsort(binCells, xBinCount, sizeof(ConcreteCell*), cellSortByY); |
| |
| // printf("x-bin %d count=%d area=%f\n",y,yBinCount, yBinArea); |
| |
| y = 0; |
| yBinCount = 0, yBinStart = 0; |
| yBinArea = 0, yCumArea = 0; |
| lastOldEdge = g_place_coreBounds.y; |
| lastNewEdge = g_place_coreBounds.y; |
| |
| // for each y-bin... |
| for(c2=0; c2<xBinCount; c2++) { |
| yCell = binCells[c2]; |
| yBinArea += getCellArea(yCell); |
| yCumArea += getCellArea(yCell); |
| yBinCount++; |
| curOldEdge = yCell->m_y; |
| |
| // have we filled up an x-bin? |
| if (yCumArea >= xBinArea*(y+1)/numBins && yBinArea > 0) { |
| curNewEdge = lastNewEdge + g_place_coreBounds.h*yBinArea/xBinArea; |
| |
| if (curNewEdge > g_place_coreBounds.y+g_place_coreBounds.h) |
| curNewEdge = g_place_coreBounds.y+g_place_coreBounds.h; |
| if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement; |
| if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement; |
| |
| if (curOldEdge == lastOldEdge) continue; // hmmm |
| stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge); |
| |
| // stretch! |
| for(c3=yBinStart; c3<yBinStart+yBinCount; c3++) { |
| binCells[c3]->m_y = lastNewEdge+(binCells[c3]->m_y-lastOldEdge)*stretch; |
| |
| // force within core |
| h = binCells[c3]->m_parent->m_height; |
| if (binCells[c3]->m_y-h < g_place_coreBounds.y) |
| binCells[c3]->m_y = g_place_coreBounds.y+h; |
| if (binCells[c3]->m_y+h > g_place_coreBounds.y+g_place_coreBounds.h) |
| binCells[c3]->m_y = g_place_coreBounds.y+g_place_coreBounds.h-h; |
| } |
| |
| lastOldEdge = curOldEdge; |
| lastNewEdge = curNewEdge; |
| y++; |
| yBinCount = 0; |
| yBinArea = 0; |
| yBinStart = c2+1; |
| } |
| } |
| |
| x++; |
| xBinCount = 0; |
| xBinArea = 0; |
| xBinStart = c+1; |
| } |
| } |
| |
| free(binCells); |
| free(allCells); |
| } |
| ABC_NAMESPACE_IMPL_END |
| |