OpenFPGA/abc/src/phys/place/place_base.c

351 lines
9.7 KiB
C

/*===================================================================*/
//
// place_base.c
//
// Aaron P. Hurst, 2003-2007
// ahurst@eecs.berkeley.edu
//
/*===================================================================*/
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include <string.h>
#include "place_base.h"
#include "place_gordian.h"
ABC_NAMESPACE_IMPL_START
// --------------------------------------------------------------------
// Global variables
//
// --------------------------------------------------------------------
int g_place_numCells = 0;
int g_place_numNets = 0;
float g_place_rowHeight = 1.0;
Rect g_place_coreBounds;
Rect g_place_padBounds;
ConcreteCell **g_place_concreteCells = NULL;
int g_place_concreteCellsSize = 0;
ConcreteNet **g_place_concreteNets = NULL;
int g_place_concreteNetsSize = 0;
// --------------------------------------------------------------------
// getNetBBox()
//
/// \brief Returns the bounding box of a net.
//
// --------------------------------------------------------------------
Rect getNetBBox(const ConcreteNet *net) {
int t;
Rect r;
assert(net);
r.x = r.y = INT_MAX;
r.w = r.h = -INT_MAX;
for(t=0; t<net->m_numTerms; t++) {
r.x = net->m_terms[t]->m_x < r.x ? net->m_terms[t]->m_x : r.x;
r.y = net->m_terms[t]->m_y < r.y ? net->m_terms[t]->m_y : r.y;
r.w = net->m_terms[t]->m_x > r.w ? net->m_terms[t]->m_x : r.w;
r.h = net->m_terms[t]->m_y > r.h ? net->m_terms[t]->m_y : r.h;
}
r.w -= r.x; r.h -= r.y;
return r;
}
// --------------------------------------------------------------------
// getNetWirelength()
//
/// \brief Returns the half-perimeter wirelength of a net.
//
// --------------------------------------------------------------------
float getNetWirelength(const ConcreteNet *net) {
Rect r;
assert(net);
r = getNetBBox(net);
return r.w+r.h;
}
// --------------------------------------------------------------------
// getTotalWirelength()
//
/// \brief Returns the total HPWL of all nets.
//
// --------------------------------------------------------------------
float getTotalWirelength() {
float r = 0;
int n;
for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n])
r += getNetWirelength(g_place_concreteNets[n]);
return r;
}
// --------------------------------------------------------------------
// getCellArea()
//
// --------------------------------------------------------------------
float getCellArea(const ConcreteCell *cell) {
assert(cell);
return cell->m_parent->m_width*cell->m_parent->m_height;
}
// --------------------------------------------------------------------
// addConcreteNet()
//
/// \brief Adds a net to the placement database.
///
/// The net object must already be allocated and the ID must be set
/// appropriately.
//
// --------------------------------------------------------------------
void addConcreteNet(ConcreteNet *net) {
assert(net);
assert(net->m_id >= 0);
if (net->m_id >= g_place_concreteNetsSize) {
g_place_concreteNetsSize = (net->m_id > g_place_concreteNetsSize ?
net->m_id : g_place_concreteNetsSize);
g_place_concreteNetsSize *= 1.5;
g_place_concreteNetsSize += 20;
g_place_concreteNets = (ConcreteNet**)realloc(g_place_concreteNets,
sizeof(ConcreteNet*)*g_place_concreteNetsSize);
assert(g_place_concreteNets);
}
if (net->m_id >= g_place_numNets) {
memset(&(g_place_concreteNets[g_place_numNets]), 0,
sizeof(ConcreteNet*)*(net->m_id+1-g_place_numNets));
g_place_numNets = net->m_id+1;
assert(g_place_numNets <= g_place_concreteNetsSize);
}
g_place_concreteNets[net->m_id] = net;
}
// --------------------------------------------------------------------
// delConcreteNet()
//
/// Does not deallocate memory.
// --------------------------------------------------------------------
void delConcreteNet(ConcreteNet *net) {
assert(net);
g_place_concreteNets[net->m_id] = 0;
while(!g_place_concreteNets[g_place_numNets-1]) g_place_numNets--;
}
// --------------------------------------------------------------------
// addConcreteCell()
//
/// The cell object must already be allocated and the ID must be set
/// appropriately.
//
// --------------------------------------------------------------------
void addConcreteCell(ConcreteCell *cell) {
assert(cell);
assert(cell->m_id >= 0);
if (cell->m_id >= g_place_concreteCellsSize) {
g_place_concreteCellsSize = (cell->m_id > g_place_concreteCellsSize ?
cell->m_id : g_place_concreteCellsSize);
g_place_concreteCellsSize *= 1.5;
g_place_concreteCellsSize += 20;
g_place_concreteCells = (ConcreteCell**)realloc(g_place_concreteCells,
sizeof(ConcreteCell*)*g_place_concreteCellsSize);
assert(g_place_concreteCells);
}
if (cell->m_id >= g_place_numCells) {
memset(&(g_place_concreteCells[g_place_numCells]), 0,
sizeof(ConcreteCell*)*(cell->m_id+1-g_place_numCells));
g_place_numCells = cell->m_id+1;
}
g_place_concreteCells[cell->m_id] = cell;
}
// --------------------------------------------------------------------
// delCellFromPartition()
//
// --------------------------------------------------------------------
void delCellFromPartition(ConcreteCell *cell, Partition *p) {
int c;
bool found = false;
assert(cell);
assert(p);
for(c=0; c<p->m_numMembers; c++)
if (p->m_members[c] == cell) {
p->m_members[c] = 0;
p->m_area -= getCellArea(cell);
found = true;
break;
}
if (!found) return;
if (!p->m_leaf) {
delCellFromPartition(cell, p->m_sub1);
delCellFromPartition(cell, p->m_sub2);
}
}
// --------------------------------------------------------------------
// delConcreteCell()
//
/// \brief Removes a cell from the placement database.
///
/// Does not deallocate memory.
///
/// Important: does not modify nets that may point to this
/// cell. If these are connections are not removed, segmentation faults
/// and other nasty errors will occur.
//
// --------------------------------------------------------------------
void delConcreteCell(ConcreteCell *cell) {
assert(cell);
g_place_concreteCells[cell->m_id] = 0;
while(!g_place_concreteCells[g_place_numCells-1]) g_place_numCells--;
if (g_place_rootPartition) delCellFromPartition(cell, g_place_rootPartition);
}
// --------------------------------------------------------------------
// netSortByX...
//
/// \brief Sorts nets by position of one of its corners.
//
/// These are for use with qsort().
///
/// Can tolerate pointers to NULL objects.
///
// --------------------------------------------------------------------
int netSortByL(const void *a, const void *b) {
const ConcreteNet *pa = *(const ConcreteNet **)a;
const ConcreteNet *pb = *(const ConcreteNet **)b;
Rect ba, bb;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
ba = getNetBBox(pa), bb = getNetBBox(pb);
if (ba.x < bb.x) return -1;
if (ba.x > bb.x) return 1;
return 0;
}
int netSortByR(const void *a, const void *b) {
const ConcreteNet *pa = *(const ConcreteNet **)a;
const ConcreteNet *pb = *(const ConcreteNet **)b;
Rect ba, bb;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
ba = getNetBBox(pa), bb = getNetBBox(pb);
if (ba.x + ba.w < bb.x + bb.w) return -1;
if (ba.x + ba.w > bb.x + bb.w) return 1;
return 0;
}
int netSortByB(const void *a, const void *b) {
const ConcreteNet *pa = *(const ConcreteNet **)a;
const ConcreteNet *pb = *(const ConcreteNet **)b;
Rect ba, bb;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
ba = getNetBBox(pa), bb = getNetBBox(pb);
if (ba.y + ba.h < bb.y + bb.h) return -1;
if (ba.y + ba.h > bb.y + bb.h) return 1;
return 0;
}
int netSortByT(const void *a, const void *b) {
const ConcreteNet *pa = *(const ConcreteNet **)a;
const ConcreteNet *pb = *(const ConcreteNet **)b;
Rect ba, bb;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
ba = getNetBBox(pa), bb = getNetBBox(pb);
if (ba.y < bb.y) return -1;
if (ba.y > bb.y) return 1;
return 0;
}
int netSortByID(const void *a, const void *b) {
const ConcreteNet *pa = *(const ConcreteNet **)a;
const ConcreteNet *pb = *(const ConcreteNet **)b;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
if (pa->m_id < pb->m_id) return -1;
if (pa->m_id > pb->m_id) return 1;
return 0;
}
// --------------------------------------------------------------------
// cellSortByX...
//
/// \brief Sorts cells by either position coordinate.
//
/// These are for use with qsort().
///
/// Can tolerate pointers to NULL objects.
//
// --------------------------------------------------------------------
int cellSortByX(const void *a, const void *b) {
const ConcreteCell *pa = *(const ConcreteCell **)a;
const ConcreteCell *pb = *(const ConcreteCell **)b;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
if (pa->m_x < pb->m_x) return -1;
if (pa->m_x > pb->m_x) return 1;
return 0;
}
int cellSortByY(const void *a, const void *b) {
const ConcreteCell *pa = *(const ConcreteCell **)a;
const ConcreteCell *pb = *(const ConcreteCell **)b;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
if (pa->m_y < pb->m_y) return -1;
if (pa->m_y > pb->m_y) return 1;
return 0;
}
int cellSortByID(const void *a, const void *b) {
const ConcreteCell *pa = *(const ConcreteCell **)a;
const ConcreteCell *pb = *(const ConcreteCell **)b;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
if (pa->m_id < pb->m_id) return -1;
if (pa->m_id > pb->m_id) return 1;
return 0;
}
ABC_NAMESPACE_IMPL_END