diff options
Diffstat (limited to 'src/phys/place/place_partition.c')
-rw-r--r-- | src/phys/place/place_partition.c | 1135 |
1 files changed, 0 insertions, 1135 deletions
diff --git a/src/phys/place/place_partition.c b/src/phys/place/place_partition.c deleted file mode 100644 index ea57cd1c..00000000 --- a/src/phys/place/place_partition.c +++ /dev/null @@ -1,1135 +0,0 @@ -/*===================================================================*/ -// -// place_partition.c -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include <stdlib.h> -#include <math.h> -#include <string.h> -#include <stdio.h> -#include <limits.h> -#include <assert.h> -//#include <sys/stat.h> -//#include <unistd.h> - -#include "place_base.h" -#include "place_gordian.h" - -#if !defined(NO_HMETIS) -#include "libhmetis.h" -#endif - -// -------------------------------------------------------------------- -// Global variables -// -// -------------------------------------------------------------------- - -Partition *g_place_rootPartition = NULL; -ConcreteNet **allNetsR2 = NULL, - **allNetsL2 = NULL, - **allNetsB2 = NULL, - **allNetsT2 = NULL; - - -// -------------------------------------------------------------------- -// Function prototypes and local data structures -// -// -------------------------------------------------------------------- - -typedef struct FM_cell { - int loc; - int gain; - ConcreteCell *cell; - struct FM_cell *next, *prev; - bool locked; -} FM_cell; - -void FM_updateGains(ConcreteNet *net, int partition, int inc, - FM_cell target [], FM_cell *bin [], - int count_1 [], int count_2 []); - - -// -------------------------------------------------------------------- -// initPartitioning() -// -/// \brief Initializes data structures necessary for partitioning. -// -/// Creates a valid g_place_rootPartition. -/// -// -------------------------------------------------------------------- -void initPartitioning() { - int i; - float area; - - // create root partition - g_place_numPartitions = 1; - if (g_place_rootPartition) free(g_place_rootPartition); - g_place_rootPartition = malloc(sizeof(Partition)); - g_place_rootPartition->m_level = 0; - g_place_rootPartition->m_area = 0; - g_place_rootPartition->m_bounds = g_place_coreBounds; - g_place_rootPartition->m_vertical = false; - g_place_rootPartition->m_done = false; - g_place_rootPartition->m_leaf = true; - - // add all of the cells to this partition - g_place_rootPartition->m_members = malloc(sizeof(ConcreteCell*)*g_place_numCells); - g_place_rootPartition->m_numMembers = 0; - for (i=0; i<g_place_numCells; i++) - if (g_place_concreteCells[i]) { - if (!g_place_concreteCells[i]->m_fixed) { - area = getCellArea(g_place_concreteCells[i]); - g_place_rootPartition->m_members[g_place_rootPartition->m_numMembers++] = - g_place_concreteCells[i]; - g_place_rootPartition->m_area += area; - } - } -} - - -// -------------------------------------------------------------------- -// presortNets() -// -/// \brief Sorts nets by corner positions. -// -/// Allocates allNetsX2 structures. -/// -// -------------------------------------------------------------------- -void presortNets() { - allNetsL2 = (ConcreteNet**)realloc(allNetsL2, sizeof(ConcreteNet*)*g_place_numNets); - allNetsR2 = (ConcreteNet**)realloc(allNetsR2, sizeof(ConcreteNet*)*g_place_numNets); - allNetsB2 = (ConcreteNet**)realloc(allNetsB2, sizeof(ConcreteNet*)*g_place_numNets); - allNetsT2 = (ConcreteNet**)realloc(allNetsT2, sizeof(ConcreteNet*)*g_place_numNets); - memcpy(allNetsL2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); - memcpy(allNetsR2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); - memcpy(allNetsB2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); - memcpy(allNetsT2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); - qsort(allNetsL2, g_place_numNets, sizeof(ConcreteNet*), netSortByL); - qsort(allNetsR2, g_place_numNets, sizeof(ConcreteNet*), netSortByR); - qsort(allNetsB2, g_place_numNets, sizeof(ConcreteNet*), netSortByB); - qsort(allNetsT2, g_place_numNets, sizeof(ConcreteNet*), netSortByT); -} - -// -------------------------------------------------------------------- -// refinePartitions() -// -/// \brief Splits large leaf partitions. -// -// -------------------------------------------------------------------- -bool refinePartitions() { - - return refinePartition(g_place_rootPartition); -} - - -// -------------------------------------------------------------------- -// reallocPartitions() -// -/// \brief Reallocates the partitions based on placement information. -// -// -------------------------------------------------------------------- -void reallocPartitions() { - - reallocPartition(g_place_rootPartition); -} - - -// -------------------------------------------------------------------- -// refinePartition() -// -/// \brief Splits any large leaves within a partition. -// -// -------------------------------------------------------------------- -bool refinePartition(Partition *p) { - bool degenerate = false; - int nonzeroCount = 0; - int i; - - assert(p); - - // is this partition completed? - if (p->m_done) return true; - - // is this partition a non-leaf node? - if (!p->m_leaf) { - p->m_done = refinePartition(p->m_sub1); - p->m_done &= refinePartition(p->m_sub2); - return p->m_done; - } - - // leaf... - // create two new subpartitions - g_place_numPartitions++; - p->m_sub1 = malloc(sizeof(Partition)); - p->m_sub1->m_level = p->m_level+1; - p->m_sub1->m_leaf = true; - p->m_sub1->m_done = false; - p->m_sub1->m_area = 0; - p->m_sub1->m_vertical = !p->m_vertical; - p->m_sub1->m_numMembers = 0; - p->m_sub1->m_members = NULL; - p->m_sub2 = malloc(sizeof(Partition)); - p->m_sub2->m_level = p->m_level+1; - p->m_sub2->m_leaf = true; - p->m_sub2->m_done = false; - p->m_sub2->m_area = 0; - p->m_sub2->m_vertical = !p->m_vertical; - p->m_sub2->m_numMembers = 0; - p->m_sub2->m_members = NULL; - p->m_leaf = false; - - // --- INITIAL PARTITION - - if (PARTITION_AREA_ONLY) - partitionEqualArea(p); - else - partitionScanlineMincut(p); - - resizePartition(p); - - // --- PARTITION IMPROVEMENT - - if (p->m_level < REPARTITION_LEVEL_DEPTH) { - if (REPARTITION_FM) - repartitionFM(p); - else if (REPARTITION_HMETIS) - repartitionHMetis(p); - } - - resizePartition(p); - - // fix imbalances due to zero-area cells - for(i=0; i<p->m_sub1->m_numMembers; i++) - if (p->m_sub1->m_members[i]) - if (getCellArea(p->m_sub1->m_members[i]) > 0) { - nonzeroCount++; - } - - // is this leaf now done? - if (nonzeroCount <= LARGEST_FINAL_SIZE) - p->m_sub1->m_done = true; - if (nonzeroCount == 0) - degenerate = true; - - nonzeroCount = 0; - for(i=0; i<p->m_sub2->m_numMembers; i++) - if (p->m_sub2->m_members[i]) - if (getCellArea(p->m_sub2->m_members[i]) > 0) { - nonzeroCount++; - } - - // is this leaf now done? - if (nonzeroCount <= LARGEST_FINAL_SIZE) - p->m_sub2->m_done = true; - if (nonzeroCount == 0) - degenerate = true; - - // have we found a degenerate partitioning? - if (degenerate) { - printf("QPART-35 : WARNING: degenerate partition generated\n"); - partitionEqualArea(p); - resizePartition(p); - p->m_sub1->m_done = true; - p->m_sub2->m_done = true; - } - - // is this parent now finished? - if (p->m_sub1->m_done && p->m_sub2->m_done) p->m_done = true; - - return p->m_done; -} - - -// -------------------------------------------------------------------- -// repartitionHMetis() -// -/// \brief Repartitions the two subpartitions using the hMetis min-cut library. -/// -/// The number of cut nets between the two partitions will be minimized. -// -// -------------------------------------------------------------------- -void repartitionHMetis(Partition *parent) { -#if defined(NO_HMETIS) - printf("QPAR_02 : \t\tERROR: hMetis not available. Ignoring.\n"); -#else - - int n,c,t, i; - float area; - int *edgeConnections = NULL; - int *partitionAssignment = (int *)calloc(g_place_numCells, sizeof(int)); - int *vertexWeights = (int *)calloc(g_place_numCells, sizeof(int)); - int *edgeDegree = (int *)malloc(sizeof(int)*(g_place_numNets+1)); - int numConnections = 0; - int numEdges = 0; - float initial_cut; - int targets = 0; - ConcreteCell *cell = NULL; - int options[9]; - int afterCuts = 0; - - assert(parent); - assert(parent->m_sub1); - assert(parent->m_sub2); - - printf("QPAR-02 : \t\trepartitioning with hMetis\n"); - - // count edges - edgeDegree[0] = 0; - for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) - if (g_place_concreteNets[n]->m_numTerms > 1) { - numConnections += g_place_concreteNets[n]->m_numTerms; - edgeDegree[++numEdges] = numConnections; - } - - if (parent->m_vertical) { - // vertical - initial_cut = parent->m_sub2->m_bounds.x; - - // initialize all cells - for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) { - if (g_place_concreteCells[c]->m_x < initial_cut) - partitionAssignment[c] = 0; - else - partitionAssignment[c] = 1; - } - - // initialize cells in partition 1 - for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) { - cell = parent->m_sub1->m_members[t]; - vertexWeights[cell->m_id] = getCellArea(cell); - // pay attention to cells that are close to the cut - if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { - targets++; - partitionAssignment[cell->m_id] = -1; - } - } - - // initialize cells in partition 2 - for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) { - cell = parent->m_sub2->m_members[t]; - vertexWeights[cell->m_id] = getCellArea(cell); - // pay attention to cells that are close to the cut - if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { - targets++; - partitionAssignment[cell->m_id] = -1; - } - } - - } else { - // horizontal - initial_cut = parent->m_sub2->m_bounds.y; - - // initialize all cells - for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) { - if (g_place_concreteCells[c]->m_y < initial_cut) - partitionAssignment[c] = 0; - else - partitionAssignment[c] = 1; - } - - // initialize cells in partition 1 - for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) { - cell = parent->m_sub1->m_members[t]; - vertexWeights[cell->m_id] = getCellArea(cell); - // pay attention to cells that are close to the cut - if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { - targets++; - partitionAssignment[cell->m_id] = -1; - } - } - - // initialize cells in partition 2 - for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) { - cell = parent->m_sub2->m_members[t]; - vertexWeights[cell->m_id] = getCellArea(cell); - // pay attention to cells that are close to the cut - if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { - targets++; - partitionAssignment[cell->m_id] = -1; - } - } - } - - options[0] = 1; // any non-default values? - options[1] = 3; // num bisections - options[2] = 1; // grouping scheme - options[3] = 1; // refinement scheme - options[4] = 1; // cycle refinement scheme - options[5] = 0; // reconstruction scheme - options[6] = 0; // fixed assignments? - options[7] = 12261980; // random seed - options[8] = 0; // debugging level - - edgeConnections = (int *)malloc(sizeof(int)*numConnections); - - i = 0; - for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) { - if (g_place_concreteNets[n]->m_numTerms > 1) - for(t=0; t<g_place_concreteNets[n]->m_numTerms; t++) - edgeConnections[i++] = g_place_concreteNets[n]->m_terms[t]->m_id; - } - - HMETIS_PartRecursive(g_place_numCells, numEdges, vertexWeights, - edgeDegree, edgeConnections, NULL, - 2, (int)(100*MAX_PARTITION_NONSYMMETRY), - options, partitionAssignment, &afterCuts); - - /* - printf("HMET-20 : \t\t\tbalance before %d / %d ... ", parent->m_sub1->m_numMembers, - parent->m_sub2->m_numMembers); - */ - - // reassign members to subpartitions - parent->m_sub1->m_numMembers = 0; - parent->m_sub1->m_area = 0; - parent->m_sub2->m_numMembers = 0; - parent->m_sub2->m_area = 0; - parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members, - sizeof(ConcreteCell*)*parent->m_numMembers); - parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members, - sizeof(ConcreteCell*)*parent->m_numMembers); - - for(t=0; t<parent->m_numMembers; t++) if (parent->m_members[t]) { - cell = parent->m_members[t]; - area = getCellArea(cell); - if (partitionAssignment[cell->m_id] == 0) { - parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = cell; - parent->m_sub1->m_area += area; - } - else { - parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = cell; - parent->m_sub2->m_area += area; - } - } - /* - printf("after %d / %d\n", parent->m_sub1->m_numMembers, - parent->m_sub2->m_numMembers); - */ - - // cout << "HMET-21 : \t\t\tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl; - // cout << "HMET-22 : \t\t\tstarting cuts= " << beforeCuts << " final cuts= " << afterCuts << endl; - - free(edgeConnections); - free(vertexWeights); - free(edgeDegree); - free(partitionAssignment); -#endif -} - - -// -------------------------------------------------------------------- -// repartitionFM() -// -/// \brief Fiduccia-Matheyses mincut partitioning algorithm. -// -/// UNIMPLEMENTED (well, un-C-ified) -// -// -------------------------------------------------------------------- -void repartitionFM(Partition *parent) { -#if 0 - assert(!parent->leaf && parent->m_sub1->leaf && parent->m_sub2->leaf); - - // count of each net's number of cells in each bipartition - int count_1[m_design->nets.length()]; - memset(count_1, 0, sizeof(int)*m_design->nets.length()); - int count_2[m_design->nets.length()]; - memset(count_2, 0, sizeof(int)*m_design->nets.length()); - - FM_cell target[m_design->cells.length()]; - memset(target, 0, sizeof(FM_cell)*m_design->cells.length()); - FM_cell *bin[FM_MAX_BIN+1]; - FM_cell *locked = 0; - memset(bin, 0, sizeof(FM_cell *)*(FM_MAX_BIN+1)); - - int max_gain = 0; - int before_cuts = 0, current_cuts = 0; - double initial_cut; - int targets = 0; - long cell_id; - double halfArea = parent->m_area / 2.0; - double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY; - ConcreteNet *net; - - // INITIALIZATION - // select cells to partition - - if (parent->vertical) { - // vertical - - initial_cut = parent->m_sub2->m_bounds.x; - - // initialize all cells - for(h::list<ConcreteCell *>::iterator it = rootPartition->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - if ((*it)->temp_x < initial_cut) - target[cell_id].loc = -1; - else - target[cell_id].loc = -2; - target[cell_id].cell = *it; - target[cell_id].gain = 0; - } - - // initialize cells in partition 1 - for(h::list<ConcreteCell *>::iterator it = parent->m_sub1->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - // pay attention to cells that are close to the cut - if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { - targets++; - target[cell_id].loc = 1; - } - } - - // initialize cells in partition 2 - for(h::list<ConcreteCell *>::iterator it = parent->m_sub2->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - // pay attention to cells that are close to the cut - if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { - targets++; - target[cell_id].loc = 2; - } - } - - // count the number of cells on each side of the partition for every net - for(h::hash_map<ConcreteNet *>::iterator n_it = m_design->nets.begin(); !n_it; n_it++) { - for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++) - if (abs(target[(*p_it)->getCell()->getID()].loc) == 1) - count_1[net->getID()]++; - else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2) - count_2[net->getID()]++; - else if ((*p_it)->getCell()->temp_x < initial_cut) - count_1[net->getID()]++; - else - count_2[net->getID()]++; - if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++; - } - - } else { - // horizontal - - initial_cut = parent->m_sub2->m_bounds.y; - - // initialize all cells - for(h::list<ConcreteCell *>::iterator it = rootPartition->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - if ((*it)->temp_y < initial_cut) - target[cell_id].loc = -1; - else - target[cell_id].loc = -2; - target[cell_id].cell = *it; - target[cell_id].gain = 0; - } - - // initialize cells in partition 1 - for(h::list<ConcreteCell *>::iterator it = parent->m_sub1->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - // pay attention to cells that are close to the cut - if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { - targets++; - target[cell_id].loc = 1; - } - } - - // initialize cells in partition 2 - for(h::list<ConcreteCell *>::iterator it = parent->m_sub2->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - // pay attention to cells that are close to the cut - if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { - targets++; - target[cell_id].loc = 2; - } - } - - // count the number of cells on each side of the partition for every net - for(h::hash_map<ConcreteNet *>::iterator n_it = m_design->nets.begin(); !n_it; n_it++) { - for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++) - if (abs(target[(*p_it)->getCell()->getID()].loc) == 1) - count_1[net->getID()]++; - else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2) - count_2[net->getID()]++; - else if ((*p_it)->getCell()->temp_y < initial_cut) - count_1[net->getID()]++; - else - count_2[net->getID()]++; - if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++; - } - } - - // INITIAL GAIN CALCULATION - for(long id=0; id < m_design->cells.length(); id++) - if (target[id].loc > 0) { - assert(target[id].cell != 0); - assert(target[id].gain == 0); - - // examine counts for the net on each pin - for(ConcretePinMap::iterator p_it = target[id].cell->getPins().begin(); !p_it; p_it++) - if ((*p_it)->isAttached()) { - int n_id = (*p_it)->getNet()->getID(); - if (target[id].loc == 1 && count_1[n_id] == 1) target[id].gain++; - if (target[id].loc == 1 && count_2[n_id] == 0) target[id].gain--; - if (target[id].loc == 2 && count_1[n_id] == 0) target[id].gain--; - if (target[id].loc == 2 && count_2[n_id] == 1) target[id].gain++; - } - - assert(target[id].cell->getPins().length() >= abs(target[id].gain)); - - // add it to a bin - int bin_num = min(max(0, target[id].gain),FM_MAX_BIN); - max_gain = max(max_gain, bin_num); - - assert(bin_num >= 0 && bin_num <= FM_MAX_BIN); - target[id].next = bin[bin_num]; - target[id].prev = 0; - if (bin[bin_num] != 0) - bin[bin_num]->prev = &target[id]; - bin[bin_num] = &target[id]; - } - - // OUTER F-M LOOP - current_cuts = before_cuts; - int num_moves = 1; - int pass = 0; - while(num_moves > 0 && pass < FM_MAX_PASSES) { - pass++; - num_moves = 0; - - // check_list(bin, locked, targets); // DEBUG - - // move all locked cells back - int moved_back = 0; - while(locked != 0) { - FM_cell *current = locked; - current->locked = false; - - int bin_num = min(max(0, current->gain),FM_MAX_BIN); - max_gain = max(max_gain, bin_num); - - locked = current->next; - if (locked != 0) - locked->prev = 0; - - if (bin[bin_num] != 0) - bin[bin_num]->prev = current; - current->next = bin[bin_num]; - bin[bin_num] = current; - - moved_back++; - } - // cout << "\tmoved back: " << moved_back << endl; - // check_list(bin, locked, targets); // DEBUG - - max_gain = FM_MAX_BIN; - while(bin[max_gain] == 0 && max_gain > 0) max_gain--; - - // INNER F-M LOOP (single pass) - while(1) { - - int bin_num = FM_MAX_BIN; - FM_cell *current = bin[bin_num]; - - // look for next cell to move - while (bin_num > 0 && (current == 0 || - (current->loc==1 && current->cell->getArea()+parent->m_sub2->m_area > halfArea+areaFlexibility) || - (current->loc==2 && current->cell->getArea()+parent->m_sub1->m_area > halfArea+areaFlexibility))) { - - if (current == 0) current = bin[--bin_num]; else current = current->next; - } - if (bin_num == 0) - break; - - num_moves++; - current->locked = true; - // cout << "moving cell " << current->cell->getID() << " gain=" << current->gain << " pins= " << current->cell->getPins().length() << " from " << current->loc; - - // change partition marking and areas - if (current->loc == 1) { - current->loc = 2; - parent->m_sub1->m_area -= current->cell->getArea(); - parent->m_sub2->m_area += current->cell->getArea(); - - // update partition counts on all nets attached to this cell - for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); - !p_it; p_it++) { - - if (!(*p_it)->isAttached()) // ignore unattached pins - continue; - net = (*p_it)->getNet(); - - count_1[net->getID()]--; - count_2[net->getID()]++; - - // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]+1 << "/" << count_2[net->getID()]-1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl; - - // if net becomes critical, update gains on attached cells and resort bins - if (count_1[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); } - if (count_2[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); } - - // check_list(bin, locked, targets); // DEBUG - } - - } else { - current->loc = 1; - parent->m_sub2->m_area -= current->cell->getArea(); - parent->m_sub1->m_area += current->cell->getArea(); - - // update gains on all nets attached to this cell - for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); - !p_it; p_it++) { - - if (!(*p_it)->isAttached()) // ignore unattached pins - continue; - net = (*p_it)->getNet(); - count_2[net->getID()]--; - count_1[net->getID()]++; - - // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]-1 << "/" << count_2[net->getID()]+1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl; - - if (count_2[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); } - if (count_1[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); } - - // check_list(bin, locked, targets); // DEBUG - } - } - - //cout << " cuts=" << current_cuts << endl; - - // move current to locked - -/* - cout << "b=" << bin[bin_num] << " "; - cout << current->prev << "-> "; - if (current->prev == 0) - cout << "X"; - else cout << current->prev->next; - cout << "=" << current << "="; - if (current->next == 0) - cout << "X"; - else - cout << current->next->prev; - cout << " ->" << current->next << endl; -*/ - - if (bin[bin_num] == current) - bin[bin_num] = current->next; - if (current->prev != 0) - current->prev->next = current->next; - if (current->next != 0) - current->next->prev = current->prev; - -/* - cout << "b=" << bin[bin_num] << " "; - cout << current->prev << "-> "; - if (current->prev == 0) - cout << "X"; - else cout << current->prev->next; - cout << "=" << current << "="; - if (current->next == 0) - cout << "X"; - else - cout << current->next->prev; - cout << " ->" << current->next << endl; -*/ - - current->prev = 0; - current->next = locked; - if (locked != 0) - locked->prev = current; - locked = current; - - // check_list(bin, locked, targets); // DEBUG - - // update max_gain - max_gain = FM_MAX_BIN; - while(bin[max_gain] == 0 && max_gain > 0) max_gain--; - } - - // cout << "\tcurrent cuts= " << current_cuts << " moves= " << num_moves << endl; - } - - // reassign members to subpartitions - cout << "FIDM-20 : \tbalance before " << parent->m_sub1->m_members.length() << "/" - << parent->m_sub2->m_members.length() << " "; - parent->m_sub1->m_members.clear(); - parent->m_sub1->m_area = 0; - parent->m_sub2->m_members.clear(); - parent->m_sub2->m_area = 0; - for(h::list<ConcreteCell *>::iterator it = parent->m_members.begin(); !it; it++) { - if (target[(*it)->getID()].loc == 1 || target[(*it)->getID()].loc == -1) { - parent->m_sub1->m_members.push_back(*it); - parent->m_sub1->m_area += (*it)->getArea(); - } - else { - parent->m_sub2->m_members.push_back(*it); - parent->m_sub2->m_area += (*it)->getArea(); - } - } - cout << " after " << parent->m_sub1->m_members.length() << "/" - << parent->m_sub2->m_members.length() << endl; - - - cout << "FIDM-21 : \tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl; - cout << "FIDM-22 : \tstarting cuts= " << before_cuts << " final cuts= " << current_cuts << endl; -#endif -} - -// ----- FM_updateGains() -// moves a cell between bins -#if 0 -void FM_updateGains(ConcreteNet *net, int partition, int inc, - FM_cell target [], FM_cell *bin [], - int count_1 [], int count_2 []) { - - for(ConcretePinList::iterator it = net->getPins().begin(); !it; it++) { - FM_cell *current = &(target[(*it)->getCell()->getID()]); - assert(current->cell != 0); - - int old_gain = current->gain; - current->gain = 0; - - // examine counts for the net on each pin - for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); !p_it; p_it++) - if ((*p_it)->isAttached()) { - int n_id = (*p_it)->getNet()->getID(); - if (current->loc == 1 && count_1[n_id] == 1) current->gain++; - if (current->loc == 1 && count_2[n_id] == 0) current->gain--; - if (current->loc == 2 && count_1[n_id] == 0) current->gain--; - if (current->loc == 2 && count_2[n_id] == 1) current->gain++; - } - - if (!current->locked) { - // remove cell from existing bin - int bin_num = min(max(0, old_gain),FM_MAX_BIN); - if (bin[bin_num] == current) - bin[bin_num] = current->next; - if (current->prev != 0) - current->prev->next = current->next; - if (current->next != 0) - current->next->prev = current->prev; - // add cell to correct bin - bin_num = min(max(0, current->gain),FM_MAX_BIN); - current->prev = 0; - current->next = bin[bin_num]; - if (bin[bin_num] != 0) - bin[bin_num]->prev = current; - bin[bin_num] = current; - } - } - -} -#endif - - -// -------------------------------------------------------------------- -// partitionEqualArea() -// -/// \brief Splits a partition into two halves of equal area. -// -// -------------------------------------------------------------------- -void partitionEqualArea(Partition *parent) { - float halfArea, area; - int i=0; - - // which way to sort? - if (parent->m_vertical) - // sort by X position - qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByX); - else - // sort by Y position - qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByY); - - // split the list - halfArea = parent->m_area*0.5; - parent->m_sub1->m_area = 0.0; - parent->m_sub1->m_numMembers = 0; - parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members, - sizeof(ConcreteCell*)*parent->m_numMembers); - parent->m_sub2->m_area = 0.0; - parent->m_sub2->m_numMembers = 0; - parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members, - sizeof(ConcreteCell*)*parent->m_numMembers); - - for(; parent->m_sub1->m_area < halfArea; i++) - if (parent->m_members[i]) { - area = getCellArea(parent->m_members[i]); - parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = parent->m_members[i]; - parent->m_sub1->m_area += area; - } - for(; i<parent->m_numMembers; i++) - if (parent->m_members[i]) { - area = getCellArea(parent->m_members[i]); - parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = parent->m_members[i]; - parent->m_sub2->m_area += area; - } - -} - - -// -------------------------------------------------------------------- -// partitionScanlineMincut() -// -/// \brief Scans the cells within a partition from left to right and chooses the min-cut. -// -// -------------------------------------------------------------------- -void partitionScanlineMincut(Partition *parent) { -#if 0 - int current_cuts = 0; - int minimum_cuts = INT_MAX; - ConcreteCell *minimum_location = NULL; - double currentArea = 0, halfArea = parent->m_area * 0.5; - double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY; - double newLine, oldLine = -DBL_MAX; - - for(ConcreteNetList::iterator n_it = m_design->nets.begin(); !n_it; n_it++) - (*n_it)->m_mark = 0; - for(h::list<ConcreteCell *>::iterator i = parent->m_members.begin(); - !i.isDone(); i++) { - assert(*i); - for(ConcretePinMap::iterator j = (*i)->getPins().begin(); - !j.isDone(); j++) { - assert(*j); - if((*j)->isAttached()) { - (*j)->getNet()->m_mark = 1; - } - } - } - - if (parent->vertical) { - parent->m_members.sort(sortByX); - int all1 = 0, all2 = 0; - h::list<ConcreteCell *>::iterator local = parent->m_members.begin(); - for(; !local.isDone(); local++) { - currentArea += (*local)->getArea(); - if (currentArea < halfArea-areaFlexibility) - continue; - if (currentArea > halfArea+areaFlexibility) - break; - newLine = (*local)->temp_x; - while(all1 < g_place_numNets && allNetsL2[all1]->getBoundingBox().left() <= newLine) { - if(allNetsL2[all1]->m_mark) { - current_cuts++; - } - all1++; - } - while(all2 < g_place_numNets && allNetsR2[all2]->getBoundingBox().right() <= newLine) { - if(allNetsR2[all2]->m_mark) { - current_cuts--; - } - all2++; - } - if (current_cuts < minimum_cuts) { - minimum_cuts = current_cuts; - minimum_location = *local; - } - oldLine = newLine; - } - } - else { - parent->m_members.sort(sortByY); - int all1 = 0, all2 = 0; - h::list<ConcreteCell *>::iterator local = parent->m_members.begin(); - for(; !local.isDone(); local++) { - currentArea += (*local)->getArea(); - if (currentArea < halfArea-areaFlexibility) - continue; - if (currentArea > halfArea+areaFlexibility) - break; - newLine = (*local)->temp_y; - while(all1 < g_place_numNets && allNetsB2[all1]->getBoundingBox().top() <= newLine) { - if(allNetsB2[all1]->m_mark) { - current_cuts++; - } - all1++; - } - while(all2 < g_place_numNets && allNetsT2[all2]->getBoundingBox().bottom() <= newLine) { - if(allNetsT2[all2]->m_mark) { - current_cuts--; - } - all2++; - } - if (current_cuts < minimum_cuts) { - minimum_cuts = current_cuts; - minimum_location = *local; - } - oldLine = newLine; - } - } - if (minimum_location == NULL) { - return partitionEqualArea(parent); - } - h::list<ConcreteCell *>::iterator it = parent->m_members.begin(); - parent->m_sub1->m_members.clear(); - parent->m_sub1->m_area = 0; - for(; *it != minimum_location; it++) { - parent->m_sub1->m_members.push_front(*it); - parent->m_sub1->m_area += (*it)->getArea(); - } - parent->m_sub2->m_members.clear(); - parent->m_sub2->m_area = 0; - for(; !it; it++) { - parent->m_sub2->m_members.push_front(*it); - parent->m_sub2->m_area += (*it)->getArea(); - } -#endif -} - - -// -------------------------------------------------------------------- -// reallocPartition() -// -/// \brief Reallocates a partition and all of its children. -// -// -------------------------------------------------------------------- -void reallocPartition(Partition *p) { - - if (p->m_leaf) { - return; - } - - // --- INITIAL PARTITION - - if (PARTITION_AREA_ONLY) - partitionEqualArea(p); - else - partitionScanlineMincut(p); - - resizePartition(p); - - // --- PARTITION IMPROVEMENT - if (p->m_level < REPARTITION_LEVEL_DEPTH) { - if (REPARTITION_HMETIS) - repartitionHMetis(p); - - resizePartition(p); - } - - reallocPartition(p->m_sub1); - reallocPartition(p->m_sub2); -} - - -// -------------------------------------------------------------------- -// resizePartition() -// -/// \brief Recomputes the bounding boxes of the child partitions based on their relative areas. -// -// -------------------------------------------------------------------- -void resizePartition(Partition *p) { - // compute the new bounding box - p->m_sub1->m_bounds.x = p->m_bounds.x; - p->m_sub1->m_bounds.y = p->m_bounds.y; - if (p->m_vertical) { - p->m_sub1->m_bounds.w = p->m_bounds.w*(p->m_sub1->m_area/p->m_area); - p->m_sub1->m_bounds.h = p->m_bounds.h; - p->m_sub2->m_bounds.x = p->m_bounds.x + p->m_sub1->m_bounds.w; - p->m_sub2->m_bounds.w = p->m_bounds.w*(p->m_sub2->m_area/p->m_area); - p->m_sub2->m_bounds.y = p->m_bounds.y; - p->m_sub2->m_bounds.h = p->m_bounds.h; - } else { - p->m_sub1->m_bounds.h = p->m_bounds.h*(p->m_sub1->m_area/p->m_area); - p->m_sub1->m_bounds.w = p->m_bounds.w; - p->m_sub2->m_bounds.y = p->m_bounds.y + p->m_sub1->m_bounds.h; - p->m_sub2->m_bounds.h = p->m_bounds.h*(p->m_sub2->m_area/p->m_area); - p->m_sub2->m_bounds.x = p->m_bounds.x; - p->m_sub2->m_bounds.w = p->m_bounds.w; - } -} - - -// -------------------------------------------------------------------- -// incrementalSubpartition() -// -/// \brief Adds new cells to an existing partition. Partition sizes/locations are unchanged. -/// -/// The function recurses, adding new cells to appropriate subpartitions. -// -// -------------------------------------------------------------------- -void incrementalSubpartition(Partition *p, ConcreteCell *newCells [], const int numNewCells) { - int c; - ConcreteCell **newCells1 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells), - **newCells2 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells); - int numNewCells1 = 0, numNewCells2 = 0; - float cut_loc; - - assert(p); - - // add new cells to partition list - p->m_members = (ConcreteCell**)realloc(p->m_members, - sizeof(ConcreteCell*)*(p->m_numMembers+numNewCells)); - memcpy(&(p->m_members[p->m_numMembers]), newCells, sizeof(ConcreteCell*)*numNewCells); - p->m_numMembers += numNewCells; - - // if is a leaf partition, finished - if (p->m_leaf) return; - - // split new cells into sub-partitions based on location - if (p->m_vertical) { - cut_loc = p->m_sub2->m_bounds.x; - for(c=0; c<numNewCells; c++) - if (newCells[c]->m_x < cut_loc) - newCells1[numNewCells1++] = newCells[c]; - else - newCells2[numNewCells2++] = newCells[c]; - } else { - cut_loc = p->m_sub2->m_bounds.y; - for(c=0; c<numNewCells; c++) - if (newCells[c]->m_y < cut_loc) - newCells1[numNewCells1++] = newCells[c]; - else - newCells2[numNewCells2++] = newCells[c]; - } - - if (numNewCells1 > 0) incrementalSubpartition(p->m_sub1, newCells1, numNewCells1); - if (numNewCells2 > 0) incrementalSubpartition(p->m_sub2, newCells2, numNewCells2); - - free(newCells1); - free(newCells2); -} - - -// -------------------------------------------------------------------- -// incrementalPartition() -// -/// \brief Adds new cells to an existing partition. Partition sizes/locations are unchanged. -/// -/// The function recurses, adding new cells to appropriate subpartitions. -// -// -------------------------------------------------------------------- -void incrementalPartition() { - int c = 0, c2 = 0; - int numNewCells = 0; - ConcreteCell **allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells), - **newCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); - - assert(g_place_rootPartition); - - // update cell list of root partition - memcpy(allCells, g_place_concreteCells, sizeof(ConcreteCell*)*g_place_numCells); - qsort(allCells, g_place_numCells, sizeof(ConcreteCell*), cellSortByID); - qsort(g_place_rootPartition->m_members, g_place_rootPartition->m_numMembers, - sizeof(ConcreteCell*), cellSortByID); - - // scan sorted lists and collect cells not in partitions - while(!allCells[c++]); - while(!g_place_rootPartition->m_members[c2++]); - - for(; c<g_place_numCells; c++, c2++) { - while(c2 < g_place_rootPartition->m_numMembers && - allCells[c]->m_id > g_place_rootPartition->m_members[c2]->m_id) c2++; - while(c < g_place_numCells && - (c2 >= g_place_rootPartition->m_numMembers || - allCells[c]->m_id < g_place_rootPartition->m_members[c2]->m_id)) { - // a new cell! - newCells[numNewCells++] = allCells[c]; - c++; - } - } - - printf("QPRT-50 : \tincremental partitioning with %d new cells\n", numNewCells); - if (numNewCells>0) incrementalSubpartition(g_place_rootPartition, newCells, numNewCells); - - free(allCells); - free(newCells); -} |