1 /*
2  *   Copyright (C) 1988-1991 Yale University
3  *
4  *   This work is distributed in the hope that it will be useful; you can
5  *   redistribute it and/or modify it under the terms of the
6  *   GNU General Public License as published by the Free Software Foundation;
7  *   either version 2 of the License,
8  *   or any later version, on the following conditions:
9  *
10  *   (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS
11  *   ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE,
12  *   SALE OR
13  *   OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY
14  *   PATENT OR
15  *   OTHER RIGHTS NOT VESTED IN YALE.
16  *
17  *   (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND
18  *   WARRANTIES
19  *   WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED,
20  *   INCLUDING,
21  *   BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
22  *   PARTICULAR
23  *   PURPOSE.
24  *
25  *   (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES
26  *   WHATSOEVER TO
27  *   ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN
28  *   ARTICLE
29  *   (a) AND (b) above.
30  *
31  *   (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS,
32  *   EMPLOYEES AND
33  *   AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR
34  *   INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE
35  *   ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE
36  *   POSSIBILITY OF THE FOREGOING.
37  *
38  */
39 
40 /* -----------------------------------------------------------------
41 FILE:	    sortpad.c
42 DESCRIPTION:This file contains the utility routines to sort pads
43 	    for the new pad routines.
44 CONTENTS:
45 DATE:	    Aug 12, 1988
46 REVISIONS:  Sun Jan 20 21:34:36 PST 1991 - ported to AIX.
47 	    Sat Feb 23 00:17:28 EST 1991 - added placepads algorithm.
48 	    Tue Mar 12 17:05:03 CST 1991 - fixed initialization problem
49 		with permutation.
50 ----------------------------------------------------------------- */
51 
52 #include <custom.h>
53 #include <pads.h>
54 #include <yalecad/debug.h>
55 
56 
57 
58 static INT compare_pads();
59 static INT sort_by_pos();
60 static void install_pad_groups();
61 static void permute_pads();
62 
63 
64 
sort_pads()65 void sort_pads()
66 {
67     INT i ;                /* pad counter */
68     INT pos ;              /* position in place array */
69     INT compare_pads() ;   /* how to sort the pads initially */
70     INT sort_by_pos() ;    /* how to sort the pads */
71     PADBOXPTR pad ;        /* current pad */
72 
73     /* first perform an initial sort to order the pads by side, hierarchy, */
74     /* and position on the side. */
75     Yquicksort( &(sortarrayG[1]), totalpadsG, sizeof(PADBOXPTR), compare_pads );
76     D( "placepads/after_sort",
77 	print_pads("pads after initial sort\n",sortarrayG, totalpadsG ) ;
78     ) ;
79 
80     /* Now make sure the pads are permuted correctly */
81     for( i = 1; i <= totalpadsG; i++ ){
82 	pad = sortarrayG[i];
83 	if( pad->hierarchy == ROOT ){
84 	    permute_pads( pad ) ;
85 	}
86     }
87 
88     /* NOW INSTALL THE PAD GROUPS IN THEIR PROPER ORDER. There are 2 cases: */
89     /* CASE I CONTIGUOUS INSURE THAT GROUP REMAIN INTACT */
90     pos = 1 ;
91     for( i = 1; i <= totalpadsG; i++ ){
92 	pad = sortarrayG[i];
93 	if( pad->hierarchy == ROOT || pad->hierarchy == NONE ){
94 	    install_pad_groups( pad, &pos ) ;
95 	}
96     }
97     D( "placepads/after_install",
98 	print_pads("pads after install\n",placearrayG,numpadsG);
99     ) ;
100 
101     if(!(contiguousG)){
102 	/* CASE II -  LEAVES ARE ALIGNED LIKE ORDINARY PADS IF THEY HAVE NO */
103 	/* CONSTRAINTS SUCH AS ORDER OR PERMUTE.  **/
104 	Yquicksort( &(placearrayG[1]), numpadsG, sizeof(PADBOXPTR), sort_by_pos ) ;
105 	D( "placepads/after_ncontsort",
106 	    print_pads("pads after noncontiguous sort\n",placearrayG,numpadsG);
107 	) ;
108     }
109 
110 } /* end SortPads */
111 /* ***************************************************************** */
112 
113 /*** compare_pads() RETURNS TRUE IF ARG1 > ARG2 BY ITS OWN RULES **/
compare_pads(padptr1,padptr2)114 static INT compare_pads( padptr1, padptr2 )
115 PADBOXPTR *padptr1, *padptr2 ;
116 {
117     PADBOXPTR pad1, pad2;
118 
119     pad1 = *padptr1 ;
120     pad2 = *padptr2 ;
121 
122     if( pad1->padside != pad2->padside) {
123 	return( pad1->padside - pad2->padside ) ;
124     }
125     if( pad1->hierarchy != pad2->hierarchy ){
126 	/*** MOVE ROOTS TO THE BEGINNING OF ARRAY MOVE */
127 	/* LEAVES ARE SEPARATED, ROOTS ARE MERGED **/
128 	if( pad1->hierarchy == SUBROOT ){
129 	    return( 1 ) ;
130 	} else if( pad2->hierarchy == SUBROOT ){
131 	    return( 0 ) ;
132 	} else if( pad1->hierarchy == LEAF ){
133 	    return( 1 ) ;
134 	} else if( pad2->hierarchy == LEAF ){
135 	    return( 0 ) ;
136 	}
137     }
138 
139     if( pad1->position == pad2->position ){
140 	return( pad1->tiebreak - pad2->tiebreak ) ;
141     } else {
142 	return( pad1->position - pad2->position ) ;
143     }
144 
145 } /* end compare_pads */
146 /* ***************************************************************** */
147 
sort_by_pos(padptr1,padptr2)148 static INT sort_by_pos( padptr1, padptr2 )
149 PADBOXPTR *padptr1, *padptr2 ;
150 {
151     PADBOXPTR pad1, pad2;
152     BOOL pad1fixed, pad2fixed ;
153 
154     pad1 = *padptr1 ;
155     pad2 = *padptr2 ;
156 
157     if( pad1->padside != pad2->padside) {
158 	return( pad1->padside - pad2->padside ) ;
159     }
160     if( pad1->ordered || pad1->permute ){
161 	pad1fixed = TRUE ;
162     } else {
163 	pad1fixed = FALSE ;
164     }
165     if( pad2->ordered || pad2->permute ){
166 	pad2fixed = TRUE ;
167     } else {
168 	pad2fixed = FALSE ;
169     }
170     if( pad1fixed && pad2fixed && !(contiguousG) ){
171 	return( 0 ) ;
172     } else if( pad1fixed && contiguousG ){
173 	return( 0 ) ;
174     } else if( pad2fixed && contiguousG ){
175 	return( 1 ) ;
176     } else if( pad1->position == pad2->position ){
177 	return( pad1->tiebreak - pad2->tiebreak ) ;
178     } else {
179 	return( pad1->position - pad2->position ) ;
180     }
181 
182 } /* end sort_by_pos */
183 /* ***************************************************************** */
184 
install_pad_groups(pad,position)185 static void install_pad_groups( pad, position )
186 PADBOXPTR pad ;
187 INT *position ;
188 {
189     INT i ;                      /* pad counter */
190     INT howmany ;                /* number of pads in group */
191     INT initial_position ;       /* position of next open place in placearray */
192     INT sort_by_pos() ;          /* how to sort the pads */
193     PADBOXPTR child ;            /* current child */
194     PADBOXPTR *temparray ;       /* temporary array to sort pads */
195 
196     initial_position = *position ;
197     if( pad->padtype == PADCELLTYPE ){
198 	placearrayG[initial_position] = pad ;
199 	*position = ++initial_position ;
200     } else {
201 	howmany = pad->children[HOWMANY] ;
202 	temparray = (PADBOXPTR *) Yvector_alloc( 1,howmany,sizeof(PADBOXPTR) ) ;
203 	for( i = 1 ;i <= howmany ; i++ ){
204 	    child = padarrayG[ pad->children[i] ] ;
205 	    temparray[i] = child ;
206 	}
207 	/* now sort the subroots or leaves to obey both order constraints */
208 	/* and permutation constraints.  Otherwise try to sort by opt. pos.*/
209 	Yquicksort( &(temparray[1]), howmany, sizeof(PADBOXPTR), sort_by_pos ) ;
210 
211 	/* now that we have subroots or leaves in correct order */
212 	/* look at next level down */
213 	for( i = 1 ;i <= howmany ; i++ ){
214 	    child = temparray[ i ] ;
215 	    install_pad_groups( child, position ) ;
216 	}
217 	Yvector_free( temparray, 1, sizeof(PADBOXPTR) ) ;
218     }
219 } /* end install_pad_groups */
220 /* ***************************************************************** */
221 
permute_pads(pad)222 static void permute_pads( pad )
223 PADBOXPTR pad ;
224 {
225     INT tmp ;                 /* used to reverse permutable pads */
226     INT j, k ;                /* used to reverse pads */
227     INT i ;                   /* padcounter */
228     INT howmany ;             /* number of children in current padgroup */
229     INT max_pos ;             /* max. value of the ideal positions of pad in pg */
230     INT min_pos ;             /* min. value of the ideal positions of pad in pg */
231     INT forward_cost ;        /* cost to place pads in current order */
232     INT bakward_cost ;        /* cost to place pads in reverse order */
233     INT proposed_fpos ;       /* proposed uniformly spaced pos in forward order */
234     INT proposed_bpos ;       /* proposed uniformly spaced pos in bakward order */
235     INT *array ;              /* sort the children */
236     DOUBLE spacing ;          /* spacing if we place pads in pg uniformly */
237     PADBOXPTR child ;         /* current child */
238 
239     if( pad->permute ){
240 	/* first calculate span of padgroup */
241 	howmany = pad->children[HOWMANY] ;
242 	ASSERTNRETURN( howmany >= 2,"permute_pads",
243 	    "Must have at least 2 pads in a padgroup\n");
244 	child = padarrayG[pad->children[1]];
245 	min_pos = child->position ;
246 	max_pos = child->position ;
247 	for( i = 2; i <= howmany ; i++ ){
248 	    child = padarrayG[pad->children[i]];
249 	    min_pos = MIN( child->position, min_pos ) ;
250 	    max_pos = MAX( child->position, max_pos ) ;
251 	}
252 	/* now find the cost if we evenly space the pads over that region */
253 	spacing = (DOUBLE) (max_pos - min_pos) / (DOUBLE) (howmany - 1) ;
254 	forward_cost = 0 ;
255 	bakward_cost = 0 ;
256 	for( i = 1; i <= howmany ; i++ ){
257 	    child = padarrayG[pad->children[i]];
258 	    proposed_fpos = min_pos + ROUND( (i - 1) * spacing ) ;
259 	    proposed_bpos = max_pos - ROUND( (i - 1) * spacing ) ;
260 	    forward_cost += ABS( child->position - proposed_fpos ) ;
261 	    bakward_cost += ABS( child->position - proposed_bpos ) ;
262 	}
263 
264 	if( bakward_cost < forward_cost ) {
265 	    /* we need to reverse the permutation */
266 	    array = pad->children + 1;
267 	    j = howmany - 1;
268 	    k = 0;
269 	    while( k < j ){
270 		tmp        = array[j];
271 		array[j--] = array[k];
272 		array[k++] = tmp;
273 	    }
274 	}
275    }
276    /*** NEED TO CHECK THE CHILDREN REGARDLESS OF THE PERMUTABILITY OF
277 	THE PARENT ROOT */
278    for( i = 1; i <= pad->children[HOWMANY]; i++ ){
279 	child = padarrayG[pad->children[i]];
280 	if( child->hierarchy == SUBROOT){
281 	    permute_pads( child ) ;
282 	}
283     }
284 
285 } /* end permute_pads */
286 /* ***************************************************************** */
287