1 /*
2 * Copyright (C) 1988-1990 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: window.c
42 DESCRIPTION:new window limiter routines due to Jimmy Lamm
43 CONTENTS: DOUBLE eval_ratio(percentWindow)
44 DOUBLE *percentWindow ;
45 init_control()
46 pick_position(INT *, INT *, int, int)
47 update_control(a)
48 fix_window()
49 update_window_size( iteration )
50 DOUBLE iteration ;
51 DATE: Feb 29, 1988
52 REVISIONS: Apr 23, 1988 - added fix_window for low temp anneal
53 Oct 21, 1988 - changed steps per cell and add graph func.
54 Oct 26, 1988 - add pick_neighborhood and fixed bug in
55 pick_position.
56 Nov 20, 1988 - fixed chip aspect ratio.
57 Jan 15, 1989 - added update_window_size, and new eval ratio
58 for curve-fit controller.
59 Jan 29, 1989 - changed to YmsgG.
60 Mar 02, 1989 - move temp defintions to temp.h
61 Apr 09, 1989 - fixed bug in pick_position and
62 pick_neighborhood so that cells can't jump outside region.
63 ----------------------------------------------------------------- */
64
65 #include <custom.h>
66 #include <temp.h>
67 #include <yalecad/debug.h>
68
69 #define AC0 0.90 /*** 0.75 ***/
70 #define AC1 0.44 /*** 0.44 ***/
71 #define AC2 0.06 /*** 0.08 ***/
72
73 #define PT1 0.15 /*** 0.15 ***/
74 #define PT2 0.52 /*** 0.52 ***/
75 #define PT3 1.00 /*** 1.00 ***/
76
77 #define LAC1 (log(AC1))
78 #define LAC2 (log(AC2))
79
80 #define STEPSPERCEL 0.01 /* was 0.01 */
81
82 #define TABLIMIT 4096 /*** simple table lookup for log. ***/
83 #define TABSHIFT 19
84 #define TABMASK 0xfff
85 #define TABOFFSET 0x40000
86 #define RANDFACT (1.0 / INT_MAX)
87 #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l))
88
89 static DOUBLE xadjustmentS,xalS,min_xalphaS,max_xalphaS;/** x control **/
90 static DOUBLE yadjustmentS,yalS,min_yalphaS,max_yalphaS;/** y control **/
91 static DOUBLE total_stepS;
92 static DOUBLE log_tabS[TABLIMIT];
93 static DOUBLE tauXS, tauYS ; /* exp. decay time constants for window */
94
eval_ratio(iteration)95 DOUBLE eval_ratio( iteration )
96 INT iteration ;
97 {
98 if( iteration >= TURNOFFT ){
99 return( (DOUBLE) 1.0 ) ;
100 } else if( iteration < 0 ){
101 return( (DOUBLE) 0.0 ) ;
102 } else {
103 return( (DOUBLE) iteration / TURNOFFT ) ;
104 }
105 }
106
107 /* *****************************************************************
108 init_control - initialize range limiter.
109 */
init_control(first)110 void init_control(first)
111 BOOL first ;
112 {
113 INT i;
114 DOUBLE area ;
115
116 #define FRACTION 0.10
117
118 /*** initialize move generation parameters ***/
119 /* minxspan = mean_width + 3 sigma variation */
120 area = mean_cellAreaG + 3 * dev_cellAreaG ;
121
122 /*** average min. window size ***/
123 min_xalphaS = 0.5 * sqrt( area / chipaspectG ) ;
124 min_yalphaS = 0.5 * sqrt( chipaspectG * area ) ;
125
126 min_xalphaS = MIN( min_xalphaS, FRACTION * (DOUBLE) bdxlengthG ) ;
127 min_yalphaS = MIN( min_yalphaS, FRACTION * (DOUBLE) bdylengthG ) ;
128 OUT2( "min_xalpha:%4.2lf\n", min_xalphaS ) ;
129 OUT2( "min_yalpha:%4.2lf\n", min_yalphaS ) ;
130
131 if (init_accG >= 0.44) {
132 max_xalphaS = bdxlengthG; /*** average max. window size ***/
133 max_yalphaS = bdylengthG; /*** average max. window size ***/
134 } else {
135 max_xalphaS = min_xalphaS; /*** no adjustments ***/
136 max_yalphaS = min_yalphaS;
137 }
138
139 total_stepS = STEPSPERCEL * numcellsG;
140 xadjustmentS = (max_xalphaS - min_xalphaS) / total_stepS;
141 yadjustmentS = (max_yalphaS - min_yalphaS) / total_stepS;
142
143 xalS = max_xalphaS;
144 yalS = max_yalphaS;
145
146 if (first) {
147 xalS = max_xalphaS;
148 yalS = max_yalphaS;
149 /* determine tauXS */
150 tauXS = - log( (min_xalphaS/max_xalphaS)) / (MEDTEMP - HIGHTEMP) ;
151 tauYS = - log( (min_yalphaS/max_yalphaS)) / (MEDTEMP - HIGHTEMP) ;
152 }
153
154 /*** prepare lookup table ***/
155 for (i=0; i<TABLIMIT; i++)
156 log_tabS[i] = log(((i << TABSHIFT) + TABOFFSET) * RANDFACT);
157 }
158
159 /* *****************************************************************
160 pick_positon - pick place to move within range limiter.
161 */
pick_position(x,y,ox,oy)162 void pick_position(x,y,ox,oy)
163 INT *x,*y,ox,oy;
164 {
165 register INT i,m,n;
166
167 /* get exponentially distributed random number around old x */
168 for (i=0; i<2; i++) {
169 m = RAND;
170 n = -xalS * log_tabS[(m >> TABSHIFT) & TABMASK];
171 if (m & 0x10000){
172 n = -n;
173 }
174 n += ox;
175 /* check for inside core */
176 if (n >= blocklG && n <= blockrG){
177 /* hate to use a goto here but it saves another test */
178 goto DONEX ;
179 }
180 }
181 /* by default -we have failed. Use boundary */
182 if (n < blocklG) {
183 if (ox > blockrG){
184 ox = blockrG;
185 } else if (ox < blocklG){
186 ox = blocklG;
187 }
188 n = PICK_INT(blocklG,ox);
189 } else if (n > blockrG) {
190 if (ox < blocklG){
191 ox = blocklG;
192 } else if (ox > blockrG){
193 ox = blockrG;
194 }
195 n = PICK_INT(ox,blockrG);
196 }
197 DONEX: *x = n;
198
199 /* get exponentially distributed random number around old y */
200 for (i=0; i<2; i++) {
201 m = RAND;
202 n = -yalS * log_tabS[(m >> TABSHIFT) & TABMASK];
203 if (m & 0x10000){
204 n = -n;
205 }
206 n += oy;
207 /* check for inside core */
208 if (n >= blockbG && n <= blocktG){
209 *y = n;
210 return;
211 }
212 }
213 /* if fail use boundary */
214 if (n < blockbG) {
215 if (oy > blocktG){
216 oy = blocktG;
217 } else if (oy < blockbG){
218 oy = blockbG;
219 }
220 n = PICK_INT(blockbG,oy);
221 } else if (n > blocktG) {
222 if (oy < blockbG){
223 oy = blockbG;
224 } else if (oy > blocktG){
225 oy = blocktG;
226 }
227 n = PICK_INT(oy,blocktG);
228 }
229 *y = n;
230 }
231
232 /* *****************************************************************
233 pick_neighborhood - pick place to move within neighborhood while
234 still using range limiter.
235 */
pick_neighborhood(x,y,ox,oy,fixptr)236 void pick_neighborhood(x,y,ox,oy,fixptr)
237 INT *x,*y,ox,oy;
238 FIXEDBOXPTR fixptr ;
239 {
240 register INT i,m,n;
241 INT xjump, yjump ;
242
243 #define DIV_2 >> 1
244
245 /* check if x range limiter is smaller than neighborhood */
246 if( xalS > fixptr->xspan ){
247 ox = fixptr->xcenter ; /* jump from center of neighborhood */
248 xjump = fixptr->xspan DIV_2 ; /* average jump half the xspan */
249 } else {
250 /* we must use range limiter and jump from old coordinates */
251 xjump = xalS ;
252 }
253
254 /* get exponentially distributed random number around old x */
255 for (i=0; i<2; i++) {
256 m = RAND;
257 n = -xjump * log_tabS[(m >> TABSHIFT) & TABMASK];
258 if (m & 0x10000){
259 n = -n;
260 }
261 n += ox;
262 /* check for inside neighborhood */
263 if (n >= fixptr->x1 && n <= fixptr->x2 ){
264 /* hate to use a goto here but it saves another test */
265 goto DONEX ;
266 }
267 }
268 /* by default - we have failed. Use neighborhood boundary */
269 if (n < fixptr->x1 ) {
270 if (ox > fixptr->x2 ){
271 ox = fixptr->x2 ;
272 } else if (ox < fixptr->x1 ){
273 ox = fixptr->x1 ;
274 }
275 n = PICK_INT(fixptr->x1 ,ox);
276 } else if (n > fixptr->x2 ) {
277 if (ox < fixptr->x1 ){
278 ox = fixptr->x1 ;
279 } else if (ox > fixptr->x2 ){
280 ox = fixptr->x2 ;
281 }
282 n = PICK_INT(ox,fixptr->x2 );
283 }
284 DONEX: *x = n;
285
286 /* check if y range limiter is smaller than neighborhood */
287 if( yalS > fixptr->yspan ){
288 oy = fixptr->ycenter ; /* jump from center of neighborhood */
289 yjump = fixptr->yspan DIV_2 ; /* average jump half the yspan */
290 } else {
291 /* we must use range limiter and jump from old coordinates */
292 yjump = yalS ;
293 }
294 /* get exponentially distributed random number around old y */
295 for (i=0; i<2; i++) {
296 m = RAND;
297 n = -yjump * log_tabS[(m >> TABSHIFT) & TABMASK];
298 if (m & 0x10000){
299 n = -n;
300 }
301 n += oy;
302 /* check for inside core */
303 if (n >= fixptr->y1 && n <= fixptr->y2){
304 *y = n;
305 return;
306 }
307 }
308 /* if fail use neighborhood boundary */
309 if (n < fixptr->y1) {
310 if (oy > fixptr->y2){
311 oy = fixptr->y2;
312 } else if (oy < fixptr->y1){
313 oy = fixptr->y1;
314 }
315 n = PICK_INT(fixptr->y1,oy);
316 } else if (n > fixptr->y2) {
317 if (oy < fixptr->y1){
318 oy = fixptr->y1;
319 } else if (oy > fixptr->y2){
320 oy = fixptr->y2;
321 }
322 n = PICK_INT(oy,fixptr->y2);
323 }
324 *y = n;
325 } /* end pick_neighborhood */
326
update_window_size(iteration)327 void update_window_size( iteration )
328 DOUBLE iteration ;
329 {
330 if( iteration <= HIGHTEMP ){
331 xalS = max_xalphaS ;
332 yalS = max_yalphaS ;
333 } else if( iteration <= MEDTEMP ){
334 /* exponential decay xal and yal */
335 /* --------------------------------------------------------
336 xal = max_xalpha * exp( - tauXS * ( iteration - HIGHTEMP ))
337 yal = max_yalpha * exp( - tauYS * ( iteration - HIGHTEMP ))
338 -------------------------------------------------------- */
339 xalS = yalS = iteration - HIGHTEMP ;
340 xalS *= - tauXS ;
341 xalS = max_xalphaS * exp( xalS ) ;
342
343 yalS *= - tauYS ;
344 yalS = max_yalphaS * exp( yalS ) ;
345
346 } else { /* low temp */
347 xalS = min_xalphaS ;
348 yalS = min_yalphaS ;
349 }
350 /*
351 OUT5(" xal = %4.2le yal = %4.2le stepsG = %4.2le T=%4.2le\n",
352 xalS, yalS, stepsG, TG );
353 */
354
355 }
356
fix_window()357 void fix_window()
358 {
359 /*** set window to minimum for low temp anneal ***/
360 xalS = min_xalphaS;
361 yalS = min_yalphaS;
362 }
363
364 /* *****************************************************************
365 save_window - save window parameters for restart
366 */
367 /* static declaration for restoring state for low temp anneal */
368 static DOUBLE ws_xalS;
369 static DOUBLE ws_yalS;
370 static DOUBLE ws_ratioS ;
371
save_window(fp)372 void save_window( fp )
373 FILE *fp ;
374 {
375 if( fp ){ /* if a file pointer is given write to file */
376 fprintf(fp,"# window parameters:\n") ;
377 fprintf(fp,"%f %f %f\n",xalS,yalS,ratioG );
378 } else { /* otherwise save in memory */
379 ws_xalS = xalS ;
380 ws_yalS = yalS ;
381 ws_ratioS = ratioG ;
382 }
383 }
384
385 /* *****************************************************************
386 read_window - read window parameters for restart
387 */
read_window(fp)388 INT read_window( fp )
389 FILE *fp ;
390 {
391 INT errors = 0 ;
392 if( fp ){ /* if file pointer given restore from file */
393 fscanf(fp,"%[ #:a-zA-Z]\n",YmsgG ); /* throw away comment */
394 fscanf(fp,"%lf %lf %lf\n",&xalS,&yalS,&ratioG);
395 /* try to detect errors */
396 if( xalS < 0.0 ){
397 M(ERRMSG,"read_window","Restart file: xal negative\n") ;
398 errors++ ;
399 }
400 if( yalS < 0.0 ){
401 M(ERRMSG,"read_window","Restart file: yal negative\n") ;
402 errors++ ;
403 }
404 if( ratioG < 0.0 ){
405 M(ERRMSG,"read_window","Restart file: ratio negative\n") ;
406 errors++ ;
407 }
408 if( ratioG > 1.0 ){
409 M(ERRMSG,"read_window","Restart file: ratio > 1\n") ;
410 errors++ ;
411 }
412 } else { /* restore from memory */
413 xalS = ws_xalS ;
414 yalS = ws_yalS ;
415 ratioG = ws_ratioS ;
416 }
417 return(errors) ;
418 } /* end read_window */
419