blob: 3418ffcf20d5219e3459ce171650d86009bfe167 [file] [log] [blame]
/*===================================================================*/
//
// place_genqp.c
//
// Aaron P. Hurst, 2003-2007
// ahurst@eecs.berkeley.edu
//
/*===================================================================*/
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "place_base.h"
#include "place_qpsolver.h"
#include "place_gordian.h"
ABC_NAMESPACE_IMPL_START
// --------------------------------------------------------------------
// Global variables
//
// --------------------------------------------------------------------
qps_problem_t *g_place_qpProb = NULL;
// --------------------------------------------------------------------
// splitPenalty()
//
/// \brief Returns a weight for all of the edges in the clique for a multipin net.
//
// --------------------------------------------------------------------
float splitPenalty(int pins) {
if (pins > 1) {
return 1.0 + CLIQUE_PENALTY/(pins - 1);
// return pow(pins - 1, CLIQUE_PENALTY);
}
return 1.0 + CLIQUE_PENALTY;
}
// --------------------------------------------------------------------
// constructQuadraticProblem()
//
/// \brief Constructs the matrices necessary to do analytical placement.
//
// --------------------------------------------------------------------
void constructQuadraticProblem() {
int maxConnections = 1;
int ignoreNum = 0;
int n,t,c,c2,p;
ConcreteCell *cell;
ConcreteNet *net;
int *cell_numTerms = calloc(g_place_numCells, sizeof(int));
ConcreteNet ***cell_terms = calloc(g_place_numCells, sizeof(ConcreteNet**));
bool incremental = false;
int nextIndex = 1;
int *seen = calloc(g_place_numCells, sizeof(int));
float weight;
int last_index;
// create problem object
if (!g_place_qpProb) {
g_place_qpProb = malloc(sizeof(qps_problem_t));
g_place_qpProb->area = NULL;
g_place_qpProb->x = NULL;
g_place_qpProb->y = NULL;
g_place_qpProb->fixed = NULL;
g_place_qpProb->connect = NULL;
g_place_qpProb->edge_weight = NULL;
}
// count the maximum possible number of non-sparse entries
for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
ConcreteNet *net = g_place_concreteNets[n];
if (net->m_numTerms > IGNORE_NETSIZE) {
ignoreNum++;
}
else {
maxConnections += net->m_numTerms*(net->m_numTerms-1);
for(t=0; t<net->m_numTerms; t++) {
c = net->m_terms[t]->m_id;
p = ++cell_numTerms[c];
cell_terms[c] = (ConcreteNet**)realloc(cell_terms[c], p*sizeof(ConcreteNet*));
cell_terms[c][p-1] = net;
}
}
}
if(ignoreNum) {
printf("QMAN-10 : \t\t%d large nets ignored\n", ignoreNum);
}
// initialize the data structures
g_place_qpProb->num_cells = g_place_numCells;
maxConnections += g_place_numCells + 1;
g_place_qpProb->area = realloc(g_place_qpProb->area,
sizeof(float)*g_place_numCells);// "area" matrix
g_place_qpProb->edge_weight = realloc(g_place_qpProb->edge_weight,
sizeof(float)*maxConnections); // "weight" matrix
g_place_qpProb->connect = realloc(g_place_qpProb->connect,
sizeof(int)*maxConnections); // "connectivity" matrix
g_place_qpProb->fixed = realloc(g_place_qpProb->fixed,
sizeof(int)*g_place_numCells); // "fixed" matrix
// initialize or keep preexisting locations
if (g_place_qpProb->x != NULL && g_place_qpProb->y != NULL) {
printf("QMAN-10 :\tperforming incremental placement\n");
incremental = true;
}
g_place_qpProb->x = (float*)realloc(g_place_qpProb->x, sizeof(float)*g_place_numCells);
g_place_qpProb->y = (float*)realloc(g_place_qpProb->y, sizeof(float)*g_place_numCells);
// form a row for each cell
// build data
for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) {
cell = g_place_concreteCells[c];
// fill in the characteristics for this cell
g_place_qpProb->area[c] = getCellArea(cell);
if (cell->m_fixed || cell->m_parent->m_pad) {
g_place_qpProb->x[c] = cell->m_x;
g_place_qpProb->y[c] = cell->m_y;
g_place_qpProb->fixed[c] = 1;
} else {
if (!incremental) {
g_place_qpProb->x[c] = g_place_coreBounds.x+g_place_coreBounds.w*0.5;
g_place_qpProb->y[c] = g_place_coreBounds.y+g_place_coreBounds.h*0.5;
}
g_place_qpProb->fixed[c] = 0;
}
// update connectivity matrices
last_index = nextIndex;
for(n=0; n<cell_numTerms[c]; n++) {
net = cell_terms[c][n];
weight = net->m_weight / splitPenalty(net->m_numTerms);
for(t=0; t<net->m_numTerms; t++) {
c2 = net->m_terms[t]->m_id;
if (c2 == c) continue;
if (seen[c2] < last_index) {
// not seen
g_place_qpProb->connect[nextIndex-1] = c2;
g_place_qpProb->edge_weight[nextIndex-1] = weight;
seen[c2] = nextIndex;
nextIndex++;
} else {
// seen
g_place_qpProb->edge_weight[seen[c2]-1] += weight;
}
}
}
g_place_qpProb->connect[nextIndex-1] = -1;
g_place_qpProb->edge_weight[nextIndex-1] = -1.0;
nextIndex++;
} else {
// fill in dummy values for connectivity matrices
g_place_qpProb->connect[nextIndex-1] = -1;
g_place_qpProb->edge_weight[nextIndex-1] = -1.0;
nextIndex++;
}
free(cell_numTerms);
free(cell_terms);
free(seen);
}
typedef struct reverseCOG {
float x,y;
Partition *part;
float delta;
} reverseCOG;
// --------------------------------------------------------------------
// generateCoGConstraints()
//
/// \brief Generates center of gravity constraints.
//
// --------------------------------------------------------------------
int generateCoGConstraints(reverseCOG COG_rev[]) {
int numConstraints = 0; // actual num constraints
int cogRevNum = 0;
Partition **stack = malloc(sizeof(Partition*)*g_place_numPartitions*2);
int stackPtr = 0;
Partition *p;
float cgx, cgy;
int next_index = 0, last_constraint = 0;
bool isTrueConstraint = false;
int i, m;
float totarea;
ConcreteCell *cell;
// each partition may give rise to a center-of-gravity constraint
stack[stackPtr] = g_place_rootPartition;
while(stackPtr >= 0) {
p = stack[stackPtr--];
assert(p);
// traverse down the partition tree to leaf nodes-only
if (!p->m_leaf) {
stack[++stackPtr] = p->m_sub1;
stack[++stackPtr] = p->m_sub2;
} else {
/*
cout << "adding a COG constraint for box "
<< p->bounds.x << ","
<< p->bounds.y << " of size"
<< p->bounds.w << "x"
<< p->bounds.h
<< endl;
*/
cgx = p->m_bounds.x + p->m_bounds.w*0.5;
cgy = p->m_bounds.y + p->m_bounds.h*0.5;
COG_rev[cogRevNum].x = cgx;
COG_rev[cogRevNum].y = cgy;
COG_rev[cogRevNum].part = p;
COG_rev[cogRevNum].delta = 0;
cogRevNum++;
}
}
assert(cogRevNum == g_place_numPartitions);
for (i = 0; i < g_place_numPartitions; i++) {
p = COG_rev[i].part;
assert(p);
g_place_qpProb->cog_x[numConstraints] = COG_rev[i].x;
g_place_qpProb->cog_y[numConstraints] = COG_rev[i].y;
totarea = 0.0;
for(m=0; m<p->m_numMembers; m++) if (p->m_members[m]) {
cell = p->m_members[m];
assert(cell);
if (!cell->m_fixed && !cell->m_parent->m_pad) {
isTrueConstraint = true;
}
else {
continue;
}
g_place_qpProb->cog_list[next_index++] = cell->m_id;
totarea += getCellArea(cell);
}
if (totarea == 0.0) {
isTrueConstraint = false;
}
if (isTrueConstraint) {
numConstraints++;
g_place_qpProb->cog_list[next_index++] = -1;
last_constraint = next_index;
}
else {
next_index = last_constraint;
}
}
free(stack);
return --numConstraints;
}
// --------------------------------------------------------------------
// solveQuadraticProblem()
//
/// \brief Calls quadratic solver.
//
// --------------------------------------------------------------------
void solveQuadraticProblem(bool useCOG) {
int c;
reverseCOG *COG_rev = malloc(sizeof(reverseCOG)*g_place_numPartitions);
g_place_qpProb->cog_list = malloc(sizeof(int)*(g_place_numPartitions+g_place_numCells));
g_place_qpProb->cog_x = malloc(sizeof(float)*g_place_numPartitions);
g_place_qpProb->cog_y = malloc(sizeof(float)*g_place_numPartitions);
// memset(g_place_qpProb->x, 0, sizeof(float)*g_place_numCells);
// memset(g_place_qpProb->y, 0, sizeof(float)*g_place_numCells);
qps_init(g_place_qpProb);
if (useCOG)
g_place_qpProb->cog_num = generateCoGConstraints(COG_rev);
else
g_place_qpProb->cog_num = 0;
g_place_qpProb->loop_num = 0;
qps_solve(g_place_qpProb);
qps_clean(g_place_qpProb);
// set the positions
for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) {
g_place_concreteCells[c]->m_x = g_place_qpProb->x[c];
g_place_concreteCells[c]->m_y = g_place_qpProb->y[c];
}
// clean up
free(g_place_qpProb->cog_list);
free(g_place_qpProb->cog_x);
free(g_place_qpProb->cog_y);
free(COG_rev);
}
ABC_NAMESPACE_IMPL_END