ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
place_partition.c
Go to the documentation of this file.
1/*===================================================================*/
2//
3// place_partition.c
4//
5// Aaron P. Hurst, 2003-2007
6// ahurst@eecs.berkeley.edu
7//
8/*===================================================================*/
9
10#include <stdlib.h>
11#include <math.h>
12#include <string.h>
13#include <stdio.h>
14#include <limits.h>
15#include <assert.h>
16//#include <sys/stat.h>
17//#include <unistd.h>
18
19#include "place_base.h"
20#include "place_gordian.h"
21
22#if !defined(NO_HMETIS)
23#include "libhmetis.h"
24
26
27#endif
28
29// --------------------------------------------------------------------
30// Global variables
31//
32// --------------------------------------------------------------------
33
36 **allNetsL2 = NULL,
37 **allNetsB2 = NULL,
38 **allNetsT2 = NULL;
39
40
41// --------------------------------------------------------------------
42// Function prototypes and local data structures
43//
44// --------------------------------------------------------------------
45
46typedef struct FM_cell {
47 int loc;
48 int gain;
50 struct FM_cell *next, *prev;
51 bool locked;
53
54void FM_updateGains(ConcreteNet *net, int partition, int inc,
55 FM_cell target [], FM_cell *bin [],
56 int count_1 [], int count_2 []);
57
58
59// --------------------------------------------------------------------
60// initPartitioning()
61//
63//
66// --------------------------------------------------------------------
68 int i;
69 float area;
70
71 // create root partition
75 g_place_rootPartition->m_level = 0;
76 g_place_rootPartition->m_area = 0;
78 g_place_rootPartition->m_vertical = false;
79 g_place_rootPartition->m_done = false;
80 g_place_rootPartition->m_leaf = true;
81
82 // add all of the cells to this partition
84 g_place_rootPartition->m_numMembers = 0;
85 for (i=0; i<g_place_numCells; i++)
86 if (g_place_concreteCells[i]) {
87 if (!g_place_concreteCells[i]->m_fixed) {
89 g_place_rootPartition->m_members[g_place_rootPartition->m_numMembers++] =
91 g_place_rootPartition->m_area += area;
92 }
93 }
94}
95
96
97// --------------------------------------------------------------------
98// presortNets()
99//
101//
104// --------------------------------------------------------------------
119
120// --------------------------------------------------------------------
121// refinePartitions()
122//
124//
125// --------------------------------------------------------------------
130
131
132// --------------------------------------------------------------------
133// reallocPartitions()
134//
136//
137// --------------------------------------------------------------------
142
143
144// --------------------------------------------------------------------
145// refinePartition()
146//
148//
149// --------------------------------------------------------------------
151 bool degenerate = false;
152 int nonzeroCount = 0;
153 int i;
154
155 assert(p);
156
157 // is this partition completed?
158 if (p->m_done) return true;
159
160 // is this partition a non-leaf node?
161 if (!p->m_leaf) {
162 p->m_done = refinePartition(p->m_sub1);
163 p->m_done &= refinePartition(p->m_sub2);
164 return p->m_done;
165 }
166
167 // leaf...
168 // create two new subpartitions
170 p->m_sub1 = malloc(sizeof(Partition));
171 p->m_sub1->m_level = p->m_level+1;
172 p->m_sub1->m_leaf = true;
173 p->m_sub1->m_done = false;
174 p->m_sub1->m_area = 0;
175 p->m_sub1->m_vertical = !p->m_vertical;
176 p->m_sub1->m_numMembers = 0;
177 p->m_sub1->m_members = NULL;
178 p->m_sub2 = malloc(sizeof(Partition));
179 p->m_sub2->m_level = p->m_level+1;
180 p->m_sub2->m_leaf = true;
181 p->m_sub2->m_done = false;
182 p->m_sub2->m_area = 0;
183 p->m_sub2->m_vertical = !p->m_vertical;
184 p->m_sub2->m_numMembers = 0;
185 p->m_sub2->m_members = NULL;
186 p->m_leaf = false;
187
188 // --- INITIAL PARTITION
189
192 else
194
196
197 // --- PARTITION IMPROVEMENT
198
199 if (p->m_level < REPARTITION_LEVEL_DEPTH) {
200 if (REPARTITION_FM)
202 else if (REPARTITION_HMETIS)
204 }
205
207
208 // fix imbalances due to zero-area cells
209 for(i=0; i<p->m_sub1->m_numMembers; i++)
210 if (p->m_sub1->m_members[i])
211 if (getCellArea(p->m_sub1->m_members[i]) > 0) {
212 nonzeroCount++;
213 }
214
215 // is this leaf now done?
216 if (nonzeroCount <= LARGEST_FINAL_SIZE)
217 p->m_sub1->m_done = true;
218 if (nonzeroCount == 0)
219 degenerate = true;
220
221 nonzeroCount = 0;
222 for(i=0; i<p->m_sub2->m_numMembers; i++)
223 if (p->m_sub2->m_members[i])
224 if (getCellArea(p->m_sub2->m_members[i]) > 0) {
225 nonzeroCount++;
226 }
227
228 // is this leaf now done?
229 if (nonzeroCount <= LARGEST_FINAL_SIZE)
230 p->m_sub2->m_done = true;
231 if (nonzeroCount == 0)
232 degenerate = true;
233
234 // have we found a degenerate partitioning?
235 if (degenerate) {
236 printf("QPART-35 : WARNING: degenerate partition generated\n");
239 p->m_sub1->m_done = true;
240 p->m_sub2->m_done = true;
241 }
242
243 // is this parent now finished?
244 if (p->m_sub1->m_done && p->m_sub2->m_done) p->m_done = true;
245
246 return p->m_done;
247}
248
249
250// --------------------------------------------------------------------
251// repartitionHMetis()
252//
256//
257// --------------------------------------------------------------------
259#if defined(NO_HMETIS)
260 printf("QPAR_02 : \t\tERROR: hMetis not available. Ignoring.\n");
261#else
262
263 int n,c,t, i;
264 float area;
265 int *edgeConnections = NULL;
266 int *partitionAssignment = (int *)calloc(g_place_numCells, sizeof(int));
267 int *vertexWeights = (int *)calloc(g_place_numCells, sizeof(int));
268 int *edgeDegree = (int *)malloc(sizeof(int)*(g_place_numNets+1));
269 int numConnections = 0;
270 int numEdges = 0;
271 float initial_cut;
272 int targets = 0;
273 ConcreteCell *cell = NULL;
274 int options[9];
275 int afterCuts = 0;
276
277 assert(parent);
278 assert(parent->m_sub1);
279 assert(parent->m_sub2);
280
281 printf("QPAR-02 : \t\trepartitioning with hMetis\n");
282
283 // count edges
284 edgeDegree[0] = 0;
285 for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n])
286 if (g_place_concreteNets[n]->m_numTerms > 1) {
287 numConnections += g_place_concreteNets[n]->m_numTerms;
288 edgeDegree[++numEdges] = numConnections;
289 }
290
291 if (parent->m_vertical) {
292 // vertical
293 initial_cut = parent->m_sub2->m_bounds.x;
294
295 // initialize all cells
296 for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
297 if (g_place_concreteCells[c]->m_x < initial_cut)
298 partitionAssignment[c] = 0;
299 else
300 partitionAssignment[c] = 1;
301 }
302
303 // initialize cells in partition 1
304 for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) {
305 cell = parent->m_sub1->m_members[t];
306 vertexWeights[cell->m_id] = getCellArea(cell);
307 // pay attention to cells that are close to the cut
308 if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
309 targets++;
310 partitionAssignment[cell->m_id] = -1;
311 }
312 }
313
314 // initialize cells in partition 2
315 for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) {
316 cell = parent->m_sub2->m_members[t];
317 vertexWeights[cell->m_id] = getCellArea(cell);
318 // pay attention to cells that are close to the cut
319 if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
320 targets++;
321 partitionAssignment[cell->m_id] = -1;
322 }
323 }
324
325 } else {
326 // horizontal
327 initial_cut = parent->m_sub2->m_bounds.y;
328
329 // initialize all cells
330 for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
331 if (g_place_concreteCells[c]->m_y < initial_cut)
332 partitionAssignment[c] = 0;
333 else
334 partitionAssignment[c] = 1;
335 }
336
337 // initialize cells in partition 1
338 for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) {
339 cell = parent->m_sub1->m_members[t];
340 vertexWeights[cell->m_id] = getCellArea(cell);
341 // pay attention to cells that are close to the cut
342 if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
343 targets++;
344 partitionAssignment[cell->m_id] = -1;
345 }
346 }
347
348 // initialize cells in partition 2
349 for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) {
350 cell = parent->m_sub2->m_members[t];
351 vertexWeights[cell->m_id] = getCellArea(cell);
352 // pay attention to cells that are close to the cut
353 if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
354 targets++;
355 partitionAssignment[cell->m_id] = -1;
356 }
357 }
358 }
359
360 options[0] = 1; // any non-default values?
361 options[1] = 3; // num bisections
362 options[2] = 1; // grouping scheme
363 options[3] = 1; // refinement scheme
364 options[4] = 1; // cycle refinement scheme
365 options[5] = 0; // reconstruction scheme
366 options[6] = 0; // fixed assignments?
367 options[7] = 12261980; // random seed
368 options[8] = 0; // debugging level
369
370 edgeConnections = (int *)malloc(sizeof(int)*numConnections);
371
372 i = 0;
373 for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
374 if (g_place_concreteNets[n]->m_numTerms > 1)
375 for(t=0; t<g_place_concreteNets[n]->m_numTerms; t++)
376 edgeConnections[i++] = g_place_concreteNets[n]->m_terms[t]->m_id;
377 }
378
379 HMETIS_PartRecursive(g_place_numCells, numEdges, vertexWeights,
380 edgeDegree, edgeConnections, NULL,
381 2, (int)(100*MAX_PARTITION_NONSYMMETRY),
382 options, partitionAssignment, &afterCuts);
383
384 /*
385 printf("HMET-20 : \t\t\tbalance before %d / %d ... ", parent->m_sub1->m_numMembers,
386 parent->m_sub2->m_numMembers);
387 */
388
389 // reassign members to subpartitions
390 parent->m_sub1->m_numMembers = 0;
391 parent->m_sub1->m_area = 0;
392 parent->m_sub2->m_numMembers = 0;
393 parent->m_sub2->m_area = 0;
394 parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members,
395 sizeof(ConcreteCell*)*parent->m_numMembers);
396 parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members,
397 sizeof(ConcreteCell*)*parent->m_numMembers);
398
399 for(t=0; t<parent->m_numMembers; t++) if (parent->m_members[t]) {
400 cell = parent->m_members[t];
401 area = getCellArea(cell);
402 if (partitionAssignment[cell->m_id] == 0) {
403 parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = cell;
404 parent->m_sub1->m_area += area;
405 }
406 else {
407 parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = cell;
408 parent->m_sub2->m_area += area;
409 }
410 }
411 /*
412 printf("after %d / %d\n", parent->m_sub1->m_numMembers,
413 parent->m_sub2->m_numMembers);
414 */
415
416 // cout << "HMET-21 : \t\t\tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl;
417 // cout << "HMET-22 : \t\t\tstarting cuts= " << beforeCuts << " final cuts= " << afterCuts << endl;
418
419 free(edgeConnections);
420 free(vertexWeights);
421 free(edgeDegree);
422 free(partitionAssignment);
423#endif
424}
425
426
427// --------------------------------------------------------------------
428// repartitionFM()
429//
431//
433//
434// --------------------------------------------------------------------
436#if 0
437 assert(!parent->leaf && parent->m_sub1->leaf && parent->m_sub2->leaf);
438
439 // count of each net's number of cells in each bipartition
440 int count_1[m_design->nets.length()];
441 memset(count_1, 0, sizeof(int)*m_design->nets.length());
442 int count_2[m_design->nets.length()];
443 memset(count_2, 0, sizeof(int)*m_design->nets.length());
444
445 FM_cell target[m_design->cells.length()];
446 memset(target, 0, sizeof(FM_cell)*m_design->cells.length());
447 FM_cell *bin[FM_MAX_BIN+1];
448 FM_cell *locked = 0;
449 memset(bin, 0, sizeof(FM_cell *)*(FM_MAX_BIN+1));
450
451 int max_gain = 0;
452 int before_cuts = 0, current_cuts = 0;
453 double initial_cut;
454 int targets = 0;
455 long cell_id;
456 double halfArea = parent->m_area / 2.0;
457 double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY;
458 ConcreteNet *net;
459
460 // INITIALIZATION
461 // select cells to partition
462
463 if (parent->vertical) {
464 // vertical
465
466 initial_cut = parent->m_sub2->m_bounds.x;
467
468 // initialize all cells
469 for(h::list<ConcreteCell *>::iterator it = rootPartition->m_members.begin(); !it; it++) {
470 cell_id = (*it)->getID();
471 if ((*it)->temp_x < initial_cut)
472 target[cell_id].loc = -1;
473 else
474 target[cell_id].loc = -2;
475 target[cell_id].cell = *it;
476 target[cell_id].gain = 0;
477 }
478
479 // initialize cells in partition 1
480 for(h::list<ConcreteCell *>::iterator it = parent->m_sub1->m_members.begin(); !it; it++) {
481 cell_id = (*it)->getID();
482 // pay attention to cells that are close to the cut
483 if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
484 targets++;
485 target[cell_id].loc = 1;
486 }
487 }
488
489 // initialize cells in partition 2
490 for(h::list<ConcreteCell *>::iterator it = parent->m_sub2->m_members.begin(); !it; it++) {
491 cell_id = (*it)->getID();
492 // pay attention to cells that are close to the cut
493 if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
494 targets++;
495 target[cell_id].loc = 2;
496 }
497 }
498
499 // count the number of cells on each side of the partition for every net
500 for(h::hash_map<ConcreteNet *>::iterator n_it = m_design->nets.begin(); !n_it; n_it++) {
501 for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++)
502 if (abs(target[(*p_it)->getCell()->getID()].loc) == 1)
503 count_1[net->getID()]++;
504 else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2)
505 count_2[net->getID()]++;
506 else if ((*p_it)->getCell()->temp_x < initial_cut)
507 count_1[net->getID()]++;
508 else
509 count_2[net->getID()]++;
510 if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++;
511 }
512
513 } else {
514 // horizontal
515
516 initial_cut = parent->m_sub2->m_bounds.y;
517
518 // initialize all cells
519 for(h::list<ConcreteCell *>::iterator it = rootPartition->m_members.begin(); !it; it++) {
520 cell_id = (*it)->getID();
521 if ((*it)->temp_y < initial_cut)
522 target[cell_id].loc = -1;
523 else
524 target[cell_id].loc = -2;
525 target[cell_id].cell = *it;
526 target[cell_id].gain = 0;
527 }
528
529 // initialize cells in partition 1
530 for(h::list<ConcreteCell *>::iterator it = parent->m_sub1->m_members.begin(); !it; it++) {
531 cell_id = (*it)->getID();
532 // pay attention to cells that are close to the cut
533 if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
534 targets++;
535 target[cell_id].loc = 1;
536 }
537 }
538
539 // initialize cells in partition 2
540 for(h::list<ConcreteCell *>::iterator it = parent->m_sub2->m_members.begin(); !it; it++) {
541 cell_id = (*it)->getID();
542 // pay attention to cells that are close to the cut
543 if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
544 targets++;
545 target[cell_id].loc = 2;
546 }
547 }
548
549 // count the number of cells on each side of the partition for every net
550 for(h::hash_map<ConcreteNet *>::iterator n_it = m_design->nets.begin(); !n_it; n_it++) {
551 for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++)
552 if (abs(target[(*p_it)->getCell()->getID()].loc) == 1)
553 count_1[net->getID()]++;
554 else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2)
555 count_2[net->getID()]++;
556 else if ((*p_it)->getCell()->temp_y < initial_cut)
557 count_1[net->getID()]++;
558 else
559 count_2[net->getID()]++;
560 if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++;
561 }
562 }
563
564 // INITIAL GAIN CALCULATION
565 for(long id=0; id < m_design->cells.length(); id++)
566 if (target[id].loc > 0) {
567 assert(target[id].cell != 0);
568 assert(target[id].gain == 0);
569
570 // examine counts for the net on each pin
571 for(ConcretePinMap::iterator p_it = target[id].cell->getPins().begin(); !p_it; p_it++)
572 if ((*p_it)->isAttached()) {
573 int n_id = (*p_it)->getNet()->getID();
574 if (target[id].loc == 1 && count_1[n_id] == 1) target[id].gain++;
575 if (target[id].loc == 1 && count_2[n_id] == 0) target[id].gain--;
576 if (target[id].loc == 2 && count_1[n_id] == 0) target[id].gain--;
577 if (target[id].loc == 2 && count_2[n_id] == 1) target[id].gain++;
578 }
579
580 assert(target[id].cell->getPins().length() >= abs(target[id].gain));
581
582 // add it to a bin
583 int bin_num = min(max(0, target[id].gain),FM_MAX_BIN);
584 max_gain = max(max_gain, bin_num);
585
586 assert(bin_num >= 0 && bin_num <= FM_MAX_BIN);
587 target[id].next = bin[bin_num];
588 target[id].prev = 0;
589 if (bin[bin_num] != 0)
590 bin[bin_num]->prev = &target[id];
591 bin[bin_num] = &target[id];
592 }
593
594 // OUTER F-M LOOP
595 current_cuts = before_cuts;
596 int num_moves = 1;
597 int pass = 0;
598 while(num_moves > 0 && pass < FM_MAX_PASSES) {
599 pass++;
600 num_moves = 0;
601
602 // check_list(bin, locked, targets); // DEBUG
603
604 // move all locked cells back
605 int moved_back = 0;
606 while(locked != 0) {
607 FM_cell *current = locked;
608 current->locked = false;
609
610 int bin_num = min(max(0, current->gain),FM_MAX_BIN);
611 max_gain = max(max_gain, bin_num);
612
613 locked = current->next;
614 if (locked != 0)
615 locked->prev = 0;
616
617 if (bin[bin_num] != 0)
618 bin[bin_num]->prev = current;
619 current->next = bin[bin_num];
620 bin[bin_num] = current;
621
622 moved_back++;
623 }
624 // cout << "\tmoved back: " << moved_back << endl;
625 // check_list(bin, locked, targets); // DEBUG
626
627 max_gain = FM_MAX_BIN;
628 while(bin[max_gain] == 0 && max_gain > 0) max_gain--;
629
630 // INNER F-M LOOP (single pass)
631 while(1) {
632
633 int bin_num = FM_MAX_BIN;
634 FM_cell *current = bin[bin_num];
635
636 // look for next cell to move
637 while (bin_num > 0 && (current == 0 ||
638 (current->loc==1 && current->cell->getArea()+parent->m_sub2->m_area > halfArea+areaFlexibility) ||
639 (current->loc==2 && current->cell->getArea()+parent->m_sub1->m_area > halfArea+areaFlexibility))) {
640
641 if (current == 0) current = bin[--bin_num]; else current = current->next;
642 }
643 if (bin_num == 0)
644 break;
645
646 num_moves++;
647 current->locked = true;
648 // cout << "moving cell " << current->cell->getID() << " gain=" << current->gain << " pins= " << current->cell->getPins().length() << " from " << current->loc;
649
650 // change partition marking and areas
651 if (current->loc == 1) {
652 current->loc = 2;
653 parent->m_sub1->m_area -= current->cell->getArea();
654 parent->m_sub2->m_area += current->cell->getArea();
655
656 // update partition counts on all nets attached to this cell
657 for(ConcretePinMap::iterator p_it = current->cell->getPins().begin();
658 !p_it; p_it++) {
659
660 if (!(*p_it)->isAttached()) // ignore unattached pins
661 continue;
662 net = (*p_it)->getNet();
663
664 count_1[net->getID()]--;
665 count_2[net->getID()]++;
666
667 // 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;
668
669 // if net becomes critical, update gains on attached cells and resort bins
670 if (count_1[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); }
671 if (count_2[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); }
672
673 // check_list(bin, locked, targets); // DEBUG
674 }
675
676 } else {
677 current->loc = 1;
678 parent->m_sub2->m_area -= current->cell->getArea();
679 parent->m_sub1->m_area += current->cell->getArea();
680
681 // update gains on all nets attached to this cell
682 for(ConcretePinMap::iterator p_it = current->cell->getPins().begin();
683 !p_it; p_it++) {
684
685 if (!(*p_it)->isAttached()) // ignore unattached pins
686 continue;
687 net = (*p_it)->getNet();
688 count_2[net->getID()]--;
689 count_1[net->getID()]++;
690
691 // 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;
692
693 if (count_2[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); }
694 if (count_1[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); }
695
696 // check_list(bin, locked, targets); // DEBUG
697 }
698 }
699
700 //cout << " cuts=" << current_cuts << endl;
701
702 // move current to locked
703
704/*
705 cout << "b=" << bin[bin_num] << " ";
706 cout << current->prev << "-> ";
707 if (current->prev == 0)
708 cout << "X";
709 else cout << current->prev->next;
710 cout << "=" << current << "=";
711 if (current->next == 0)
712 cout << "X";
713 else
714 cout << current->next->prev;
715 cout << " ->" << current->next << endl;
716*/
717
718 if (bin[bin_num] == current)
719 bin[bin_num] = current->next;
720 if (current->prev != 0)
721 current->prev->next = current->next;
722 if (current->next != 0)
723 current->next->prev = current->prev;
724
725/*
726 cout << "b=" << bin[bin_num] << " ";
727 cout << current->prev << "-> ";
728 if (current->prev == 0)
729 cout << "X";
730 else cout << current->prev->next;
731 cout << "=" << current << "=";
732 if (current->next == 0)
733 cout << "X";
734 else
735 cout << current->next->prev;
736 cout << " ->" << current->next << endl;
737*/
738
739 current->prev = 0;
740 current->next = locked;
741 if (locked != 0)
742 locked->prev = current;
743 locked = current;
744
745 // check_list(bin, locked, targets); // DEBUG
746
747 // update max_gain
748 max_gain = FM_MAX_BIN;
749 while(bin[max_gain] == 0 && max_gain > 0) max_gain--;
750 }
751
752 // cout << "\tcurrent cuts= " << current_cuts << " moves= " << num_moves << endl;
753 }
754
755 // reassign members to subpartitions
756 cout << "FIDM-20 : \tbalance before " << parent->m_sub1->m_members.length() << "/"
757 << parent->m_sub2->m_members.length() << " ";
758 parent->m_sub1->m_members.clear();
759 parent->m_sub1->m_area = 0;
760 parent->m_sub2->m_members.clear();
761 parent->m_sub2->m_area = 0;
762 for(h::list<ConcreteCell *>::iterator it = parent->m_members.begin(); !it; it++) {
763 if (target[(*it)->getID()].loc == 1 || target[(*it)->getID()].loc == -1) {
764 parent->m_sub1->m_members.push_back(*it);
765 parent->m_sub1->m_area += (*it)->getArea();
766 }
767 else {
768 parent->m_sub2->m_members.push_back(*it);
769 parent->m_sub2->m_area += (*it)->getArea();
770 }
771 }
772 cout << " after " << parent->m_sub1->m_members.length() << "/"
773 << parent->m_sub2->m_members.length() << endl;
774
775
776 cout << "FIDM-21 : \tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl;
777 cout << "FIDM-22 : \tstarting cuts= " << before_cuts << " final cuts= " << current_cuts << endl;
778#endif
779}
780
781// ----- FM_updateGains()
782// moves a cell between bins
783#if 0
784void FM_updateGains(ConcreteNet *net, int partition, int inc,
785 FM_cell target [], FM_cell *bin [],
786 int count_1 [], int count_2 []) {
787
788 for(ConcretePinList::iterator it = net->getPins().begin(); !it; it++) {
789 FM_cell *current = &(target[(*it)->getCell()->getID()]);
790 assert(current->cell != 0);
791
792 int old_gain = current->gain;
793 current->gain = 0;
794
795 // examine counts for the net on each pin
796 for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); !p_it; p_it++)
797 if ((*p_it)->isAttached()) {
798 int n_id = (*p_it)->getNet()->getID();
799 if (current->loc == 1 && count_1[n_id] == 1) current->gain++;
800 if (current->loc == 1 && count_2[n_id] == 0) current->gain--;
801 if (current->loc == 2 && count_1[n_id] == 0) current->gain--;
802 if (current->loc == 2 && count_2[n_id] == 1) current->gain++;
803 }
804
805 if (!current->locked) {
806 // remove cell from existing bin
807 int bin_num = min(max(0, old_gain),FM_MAX_BIN);
808 if (bin[bin_num] == current)
809 bin[bin_num] = current->next;
810 if (current->prev != 0)
811 current->prev->next = current->next;
812 if (current->next != 0)
813 current->next->prev = current->prev;
814 // add cell to correct bin
815 bin_num = min(max(0, current->gain),FM_MAX_BIN);
816 current->prev = 0;
817 current->next = bin[bin_num];
818 if (bin[bin_num] != 0)
819 bin[bin_num]->prev = current;
820 bin[bin_num] = current;
821 }
822 }
823
824}
825#endif
826
827
828// --------------------------------------------------------------------
829// partitionEqualArea()
830//
832//
833// --------------------------------------------------------------------
835 float halfArea, area;
836 int i=0;
837
838 // which way to sort?
839 if (parent->m_vertical)
840 // sort by X position
841 qsort(parent->m_members, (size_t)parent->m_numMembers, sizeof(ConcreteCell*), cellSortByX);
842 else
843 // sort by Y position
844 qsort(parent->m_members, (size_t)parent->m_numMembers, sizeof(ConcreteCell*), cellSortByY);
845
846 // split the list
847 halfArea = parent->m_area*0.5;
848 parent->m_sub1->m_area = 0.0;
849 parent->m_sub1->m_numMembers = 0;
850 parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members,
851 sizeof(ConcreteCell*)*parent->m_numMembers);
852 parent->m_sub2->m_area = 0.0;
853 parent->m_sub2->m_numMembers = 0;
854 parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members,
855 sizeof(ConcreteCell*)*parent->m_numMembers);
856
857 for(; parent->m_sub1->m_area < halfArea; i++)
858 if (parent->m_members[i]) {
859 area = getCellArea(parent->m_members[i]);
860 parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = parent->m_members[i];
861 parent->m_sub1->m_area += area;
862 }
863 for(; i<parent->m_numMembers; i++)
864 if (parent->m_members[i]) {
865 area = getCellArea(parent->m_members[i]);
866 parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = parent->m_members[i];
867 parent->m_sub2->m_area += area;
868 }
869
870}
871
872
873// --------------------------------------------------------------------
874// partitionScanlineMincut()
875//
877//
878// --------------------------------------------------------------------
880#if 0
881 int current_cuts = 0;
882 int minimum_cuts = INT_MAX;
883 ConcreteCell *minimum_location = NULL;
884 double currentArea = 0, halfArea = parent->m_area * 0.5;
885 double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY;
886 double newLine, oldLine = -DBL_MAX;
887
888 for(ConcreteNetList::iterator n_it = m_design->nets.begin(); !n_it; n_it++)
889 (*n_it)->m_mark = 0;
890 for(h::list<ConcreteCell *>::iterator i = parent->m_members.begin();
891 !i.isDone(); i++) {
892 assert(*i);
893 for(ConcretePinMap::iterator j = (*i)->getPins().begin();
894 !j.isDone(); j++) {
895 assert(*j);
896 if((*j)->isAttached()) {
897 (*j)->getNet()->m_mark = 1;
898 }
899 }
900 }
901
902 if (parent->vertical) {
903 parent->m_members.sort(sortByX);
904 int all1 = 0, all2 = 0;
905 h::list<ConcreteCell *>::iterator local = parent->m_members.begin();
906 for(; !local.isDone(); local++) {
907 currentArea += (*local)->getArea();
908 if (currentArea < halfArea-areaFlexibility)
909 continue;
910 if (currentArea > halfArea+areaFlexibility)
911 break;
912 newLine = (*local)->temp_x;
913 while(all1 < g_place_numNets && allNetsL2[all1]->getBoundingBox().left() <= newLine) {
914 if(allNetsL2[all1]->m_mark) {
915 current_cuts++;
916 }
917 all1++;
918 }
919 while(all2 < g_place_numNets && allNetsR2[all2]->getBoundingBox().right() <= newLine) {
920 if(allNetsR2[all2]->m_mark) {
921 current_cuts--;
922 }
923 all2++;
924 }
925 if (current_cuts < minimum_cuts) {
926 minimum_cuts = current_cuts;
927 minimum_location = *local;
928 }
929 oldLine = newLine;
930 }
931 }
932 else {
933 parent->m_members.sort(sortByY);
934 int all1 = 0, all2 = 0;
935 h::list<ConcreteCell *>::iterator local = parent->m_members.begin();
936 for(; !local.isDone(); local++) {
937 currentArea += (*local)->getArea();
938 if (currentArea < halfArea-areaFlexibility)
939 continue;
940 if (currentArea > halfArea+areaFlexibility)
941 break;
942 newLine = (*local)->temp_y;
943 while(all1 < g_place_numNets && allNetsB2[all1]->getBoundingBox().top() <= newLine) {
944 if(allNetsB2[all1]->m_mark) {
945 current_cuts++;
946 }
947 all1++;
948 }
949 while(all2 < g_place_numNets && allNetsT2[all2]->getBoundingBox().bottom() <= newLine) {
950 if(allNetsT2[all2]->m_mark) {
951 current_cuts--;
952 }
953 all2++;
954 }
955 if (current_cuts < minimum_cuts) {
956 minimum_cuts = current_cuts;
957 minimum_location = *local;
958 }
959 oldLine = newLine;
960 }
961 }
962 if (minimum_location == NULL) {
963 return partitionEqualArea(parent);
964 }
965 h::list<ConcreteCell *>::iterator it = parent->m_members.begin();
966 parent->m_sub1->m_members.clear();
967 parent->m_sub1->m_area = 0;
968 for(; *it != minimum_location; it++) {
969 parent->m_sub1->m_members.push_front(*it);
970 parent->m_sub1->m_area += (*it)->getArea();
971 }
972 parent->m_sub2->m_members.clear();
973 parent->m_sub2->m_area = 0;
974 for(; !it; it++) {
975 parent->m_sub2->m_members.push_front(*it);
976 parent->m_sub2->m_area += (*it)->getArea();
977 }
978#endif
979}
980
981
982// --------------------------------------------------------------------
983// reallocPartition()
984//
986//
987// --------------------------------------------------------------------
989
990 if (p->m_leaf) {
991 return;
992 }
993
994 // --- INITIAL PARTITION
995
998 else
1000
1002
1003 // --- PARTITION IMPROVEMENT
1004 if (p->m_level < REPARTITION_LEVEL_DEPTH) {
1007
1009 }
1010
1011 reallocPartition(p->m_sub1);
1012 reallocPartition(p->m_sub2);
1013}
1014
1015
1016// --------------------------------------------------------------------
1017// resizePartition()
1018//
1020//
1021// --------------------------------------------------------------------
1023 // compute the new bounding box
1024 p->m_sub1->m_bounds.x = p->m_bounds.x;
1025 p->m_sub1->m_bounds.y = p->m_bounds.y;
1026 if (p->m_vertical) {
1027 p->m_sub1->m_bounds.w = p->m_bounds.w*(p->m_sub1->m_area/p->m_area);
1028 p->m_sub1->m_bounds.h = p->m_bounds.h;
1029 p->m_sub2->m_bounds.x = p->m_bounds.x + p->m_sub1->m_bounds.w;
1030 p->m_sub2->m_bounds.w = p->m_bounds.w*(p->m_sub2->m_area/p->m_area);
1031 p->m_sub2->m_bounds.y = p->m_bounds.y;
1032 p->m_sub2->m_bounds.h = p->m_bounds.h;
1033 } else {
1034 p->m_sub1->m_bounds.h = p->m_bounds.h*(p->m_sub1->m_area/p->m_area);
1035 p->m_sub1->m_bounds.w = p->m_bounds.w;
1036 p->m_sub2->m_bounds.y = p->m_bounds.y + p->m_sub1->m_bounds.h;
1037 p->m_sub2->m_bounds.h = p->m_bounds.h*(p->m_sub2->m_area/p->m_area);
1038 p->m_sub2->m_bounds.x = p->m_bounds.x;
1039 p->m_sub2->m_bounds.w = p->m_bounds.w;
1040 }
1041}
1042
1043
1044// --------------------------------------------------------------------
1045// incrementalSubpartition()
1046//
1050//
1051// --------------------------------------------------------------------
1052void incrementalSubpartition(Partition *p, ConcreteCell *newCells [], const int numNewCells) {
1053 int c;
1054 ConcreteCell **newCells1 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells),
1055 **newCells2 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells);
1056 int numNewCells1 = 0, numNewCells2 = 0;
1057 float cut_loc;
1058
1059 assert(p);
1060
1061 // add new cells to partition list
1062 p->m_members = (ConcreteCell**)realloc(p->m_members,
1063 sizeof(ConcreteCell*)*(p->m_numMembers+numNewCells));
1064 memcpy(&(p->m_members[p->m_numMembers]), newCells, sizeof(ConcreteCell*)*numNewCells);
1065 p->m_numMembers += numNewCells;
1066
1067 // if is a leaf partition, finished
1068 if (p->m_leaf) return;
1069
1070 // split new cells into sub-partitions based on location
1071 if (p->m_vertical) {
1072 cut_loc = p->m_sub2->m_bounds.x;
1073 for(c=0; c<numNewCells; c++)
1074 if (newCells[c]->m_x < cut_loc)
1075 newCells1[numNewCells1++] = newCells[c];
1076 else
1077 newCells2[numNewCells2++] = newCells[c];
1078 } else {
1079 cut_loc = p->m_sub2->m_bounds.y;
1080 for(c=0; c<numNewCells; c++)
1081 if (newCells[c]->m_y < cut_loc)
1082 newCells1[numNewCells1++] = newCells[c];
1083 else
1084 newCells2[numNewCells2++] = newCells[c];
1085 }
1086
1087 if (numNewCells1 > 0) incrementalSubpartition(p->m_sub1, newCells1, numNewCells1);
1088 if (numNewCells2 > 0) incrementalSubpartition(p->m_sub2, newCells2, numNewCells2);
1089
1090 free(newCells1);
1091 free(newCells2);
1092}
1093
1094
1095// --------------------------------------------------------------------
1096// incrementalPartition()
1097//
1101//
1102// --------------------------------------------------------------------
1104 int c = 0, c2 = 0;
1105 int numNewCells = 0;
1107 **newCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
1108
1110
1111 // update cell list of root partition
1112 memcpy(allCells, (size_t)g_place_concreteCells, sizeof(ConcreteCell*)*g_place_numCells);
1113 qsort(allCells, (size_t)g_place_numCells, sizeof(ConcreteCell*), cellSortByID);
1114 qsort(g_place_rootPartition->m_members, (size_t)g_place_rootPartition->m_numMembers,
1115 sizeof(ConcreteCell*), cellSortByID);
1116
1117 // scan sorted lists and collect cells not in partitions
1118 while(!allCells[c++]);
1119 while(!g_place_rootPartition->m_members[c2++]);
1120
1121 for(; c<g_place_numCells; c++, c2++) {
1122 while(c2 < g_place_rootPartition->m_numMembers &&
1123 allCells[c]->m_id > g_place_rootPartition->m_members[c2]->m_id) c2++;
1124 while(c < g_place_numCells &&
1125 (c2 >= g_place_rootPartition->m_numMembers ||
1126 allCells[c]->m_id < g_place_rootPartition->m_members[c2]->m_id)) {
1127 // a new cell!
1128 newCells[numNewCells++] = allCells[c];
1129 c++;
1130 }
1131 }
1132
1133 printf("QPRT-50 : \tincremental partitioning with %d new cells\n", numNewCells);
1134 if (numNewCells>0) incrementalSubpartition(g_place_rootPartition, newCells, numNewCells);
1135
1136 free(allCells);
1137 free(newCells);
1138}
1140
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define local
Definition adler32.c:17
Cube * p
Definition exorList.c:222
ConcreteCell ** g_place_concreteCells
Definition place_base.c:33
ConcreteNet ** g_place_concreteNets
Definition place_base.c:35
int netSortByB(const void *a, const void *b)
Definition place_base.c:263
int netSortByR(const void *a, const void *b)
Definition place_base.c:249
int cellSortByID(const void *a, const void *b)
Definition place_base.c:338
float getCellArea(const ConcreteCell *cell)
Definition place_base.c:99
int cellSortByY(const void *a, const void *b)
Definition place_base.c:326
int g_place_numNets
Definition place_base.c:27
ABC_NAMESPACE_IMPL_START int g_place_numCells
Definition place_base.c:26
int netSortByT(const void *a, const void *b)
Definition place_base.c:277
Rect g_place_coreBounds
Definition place_base.c:30
int netSortByL(const void *a, const void *b)
Sorts nets by position of one of its corners.
Definition place_base.c:235
int cellSortByX(const void *a, const void *b)
Sorts cells by either position coordinate.
Definition place_base.c:314
ABC_NAMESPACE_IMPL_START int g_place_numPartitions
Partition * g_place_rootPartition
#define PARTITION_AREA_ONLY
#define FM_MAX_PASSES
#define REPARTITION_HMETIS
#define REPARTITION_LEVEL_DEPTH
#define FM_MAX_BIN
#define REPARTITION_FM
#define MAX_PARTITION_NONSYMMETRY
#define REPARTITION_TARGET_FRACTION
#define LARGEST_FINAL_SIZE
void incrementalSubpartition(Partition *p, ConcreteCell *newCells[], const int numNewCells)
Adds new cells to an existing partition. Partition sizes/locations are unchanged.
ConcreteNet ** allNetsR2
void repartitionHMetis(Partition *parent)
Repartitions the two subpartitions using the hMetis min-cut library.
void FM_updateGains(ConcreteNet *net, int partition, int inc, FM_cell target[], FM_cell *bin[], int count_1[], int count_2[])
bool refinePartitions()
Splits large leaf partitions.
void reallocPartition(Partition *p)
Reallocates a partition and all of its children.
void repartitionFM(Partition *parent)
Fiduccia-Matheyses mincut partitioning algorithm.
ConcreteNet ** allNetsB2
void presortNets()
Sorts nets by corner positions.
void partitionEqualArea(Partition *parent)
Splits a partition into two halves of equal area.
void reallocPartitions()
Reallocates the partitions based on placement information.
ConcreteNet ** allNetsT2
void initPartitioning()
Initializes data structures necessary for partitioning.
void incrementalPartition()
Adds new cells to an existing partition. Partition sizes/locations are unchanged.
void resizePartition(Partition *p)
Recomputes the bounding boxes of the child partitions based on their relative areas.
ConcreteNet ** allNetsL2
void partitionScanlineMincut(Partition *parent)
Scans the cells within a partition from left to right and chooses the min-cut.
bool refinePartition(Partition *p)
Splits any large leaves within a partition.
struct FM_cell * next
ConcreteCell * cell
struct FM_cell * prev
#define assert(ex)
Definition util_old.h:213
char * memcpy()
char * calloc()
char * memset()
VOID_HACK free()
char * malloc()
char * realloc()