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