/*===================================================================*/ // // place_base.c // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include #include #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; tm_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; nm_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; cm_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