#include #include #include #include #include "flute.h" namespace Flute { #define D 9 #if D<=7 #define MGROUP 5040/4 // Max. # of groups, 7! = 5040 #define MPOWV 15 // Max. # of POWVs per group #elif D==8 #define MGROUP 40320/4 // Max. # of groups, 8! = 40320 #define MPOWV 33 // Max. # of POWVs per group #elif D==9 #define MGROUP 362880/4 // Max. # of groups, 9! = 362880 #define MPOWV 79 // Max. # of POWVs per group #endif int numgrp[10]={0,0,0,0,6,30,180,1260,10080,90720}; struct csoln { unsigned char parent; unsigned char seg[11]; // Add: 0..i, Sub: j..10; seg[i+1]=seg[j-1]=0 unsigned char rowcol[9-2]; // row = rowcol[]/16, col = rowcol[]%16, unsigned char neighbor[2*9-2]; }; struct csoln *LUT[9+1][MGROUP]; // storing 4 .. D int numsoln[9+1][MGROUP]; struct point { DTYPE x, y; int o; }; void readLUT(std::string FLUTE_POWVFILE, std::string FLUTE_POSTFILE); DTYPE flute_wl(int d, DTYPE x[], DTYPE y[], int acc); DTYPE flutes_wl_LD(int d, DTYPE xs[], DTYPE ys[], int s[]); DTYPE flutes_wl_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc); DTYPE flutes_wl_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc); Tree flute(int d, DTYPE x[], DTYPE y[], int acc); Tree flutes_LD(int d, DTYPE xs[], DTYPE ys[], int s[]); Tree flutes_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc); Tree flutes_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc); Tree dmergetree(Tree t1, Tree t2); Tree hmergetree(Tree t1, Tree t2, int s[]); Tree vmergetree(Tree t1, Tree t2); void local_refinement(Tree *tp, int p); DTYPE wirelength(Tree t); void printtree(Tree t); void plottree(Tree t); void readLUT(std::string FLUTE_POWVFILE, std::string FLUTE_POSTFILE) { unsigned char charnum[256], line[32], *linep, c; FILE *fpwv, *fprt; struct csoln *p; int d, i, j, k, kk, ns, nn; init_param(); for (i=0; i<=255; i++) { if ('0'<=i && i<='9') charnum[i] = i - '0'; else if (i>='A') charnum[i] = i - 'A' + 10; else // if (i=='$' || i=='\n' || ... ) charnum[i] = 0; } fpwv=fopen(FLUTE_POWVFILE.c_str(), "r"); if (fpwv == NULL) { printf("Error in opening %s\n", FLUTE_POWVFILE.c_str()); exit(1); } #if FLUTE_ROUTING==1 fprt=fopen(FLUTE_POSTFILE.c_str(), "r"); if (fprt == NULL) { printf("Error in opening %s\n", FLUTE_POSTFILE.c_str()); exit(1); } #endif int status_code; // useles, just to stop compile warning for (d=4; d<=D; d++) { status_code = fscanf(fpwv, "d=%d\n", &d); #if FLUTE_ROUTING==1 status_code = fscanf(fprt, "d=%d\n", &d); #endif for (k=0; kparent = charnum[*(linep++)]; j = 0; while ((p->seg[j++] = charnum[*(linep++)]) != 0) ; j = 10; while ((p->seg[j--] = charnum[*(linep++)]) != 0) ; #if FLUTE_ROUTING==1 nn = 2*d-2; status_code = fread(line, 1, d-2, fprt); linep=line; for (j=d; jrowcol[j-d] = c; } status_code = fread(line, 1, nn/2+1, fprt); linep=line; // last char \n for (j=0; jneighbor[j++] = c/16; p->neighbor[j++] = c%16; } #endif p++; } } } } } DTYPE flute_wl(int d, DTYPE x[], DTYPE y[], int acc) { DTYPE xs[FLUTE_MAXD], ys[FLUTE_MAXD], minval, l, xu, xl, yu, yl; int s[FLUTE_MAXD]; int i, j, k, minidx; struct point pt[FLUTE_MAXD], *ptp[FLUTE_MAXD], *tmpp; if (d==2) l = ADIFF(x[0], x[1]) + ADIFF(y[0], y[1]); else if (d==3) { if (x[0] > x[1]) { xu = flute_max(x[0], x[2]); xl = flute_min(x[1], x[2]); } else { xu = flute_max(x[1], x[2]); xl = flute_min(x[0], x[2]); } if (y[0] > y[1]) { yu = flute_max(y[0], y[2]); yl = flute_min(y[1], y[2]); } else { yu = flute_max(y[1], y[2]); yl = flute_min(y[0], y[2]); } l = (xu-xl) + (yu-yl); } else { for (i=0; ix; minidx = i; for (j=i+1; j ptp[j]->x) { minval = ptp[j]->x; minidx = j; } } tmpp = ptp[i]; ptp[i] = ptp[minidx]; ptp[minidx] = tmpp; } #if FLUTE_REMOVE_DUPLICATE_PIN==1 ptp[d] = &pt[d]; ptp[d]->x = ptp[d]->y = -999999; j = 0; for (i=0; ix == ptp[i]->x; k++) if (ptp[k]->y == ptp[i]->y) // pins k and i are the same break; if (ptp[k]->x != ptp[i]->x) ptp[j++] = ptp[i]; } d = j; #endif for (i=0; ix; ptp[i]->o = i; } // sort y to find s[] for (i=0; iy; minidx = i; for (j=i+1; j ptp[j]->y) { minval = ptp[j]->y; minidx = j; } } ys[i] = ptp[minidx]->y; s[i] = ptp[minidx]->o; ptp[minidx] = ptp[i]; } ys[d-1] = ptp[d-1]->y; s[d-1] = ptp[d-1]->o; l = flutes_wl(d, xs, ys, s, acc); } return l; } // xs[] and ys[] are coords in x and y in sorted order // s[] is a list of nodes in increasing y direction // if nodes are indexed in the order of increasing x coord // i.e., s[i] = s_i as defined in paper // The points are (xs[s[i]], ys[i]) for i=0..d-1 // or (xs[i], ys[si[i]]) for i=0..d-1 DTYPE flutes_wl_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc) { int i, j, ss; for (i=0; i ss) s[j]--; i--; d--; } } return flutes_wl_ALLD(d, xs, ys, s, acc); } // For low-degree, i.e., 2 <= d <= D DTYPE flutes_wl_LD(int d, DTYPE xs[], DTYPE ys[], int s[]) { int k, pi, i, j; struct csoln *rlist; DTYPE dd[2*D-2]; // 0..D-2 for v, D-1..2*D-3 for h DTYPE minl, sum, l[MPOWV+1]; if (d <= 3) minl = xs[d-1]-xs[0]+ys[d-1]-ys[0]; else { k = 0; if (s[0] < s[2]) k++; if (s[1] < s[2]) k++; for (i=3; i<=d-1; i++) { // p0=0 always, skip i=1 for symmetry pi = s[i]; for (j=d-1; j>i; j--) if (s[j] < s[i]) pi--; k = pi + (i+1)*k; } if (k < numgrp[d]) // no horizontal flip for (i=1; i<=d-3; i++) { dd[i]=ys[i+1]-ys[i]; dd[d-1+i]=xs[i+1]-xs[i]; } else { k=2*numgrp[d]-1-k; for (i=1; i<=d-3; i++) { dd[i]=ys[i+1]-ys[i]; dd[d-1+i]=xs[d-1-i]-xs[d-2-i]; } } minl = l[0] = xs[d-1]-xs[0]+ys[d-1]-ys[0]; rlist = LUT[d][k]; for (i=0; rlist->seg[i]>0; i++) minl += dd[rlist->seg[i]]; l[1] = minl; j = 2; while (j <= numsoln[d][k]) { rlist++; sum = l[rlist->parent]; for (i=0; rlist->seg[i]>0; i++) sum += dd[rlist->seg[i]]; for (i=10; rlist->seg[i]>0; i--) sum -= dd[rlist->seg[i]]; minl = flute_min(minl, sum); l[j++] = sum; } } return minl; } // For medium-degree, i.e., D+1 <= d DTYPE flutes_wl_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc) { DTYPE x1[FLUTE_MAXD], x2[FLUTE_MAXD], y1[FLUTE_MAXD], y2[FLUTE_MAXD]; int si[FLUTE_MAXD], s1[FLUTE_MAXD], s2[FLUTE_MAXD]; float score[2*FLUTE_MAXD], penalty[FLUTE_MAXD], pnlty, dx, dy; DTYPE ll, minl, extral; int i, r, p, maxbp, nbp, bp, ub, lb, n1, n2, newacc; int ms, mins, maxs, minsi, maxsi; DTYPE distx[FLUTE_MAXD], disty[FLUTE_MAXD], xydiff; if (s[0] < s[d-1]) { ms = flute_max(s[0], s[1]); for (i=2; i<=ms; i++) ms = flute_max(ms, s[i]); if (ms <= d-3) { for (i=0; i<=ms; i++) { x1[i] = xs[i]; y1[i] = ys[i]; s1[i] = s[i]; } x1[ms+1] = xs[ms]; y1[ms+1] = ys[ms]; s1[ms+1] = ms+1; s2[0] = 0; for (i=1; i<=d-1-ms; i++) s2[i] = s[i+ms]-ms; return flutes_wl_LMD(ms+2, x1, y1, s1, acc) + flutes_wl_LMD(d-ms, xs+ms, ys+ms, s2, acc); } } else { // (s[0] > s[d-1]) ms = flute_min(s[0], s[1]); for (i=2; i<=d-1-ms; i++) ms = flute_min(ms, s[i]); if (ms >= 2) { x1[0] = xs[ms]; y1[0] = ys[0]; s1[0] = s[0]-ms+1; for (i=1; i<=d-1-ms; i++) { x1[i] = xs[i+ms-1]; y1[i] = ys[i]; s1[i] = s[i]-ms+1; } x1[d-ms] = xs[d-1]; y1[d-ms] = ys[d-1-ms]; s1[d-ms] = 0; s2[0] = ms; for (i=1; i<=ms; i++) s2[i] = s[i+d-1-ms]; return flutes_wl_LMD(d+1-ms, x1, y1, s1, acc) + flutes_wl_LMD(ms+1, xs, ys+d-1-ms, s2, acc); } } // Find inverse si[] of s[] for (r=0; r=0; r--, pnlty += dx) penalty[r] = pnlty, penalty[d-1-r] = pnlty; for (r = d/2-1, pnlty = dy; r>=0; r--, pnlty += dy) penalty[s[r]] += pnlty, penalty[s[d-1-r]] += pnlty; //#define CCWL 0.16 // for (r=0; r maxs) maxs = s[r]; distx[r] = xs[maxs] - xs[mins]; if (si[r] < minsi) minsi = si[r]; else if (si[r] > maxsi) maxsi = si[r]; disty[r] = ys[maxsi] - ys[minsi] + xydiff; } if (s[d-2] < s[d-1]) mins = s[d-2], maxs = s[d-1]; else mins = s[d-1], maxs = s[d-2]; if (si[d-2] < si[d-1]) minsi = si[d-2], maxsi = si[d-1]; else minsi = si[d-1], maxsi = si[d-2]; for (r=d-3; r>=lb; r--) { if (s[r] < mins) mins = s[r]; else if (s[r] > maxs) maxs = s[r]; distx[r] += xs[maxs] - xs[mins]; if (si[r] < minsi) minsi = si[r]; else if (si[r] > maxsi) maxsi = si[r]; disty[r] += ys[maxsi] - ys[minsi]; } nbp=0; for (r=lb; r<=ub; r++) { if (si[r]==0 || si[r]==d-1) score[nbp] = (xs[r+1] - xs[r-1]) - penalty[r] - AAWL*(ys[d-2]-ys[1]) - DDWL*disty[r]; else score[nbp] = (xs[r+1] - xs[r-1]) - penalty[r] - BBWL*(ys[si[r]+1]-ys[si[r]-1]) - DDWL*disty[r]; nbp++; if (s[r]==0 || s[r]==d-1) score[nbp] = (ys[r+1] - ys[r-1]) - penalty[s[r]] - AAWL*(xs[d-2]-xs[1]) - DDWL*distx[r]; else score[nbp] = (ys[r+1] - ys[r-1]) - penalty[s[r]] - BBWL*(xs[s[r]+1]-xs[s[r]-1]) - DDWL*distx[r]; nbp++; } if (acc <= 3) newacc = 1; else { newacc = acc/2; if (acc >= nbp) acc = nbp-1; } minl = (DTYPE) INT_MAX; for (i=0; i p) { s2[n2] = s[r]-p; y2[n2] = ys[r]; n2++; } else { // if (s[r] == p) i.e., r = si[p] s1[n1] = p; s2[n2] = 0; if (r == d-1 || r == d-2) { y1[n1] = y2[n2] = ys[r-1]; extral = ys[r] - ys[r-1]; } if (r == 0 || r == 1) { y1[n1] = y2[n2] = ys[r+1]; extral = ys[r+1] - ys[r]; } else { y1[n1] = y2[n2] = ys[r]; extral = 0; } n1++; n2++; } } ll = extral + flutes_wl_LMD(p+1, xs, y1, s1, newacc) + flutes_wl_LMD(d-p, xs+p, y2, s2, newacc); } else { // if (!BreakInX(maxbp)) n1 = n2 = 0; for (r=0; r p) { s2[si[r]-p] = n2; x2[n2] = xs[r]; n2++; } else { // if (si[r] == p) i.e., r = s[p] s1[p] = n1; s2[0] = n2; if (r == d-1 || r == d-2) { x1[n1] = x2[n2] = xs[r-1]; extral = xs[r] - xs[r-1]; } if (r == 0 || r == 1) { x1[n1] = x2[n2] = xs[r+1]; extral = xs[r+1] - xs[r]; } else { x1[n1] = x2[n2] = xs[r]; extral = 0; } n1++; n2++; } } ll = extral + flutes_wl_LMD(p+1, x1, ys, s1, newacc) + flutes_wl_LMD(d-p, x2, ys+p, s2, newacc); } if (minl > ll) minl = ll; } return minl; } static int orderx(const void *a, const void *b) { struct point *pa, *pb; pa = *(struct point**)a; pb = *(struct point**)b; if (pa->x < pb->x) return -1; if (pa->x > pb->x) return 1; return 0; } static int ordery(const void *a, const void *b) { struct point *pa, *pb; pa = *(struct point**)a; pb = *(struct point**)b; if (pa->y < pb->y) return -1; if (pa->y > pb->y) return 1; return 0; } Tree flute(int d, DTYPE x[], DTYPE y[], int acc) { DTYPE *xs, *ys, minval; int *s; int i, j, k, minidx; struct point *pt, **ptp, *tmpp; Tree t; if (d==2) { t.deg = 2; t.length = ADIFF(x[0], x[1]) + ADIFF(y[0], y[1]); t.branch = (Branch *) malloc(2*sizeof(Branch)); t.branch[0].x = x[0]; t.branch[0].y = y[0]; t.branch[0].n = 1; t.branch[1].x = x[1]; t.branch[1].y = y[1]; t.branch[1].n = 1; } else { xs = (DTYPE *)malloc(sizeof(DTYPE)*(d)); ys = (DTYPE *)malloc(sizeof(DTYPE)*(d)); s = (int *)malloc(sizeof(int)*(d)); pt = (struct point *)malloc(sizeof(struct point)*(d+1)); ptp = (struct point **)malloc(sizeof(struct point*)*(d+1)); for (i=0; ix; minidx = i; for (j=i+1; j ptp[j]->x) { minval = ptp[j]->x; minidx = j; } } tmpp = ptp[i]; ptp[i] = ptp[minidx]; ptp[minidx] = tmpp; } } else { qsort(ptp, d, sizeof(struct point *), orderx); } #if FLUTE_REMOVE_DUPLICATE_PIN==1 ptp[d] = &pt[d]; ptp[d]->x = ptp[d]->y = -999999; j = 0; for (i=0; ix == ptp[i]->x; k++) if (ptp[k]->y == ptp[i]->y) // pins k and i are the same break; if (ptp[k]->x != ptp[i]->x) ptp[j++] = ptp[i]; } d = j; #endif for (i=0; ix; ptp[i]->o = i; } // sort y to find s[] if (d<200) { for (i=0; iy; minidx = i; for (j=i+1; j ptp[j]->y) { minval = ptp[j]->y; minidx = j; } } ys[i] = ptp[minidx]->y; s[i] = ptp[minidx]->o; ptp[minidx] = ptp[i]; } ys[d-1] = ptp[d-1]->y; s[d-1] = ptp[d-1]->o; } else { qsort(ptp, d, sizeof(struct point *), ordery); for (i=0; iy; s[i] = ptp[i]->o; } } t = flutes(d, xs, ys, s, acc); free(xs); free(ys); free(s); free(pt); free(ptp); } return t; } // xs[] and ys[] are coords in x and y in sorted order // s[] is a list of nodes in increasing y direction // if nodes are indexed in the order of increasing x coord // i.e., s[i] = s_i as defined in paper // The points are (xs[s[i]], ys[i]) for i=0..d-1 // or (xs[i], ys[si[i]]) for i=0..d-1 Tree flutes_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc) { int i, j, ss; for (i=0; i ss) s[j]--; i--; d--; } } return flutes_ALLD(d, xs, ys, s, acc); } // For low-degree, i.e., 2 <= d <= D Tree flutes_LD(int d, DTYPE xs[], DTYPE ys[], int s[]) { int k, pi, i, j; struct csoln *rlist, *bestrlist; DTYPE dd[2*D-2]; // 0..D-2 for v, D-1..2*D-3 for h DTYPE minl, sum, l[MPOWV+1]; int hflip; Tree t; t.deg = d; t.branch = (Branch *) malloc((2*d-2)*sizeof(Branch)); if (d == 2) { minl = xs[1]-xs[0]+ys[1]-ys[0]; t.branch[0].x = xs[s[0]]; t.branch[0].y = ys[0]; t.branch[0].n = 1; t.branch[1].x = xs[s[1]]; t.branch[1].y = ys[1]; t.branch[1].n = 1; } else if (d == 3) { minl = xs[2]-xs[0]+ys[2]-ys[0]; t.branch[0].x = xs[s[0]]; t.branch[0].y = ys[0]; t.branch[0].n = 3; t.branch[1].x = xs[s[1]]; t.branch[1].y = ys[1]; t.branch[1].n = 3; t.branch[2].x = xs[s[2]]; t.branch[2].y = ys[2]; t.branch[2].n = 3; t.branch[3].x = xs[1]; t.branch[3].y = ys[1]; t.branch[3].n = 3; } else { k = 0; if (s[0] < s[2]) k++; if (s[1] < s[2]) k++; for (i=3; i<=d-1; i++) { // p0=0 always, skip i=1 for symmetry pi = s[i]; for (j=d-1; j>i; j--) if (s[j] < s[i]) pi--; k = pi + (i+1)*k; } if (k < numgrp[d]) { // no horizontal flip hflip = 0; for (i=1; i<=d-3; i++) { dd[i]=ys[i+1]-ys[i]; dd[d-1+i]=xs[i+1]-xs[i]; } } else { hflip = 1; k=2*numgrp[d]-1-k; for (i=1; i<=d-3; i++) { dd[i]=ys[i+1]-ys[i]; dd[d-1+i]=xs[d-1-i]-xs[d-2-i]; } } minl = l[0] = xs[d-1]-xs[0]+ys[d-1]-ys[0]; rlist = LUT[d][k]; for (i=0; rlist->seg[i]>0; i++) minl += dd[rlist->seg[i]]; bestrlist = rlist; l[1] = minl; j = 2; while (j <= numsoln[d][k]) { rlist++; sum = l[rlist->parent]; for (i=0; rlist->seg[i]>0; i++) sum += dd[rlist->seg[i]]; for (i=10; rlist->seg[i]>0; i--) sum -= dd[rlist->seg[i]]; if (sum < minl) { minl = sum; bestrlist = rlist; } l[j++] = sum; } t.branch[0].x = xs[s[0]]; t.branch[0].y = ys[0]; t.branch[1].x = xs[s[1]]; t.branch[1].y = ys[1]; for (i=2; ineighbor[i]; } t.branch[d-2].x = xs[s[d-2]]; t.branch[d-2].y = ys[d-2]; t.branch[d-1].x = xs[s[d-1]]; t.branch[d-1].y = ys[d-1]; if (hflip) { if (s[1] < s[0]) { t.branch[0].n = bestrlist->neighbor[1]; t.branch[1].n = bestrlist->neighbor[0]; } else { t.branch[0].n = bestrlist->neighbor[0]; t.branch[1].n = bestrlist->neighbor[1]; } if (s[d-1] < s[d-2]) { t.branch[d-2].n = bestrlist->neighbor[d-1]; t.branch[d-1].n = bestrlist->neighbor[d-2]; } else { t.branch[d-2].n = bestrlist->neighbor[d-2]; t.branch[d-1].n = bestrlist->neighbor[d-1]; } for (i=d; i<2*d-2; i++) { t.branch[i].x = xs[d-1-bestrlist->rowcol[i-d]%16]; t.branch[i].y = ys[bestrlist->rowcol[i-d]/16]; t.branch[i].n = bestrlist->neighbor[i]; } } else { // !hflip if (s[0] < s[1]) { t.branch[0].n = bestrlist->neighbor[1]; t.branch[1].n = bestrlist->neighbor[0]; } else { t.branch[0].n = bestrlist->neighbor[0]; t.branch[1].n = bestrlist->neighbor[1]; } if (s[d-2] < s[d-1]) { t.branch[d-2].n = bestrlist->neighbor[d-1]; t.branch[d-1].n = bestrlist->neighbor[d-2]; } else { t.branch[d-2].n = bestrlist->neighbor[d-2]; t.branch[d-1].n = bestrlist->neighbor[d-1]; } for (i=d; i<2*d-2; i++) { t.branch[i].x = xs[bestrlist->rowcol[i-d]%16]; t.branch[i].y = ys[bestrlist->rowcol[i-d]/16]; t.branch[i].n = bestrlist->neighbor[i]; } } } t.length = minl; return t; } // For medium-degree, i.e., D+1 <= d Tree flutes_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc) { DTYPE x1[FLUTE_MAXD], x2[FLUTE_MAXD], y1[FLUTE_MAXD], y2[FLUTE_MAXD]; int si[FLUTE_MAXD], s1[FLUTE_MAXD], s2[FLUTE_MAXD]; float score[2*FLUTE_MAXD], penalty[FLUTE_MAXD], pnlty, dx, dy; DTYPE ll, minl, coord1, coord2; int i, r, p, maxbp, bestbp, bp, nbp, ub, lb, n1, n2, nn1, nn2, newacc; Tree t, t1, t2, bestt1, bestt2; int ms, mins, maxs, minsi, maxsi; DTYPE distx[FLUTE_MAXD], disty[FLUTE_MAXD], xydiff; if (s[0] < s[d-1]) { ms = flute_max(s[0], s[1]); for (i=2; i<=ms; i++) ms = flute_max(ms, s[i]); if (ms <= d-3) { for (i=0; i<=ms; i++) { x1[i] = xs[i]; y1[i] = ys[i]; s1[i] = s[i]; } x1[ms+1] = xs[ms]; y1[ms+1] = ys[ms]; s1[ms+1] = ms+1; s2[0] = 0; for (i=1; i<=d-1-ms; i++) s2[i] = s[i+ms]-ms; t1 = flutes_LMD(ms+2, x1, y1, s1, acc); t2 = flutes_LMD(d-ms, xs+ms, ys+ms, s2, acc); t = dmergetree(t1, t2); free(t1.branch); free(t2.branch); return t; } } else { // (s[0] > s[d-1]) ms = flute_min(s[0], s[1]); for (i=2; i<=d-1-ms; i++) ms = flute_min(ms, s[i]); if (ms >= 2) { x1[0] = xs[ms]; y1[0] = ys[0]; s1[0] = s[0]-ms+1; for (i=1; i<=d-1-ms; i++) { x1[i] = xs[i+ms-1]; y1[i] = ys[i]; s1[i] = s[i]-ms+1; } x1[d-ms] = xs[d-1]; y1[d-ms] = ys[d-1-ms]; s1[d-ms] = 0; s2[0] = ms; for (i=1; i<=ms; i++) s2[i] = s[i+d-1-ms]; t1 = flutes_LMD(d+1-ms, x1, y1, s1, acc); t2 = flutes_LMD(ms+1, xs, ys+d-1-ms, s2, acc); t = dmergetree(t1, t2); free(t1.branch); free(t2.branch); return t; } } // Find inverse si[] of s[] for (r=0; r=2; r--, pnlty += dx) penalty[r] = pnlty, penalty[d-1-r] = pnlty; penalty[1] = pnlty, penalty[d-2] = pnlty; penalty[0] = pnlty, penalty[d-1] = pnlty; for (r = d/2-1, pnlty = dy; r>=2; r--, pnlty += dy) penalty[s[r]] += pnlty, penalty[s[d-1-r]] += pnlty; penalty[s[1]] += pnlty, penalty[s[d-2]] += pnlty; penalty[s[0]] += pnlty, penalty[s[d-1]] += pnlty; //#define CC 0.16 //#define v(r) ((r==0||r==1||r==d-2||r==d-1) ? d-3 : flute_abs(d-1-r-r)) // for (r=0; r maxs) maxs = s[r]; distx[r] = xs[maxs] - xs[mins]; if (si[r] < minsi) minsi = si[r]; else if (si[r] > maxsi) maxsi = si[r]; disty[r] = ys[maxsi] - ys[minsi] + xydiff; } if (s[d-2] < s[d-1]) mins = s[d-2], maxs = s[d-1]; else mins = s[d-1], maxs = s[d-2]; if (si[d-2] < si[d-1]) minsi = si[d-2], maxsi = si[d-1]; else minsi = si[d-1], maxsi = si[d-2]; for (r=d-3; r>=lb; r--) { if (s[r] < mins) mins = s[r]; else if (s[r] > maxs) maxs = s[r]; distx[r] += xs[maxs] - xs[mins]; if (si[r] < minsi) minsi = si[r]; else if (si[r] > maxsi) maxsi = si[r]; disty[r] += ys[maxsi] - ys[minsi]; } nbp=0; for (r=lb; r<=ub; r++) { if (si[r]<=1) score[nbp] = (xs[r+1] - xs[r-1]) - penalty[r] - AA*(ys[2]-ys[1]) - DD*disty[r]; else if (si[r]>=d-2) score[nbp] = (xs[r+1] - xs[r-1]) - penalty[r] - AA*(ys[d-2]-ys[d-3]) - DD*disty[r]; else score[nbp] = (xs[r+1] - xs[r-1]) - penalty[r] - BB*(ys[si[r]+1]-ys[si[r]-1]) - DD*disty[r]; nbp++; if (s[r]<=1) score[nbp] = (ys[r+1] - ys[r-1]) - penalty[s[r]] - AA*(xs[2]-xs[1]) - DD*distx[r]; else if (s[r]>=d-2) score[nbp] = (ys[r+1] - ys[r-1]) - penalty[s[r]] - AA*(xs[d-2]-xs[d-3]) - DD*distx[r]; else score[nbp] = (ys[r+1] - ys[r-1]) - penalty[s[r]] - BB*(xs[s[r]+1]-xs[s[r]-1]) - DD*distx[r]; nbp++; } if (acc <= 3) newacc = 1; else { newacc = acc/2; if (acc >= nbp) acc = nbp-1; } minl = (DTYPE) INT_MAX; bestt1.branch = bestt2.branch = NULL; for (i=0; i p) { s2[n2] = s[r]-p; y2[n2] = ys[r]; n2++; } else { // if (s[r] == p) i.e., r = si[p] s1[n1] = p; s2[n2] = 0; y1[n1] = y2[n2] = ys[r]; nn1 = n1; nn2 = n2; n1++; n2++; } } t1 = flutes_LMD(p+1, xs, y1, s1, newacc); t2 = flutes_LMD(d-p, xs+p, y2, s2, newacc); ll = t1.length + t2.length; coord1 = t1.branch[t1.branch[nn1].n].y; coord2 = t2.branch[t2.branch[nn2].n].y; if (t2.branch[nn2].y > flute_max(coord1, coord2)) ll -= t2.branch[nn2].y - flute_max(coord1, coord2); else if (t2.branch[nn2].y < flute_min(coord1, coord2)) ll -= flute_min(coord1, coord2) - t2.branch[nn2].y; } else { // if (!BreakInX(maxbp)) n1 = n2 = 0; for (r=0; r p) { s2[si[r]-p] = n2; x2[n2] = xs[r]; n2++; } else { // if (si[r] == p) i.e., r = s[p] s1[p] = n1; s2[0] = n2; x1[n1] = x2[n2] = xs[r]; n1++; n2++; } } t1 = flutes_LMD(p+1, x1, ys, s1, newacc); t2 = flutes_LMD(d-p, x2, ys+p, s2, newacc); ll = t1.length + t2.length; coord1 = t1.branch[t1.branch[p].n].x; coord2 = t2.branch[t2.branch[0].n].x; if (t2.branch[0].x > flute_max(coord1, coord2)) ll -= t2.branch[0].x - flute_max(coord1, coord2); else if (t2.branch[0].x < flute_min(coord1, coord2)) ll -= flute_min(coord1, coord2) - t2.branch[0].x; } if (minl > ll) { minl = ll; free(bestt1.branch); free(bestt2.branch); bestt1 = t1; bestt2 = t2; bestbp = maxbp; } else { free(t1.branch); free(t2.branch); } } #if FLUTE_LOCAL_REFINEMENT==1 if (BreakInX(bestbp)) { t = hmergetree(bestt1, bestt2, s); local_refinement(&t, si[BreakPt(bestbp)]); } else { t = vmergetree(bestt1, bestt2); local_refinement(&t, BreakPt(bestbp)); } #else if (BreakInX(bestbp)) { t = hmergetree(bestt1, bestt2, s); } else { t = vmergetree(bestt1, bestt2); } #endif free(bestt1.branch); free(bestt2.branch); return t; } Tree dmergetree(Tree t1, Tree t2) { int i, d, prev, curr, next, offset1, offset2; Tree t; t.deg = d = t1.deg + t2.deg - 2; t.length = t1.length + t2.length; t.branch = (Branch *) malloc((2*d-2)*sizeof(Branch)); offset1 = t2.deg-2; offset2 = 2*t1.deg-4; for (i=0; i<=t1.deg-2; i++) { t.branch[i].x = t1.branch[i].x; t.branch[i].y = t1.branch[i].y; t.branch[i].n = t1.branch[i].n + offset1; } for (i=t1.deg-1; i<=d-1; i++) { t.branch[i].x = t2.branch[i-t1.deg+2].x; t.branch[i].y = t2.branch[i-t1.deg+2].y; t.branch[i].n = t2.branch[i-t1.deg+2].n + offset2; } for (i=d; i<=d+t1.deg-3; i++) { t.branch[i].x = t1.branch[i-offset1].x; t.branch[i].y = t1.branch[i-offset1].y; t.branch[i].n = t1.branch[i-offset1].n + offset1; } for (i=d+t1.deg-2; i<=2*d-3; i++) { t.branch[i].x = t2.branch[i-offset2].x; t.branch[i].y = t2.branch[i-offset2].y; t.branch[i].n = t2.branch[i-offset2].n + offset2; } prev = t2.branch[0].n + offset2; curr = t1.branch[t1.deg-1].n + offset1; next = t.branch[curr].n; while (curr != next) { t.branch[curr].n = prev; prev = curr; curr = next; next = t.branch[curr].n; } t.branch[curr].n = prev; return t; } Tree hmergetree(Tree t1, Tree t2, int s[]) { int i, prev, curr, next, extra, offset1, offset2; int p, ii, n1, n2, nn1, nn2; DTYPE coord1, coord2; Tree t; t.deg = t1.deg + t2.deg - 1; t.length = t1.length + t2.length; t.branch = (Branch *) malloc((2*t.deg-2)*sizeof(Branch)); offset1 = t2.deg-1; offset2 = 2*t1.deg-3; p = t1.deg - 1; n1 = n2 = 0; for (i=0; i p) { t.branch[i].x = t2.branch[n2].x; t.branch[i].y = t2.branch[n2].y; t.branch[i].n = t2.branch[n2].n + offset2; n2++; } else { t.branch[i].x = t2.branch[n2].x; t.branch[i].y = t2.branch[n2].y; t.branch[i].n = t2.branch[n2].n + offset2; nn1 = n1; nn2 = n2; ii = i; n1++; n2++; } } for (i=t.deg; i<=t.deg+t1.deg-3; i++) { t.branch[i].x = t1.branch[i-offset1].x; t.branch[i].y = t1.branch[i-offset1].y; t.branch[i].n = t1.branch[i-offset1].n + offset1; } for (i=t.deg+t1.deg-2; i<=2*t.deg-4; i++) { t.branch[i].x = t2.branch[i-offset2].x; t.branch[i].y = t2.branch[i-offset2].y; t.branch[i].n = t2.branch[i-offset2].n + offset2; } extra = 2*t.deg-3; coord1 = t1.branch[t1.branch[nn1].n].y; coord2 = t2.branch[t2.branch[nn2].n].y; if (t2.branch[nn2].y > flute_max(coord1, coord2)) { t.branch[extra].y = flute_max(coord1, coord2); t.length -= t2.branch[nn2].y - t.branch[extra].y; } else if (t2.branch[nn2].y < flute_min(coord1, coord2)) { t.branch[extra].y = flute_min(coord1, coord2); t.length -= t.branch[extra].y - t2.branch[nn2].y; } else t.branch[extra].y = t2.branch[nn2].y; t.branch[extra].x = t2.branch[nn2].x; t.branch[extra].n = t.branch[ii].n; t.branch[ii].n = extra; prev = extra; curr = t1.branch[nn1].n + offset1; next = t.branch[curr].n; while (curr != next) { t.branch[curr].n = prev; prev = curr; curr = next; next = t.branch[curr].n; } t.branch[curr].n = prev; return t; } Tree vmergetree(Tree t1, Tree t2) { int i, prev, curr, next, extra, offset1, offset2; DTYPE coord1, coord2; Tree t; t.deg = t1.deg + t2.deg - 1; t.length = t1.length + t2.length; t.branch = (Branch *) malloc((2*t.deg-2)*sizeof(Branch)); offset1 = t2.deg-1; offset2 = 2*t1.deg-3; for (i=0; i<=t1.deg-2; i++) { t.branch[i].x = t1.branch[i].x; t.branch[i].y = t1.branch[i].y; t.branch[i].n = t1.branch[i].n + offset1; } for (i=t1.deg-1; i<=t.deg-1; i++) { t.branch[i].x = t2.branch[i-t1.deg+1].x; t.branch[i].y = t2.branch[i-t1.deg+1].y; t.branch[i].n = t2.branch[i-t1.deg+1].n + offset2; } for (i=t.deg; i<=t.deg+t1.deg-3; i++) { t.branch[i].x = t1.branch[i-offset1].x; t.branch[i].y = t1.branch[i-offset1].y; t.branch[i].n = t1.branch[i-offset1].n + offset1; } for (i=t.deg+t1.deg-2; i<=2*t.deg-4; i++) { t.branch[i].x = t2.branch[i-offset2].x; t.branch[i].y = t2.branch[i-offset2].y; t.branch[i].n = t2.branch[i-offset2].n + offset2; } extra = 2*t.deg-3; coord1 = t1.branch[t1.branch[t1.deg-1].n].x; coord2 = t2.branch[t2.branch[0].n].x; if (t2.branch[0].x > flute_max(coord1, coord2)) { t.branch[extra].x = flute_max(coord1, coord2); t.length -= t2.branch[0].x - t.branch[extra].x; } else if (t2.branch[0].x < flute_min(coord1, coord2)) { t.branch[extra].x = flute_min(coord1, coord2); t.length -= t.branch[extra].x - t2.branch[0].x; } else t.branch[extra].x = t2.branch[0].x; t.branch[extra].y = t2.branch[0].y; t.branch[extra].n = t.branch[t1.deg-1].n; t.branch[t1.deg-1].n = extra; prev = extra; curr = t1.branch[t1.deg-1].n + offset1; next = t.branch[curr].n; while (curr != next) { t.branch[curr].n = prev; prev = curr; curr = next; next = t.branch[curr].n; } t.branch[curr].n = prev; return t; } void local_refinement(Tree *tp, int p) { int d, dd, i, ii, j, prev, curr, next, root; int SteinerPin[2*FLUTE_MAXD], index[2*FLUTE_MAXD]; DTYPE x[FLUTE_MAXD], xs[D], ys[D]; int ss[D]; Tree tt; d = tp->deg; root = tp->branch[p].n; // Reverse edges to point to root prev = root; curr = tp->branch[prev].n; next = tp->branch[curr].n; while (curr != next) { tp->branch[curr].n = prev; prev = curr; curr = next; next = tp->branch[curr].n; } tp->branch[curr].n = prev; tp->branch[root].n = root; // Find Steiner nodes that are at pins for (i=d; i<=2*d-3; i++) SteinerPin[i] = -1; for (i=0; ibranch[i].n; if (tp->branch[i].x == tp->branch[next].x && tp->branch[i].y == tp->branch[next].y) SteinerPin[next] = i; // Steiner 'next' at Pin 'i' } SteinerPin[root] = p; // Find pins that are directly connected to root dd = 0; for (i=0; ibranch[i].n; if (SteinerPin[curr] == i) curr = tp->branch[curr].n; while (SteinerPin[curr] < 0) curr = tp->branch[curr].n; if (curr == root) { x[dd] = tp->branch[i].x; if (SteinerPin[tp->branch[i].n] == i && tp->branch[i].n != root) index[dd++] = tp->branch[i].n; // Steiner node else index[dd++] = i; // Pin } } if (4 <= dd && dd <= D) { // Find Steiner nodes that are directly connected to root ii=dd; for (i=0; ibranch[index[i]].n; while (SteinerPin[curr] < 0) { index[ii++] = curr; SteinerPin[curr] = INT_MAX; curr = tp->branch[curr].n; } } index[ii] = root; for (ii=0; iibranch[index[ii]].y; } tt = flutes_LD(dd, xs, ys, ss); // Find new wirelength tp->length += tt.length; for (ii=0; ii<2*dd-3; ii++) { i = index[ii]; j = tp->branch[i].n; tp->length -= ADIFF(tp->branch[i].x, tp->branch[j].x) + ADIFF(tp->branch[i].y, tp->branch[j].y); } // Copy tt into t for (ii=0; iibranch[index[ii]].n = index[tt.branch[ii].n]; } for (; ii<=2*dd-3; ii++) { tp->branch[index[ii]].x = tt.branch[ii].x; tp->branch[index[ii]].y = tt.branch[ii].y; tp->branch[index[ii]].n = index[tt.branch[ii].n]; } free(tt.branch); } return; } DTYPE wirelength(Tree t) { int i, j; DTYPE l=0; for (i=0; i<2*t.deg-2; i++) { j = t.branch[i].n; l += ADIFF(t.branch[i].x, t.branch[j].x) + ADIFF(t.branch[i].y, t.branch[j].y); } return l; } void printtree(Tree t) { int i; for (i=0; i