1 /*
2  *   Copyright (C) 1989-1992 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:	    reconfig.c
42 DESCRIPTION:cell topology configuration with feed estimation.
43 CONTENTS:   INT reconfig()
44 DATE:	    Mar 27, 1989
45 REVISIONS:  Thu Jan 31 15:56:39 EST 1991 - now only call findcostf
46 		if criteria is met.  Instead call recompute_wirecosts
47 		and recompute_timecosts.
48 	    Wed Jul 24 20:58:00 CDT 1991 - reset the MIN_FEED_RATIO number.
49 	    Fri Sep  6 15:19:05 CDT 1991 - now calculate the feed
50 		taper from previous run.
51 	    Wed Sep 11 11:27:46 CDT 1991 - added user
52 		output info for blocks.
53 ----------------------------------------------------------------- */
54 
55 #include "standard.h"
56 #include "readpar.h"
57 #include "main.h"
58 #include <yalecad/message.h>
59 #include <yalecad/string.h>
60 #include <yalecad/debug.h>
61 
62 #if SIZEOF_VOID_P == 64
63 #define INTSCANSTR "%ld"
64 #else
65 #define INTSCANSTR "%d"
66 #endif
67 
68 #define MIN_FEED_RATIO     0.66
69 
70 /* global definitions */
71 extern BOOL no_feed_estG ;
72 extern INT fdWidthG ;
73 extern INT totalRG ;
74 extern INT extra_cellsG ;
75 extern INT *feeds_in_rowG ;
76 
77 /* static definitions */
78 static BOOL feed_length_setS = TRUE ;
79 static INT feed_lengthS ;             /* the current feed length */
80 static INT old_feed_lengthS = 0 ; /* the feed length from the last iteration */
81 static BOOL print_desiredS = TRUE ;
82 
reconfig()83 INT reconfig()
84 {
85 
86     INT block ;
87     INT total_desire ;
88 
89     if( print_desiredS ) {
90 	print_desiredS = FALSE ;
91 
92 	total_desire = 0 ;
93 	for( block = 1 ; block <= numRowsG ; block++ ) {
94 	    total_desire += barrayG[block]->desire ;
95 	    fprintf(fpoG,"block:%d desire:%d\n",block,barrayG[block]->desire);
96 	}
97 	fprintf(fpoG,"Total Desired Length: %d\n", total_desire ) ;
98     }
99 
100     /* place the pads */
101     placepads() ;
102 
103     /* call this since pad placement may change costs */
104     funccostG = recompute_wirecost() ;
105     timingcostG = recompute_timecost() ;
106 
107     return( 0 ) ;
108 
109 } /* end reconfig */
110 
111 
configuref()112 static void configuref()
113 {
114     INT row ;
115     INT cell ;
116     INT core_left ;
117     INT core_right ;
118     INT shift_amount ;
119     INT extra_shift , tmp ;
120 
121 
122     /* see if any rows would be completely filled with feeds */
123     extra_shift = 0 ;
124     for( row = 1 ; row <= numRowsG ; row++ ) {
125 	tmp = feeds_in_rowG[row] * fdWidthG ;
126 	if( tmp > barrayG[row]->orig_desire ) {
127 	    extra_shift += tmp - barrayG[row]->orig_desire ;
128 	}
129     }
130 
131     feed_lengthS -= extra_shift ;
132 
133     shift_amount = (feed_lengthS / numRowsG) - (old_feed_lengthS / numRowsG) ;
134     if( shift_amount == 0 ) {
135 	for( row = 1 ; row <= numRowsG ; row++ ) {
136 	    barrayG[row]->oldsize  = 0 ;
137 	}
138 	return ;
139     }
140 
141     core_right = INT_MIN ;
142     core_left  = INT_MAX ;
143     for( row = 1 ; row <= numRowsG ; row++ ) {
144 	if( barrayG[row]->bxcenter + barrayG[row]->bleft < core_left ) {
145 	    core_left = barrayG[row]->bxcenter + barrayG[row]->bleft ;
146 	}
147 	totalRG += shift_amount ;
148 	barrayG[row]->bright  += shift_amount ;
149 	barrayG[row]->blength += shift_amount ;
150 	barrayG[row]->desire  += shift_amount ;
151 	barrayG[row]->oldsize  = 0 ;
152 	if( barrayG[row]->bxcenter + barrayG[row]->bright > core_right ) {
153 	    core_right = barrayG[row]->bxcenter + barrayG[row]->bright ;
154 	}
155     }
156 
157     for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) {
158 	if( carrayG[cell]->cclass < 0 ) {
159 	    if( carrayG[cell]->border < 0 ) {
160 		carrayG[cell]->cxcenter += shift_amount ;
161 	    }
162 	}
163     }
164 
165     old_feed_lengthS = feed_lengthS ;
166 
167 
168 } /* end configuref */
169 
read_feeds(fp)170 void read_feeds( fp )
171 FILE *fp ;
172 {
173     fscanf( fp , INTSCANSTR , &feed_lengthS ) ;
174     feed_length_setS = TRUE ;
175 } /* end read_feeds */
176 
save_feeds(fp)177 void save_feeds( fp )
178 FILE *fp ;
179 {
180     fprintf( fp, "%d\n", feed_lengthS ) ;
181 } /* end save_feeds */
182 
183 /* ***********************************************************
184     Use .pl2 to find the number of rows in the output .pl1 file.
185     Read the .pl1 to find out the number of explicit feeds.
186     We can then set the feed taper for each row.  First
187     we assume that we have the same number of rows.  If
188     we don't, then we will bin the rows to smooth the
189     function and approximate.
190    *********************************************************** */
read_feed_data()191 BOOL read_feed_data()
192 {
193 
194 #define EQUAL_CASE        0   /* equal number of rows */
195 #define LESS_ROWS_CASE    1   /* currently have less rows */
196 #define MORE_ROWS_CASE    2   /* currently have more rows */
197 
198     INT row ;                 /* counter */
199     INT numtokens ;           /* number of tokens on the line */
200     INT pl1_rows ;            /* the number of row found in .pl2 */
201     INT pl1_case ;            /* which of 3 cases we have */
202     INT row_in_pl1 ;          /* the feed was found in this row */
203     INT start_row ;           /* the first row in case 3 */
204     INT end_row ;             /* the last row in case 3 */
205     FILE *fp ;                /* current file pointer */
206     DOUBLE *smooth ;          /* used to calculate MORE_ROWS case */
207     DOUBLE value ;            /* distribute feed over mult. rows */
208     char filename[LRECL] ;    /* name of the file */
209     char buffer[LRECL] ;      /* read string into buffer */
210     char *bufferptr ;         /* start of the buffer */
211     char **tokens ;           /* tokens on the line */
212 
213 	/* only process this file once */
214     static BOOL already_processedL = FALSE ;
215 	/* save the result for future use. Default no feeds */
216     static BOOL feed_statusL = FALSE ;
217 
218     if( already_processedL ){
219 	/*
220 	    We only need to call routine once.
221 	    Return the saved result.
222 	*/
223 	return( feed_statusL ) ;
224     }
225     already_processedL = TRUE ;
226     /* If we get here, this is the first time try to open .pl2 */
227     sprintf( filename, "%s.pl2", cktNameG ) ;
228     fp = TWOPEN( filename, "r", NOABORT ) ;
229     if(!(fp)){
230 	/* no feed data present return false */
231 	return( FALSE ) ;
232     }
233     /***********************************************************
234     * Read from circuitName.pl2 file.
235     ***********************************************************/
236     pl1_rows = 0 ;
237     while( bufferptr = fgets( buffer, LRECL, fp ) ){
238 	tokens = Ystrparser( bufferptr, " \t\n", &numtokens ) ;
239 	if( numtokens != 7 ){
240 	    continue ;
241 	}
242 	row = atoi( tokens[0] ) ;
243 	if( row > 0 ){
244 	    /* make sure the last two fields are zero */
245 	    if( atoi(tokens[5]) == 0 && atoi(tokens[6]) == 0 ){
246 		pl1_rows = row ;
247 	    }
248 	}
249     }
250     TWCLOSE( fp ) ;
251 
252     if( pl1_rows <= 0 ){
253 	/* no valid feed data present return false */
254 	return( FALSE ) ;
255     }
256 
257     /***********************************************************
258     * Now set the case.  Easy case I. pl1_rows == numRowsG.
259     * case II.  pll1_rows > numRowsG.
260     * case III. pl1_rows <  numRowsG.
261     ***********************************************************/
262     if( pl1_rows == numRowsG ){
263 	pl1_case = EQUAL_CASE ;
264     } else if( pl1_rows > numRowsG ){
265 	pl1_case = LESS_ROWS_CASE ;
266 	M( WARNMSG, "read_feed_data",
267 	"The number of rows have decreased since the last run.\n" ) ;
268     } else if( pl1_rows < numRowsG ){
269 	pl1_case = MORE_ROWS_CASE ;
270 	M( WARNMSG, "read_feed_data",
271 	"The number of rows have increased since the last run.\n" ) ;
272 	/* here we need also to make a smoothing array */
273 	smooth = (DOUBLE *)
274 	    Ysafe_malloc( (numRowsG+1) * sizeof(DOUBLE) ) ;
275 	for( row = 1; row <= numRowsG; row++ ){
276 	    smooth[row] = 0.0 ;
277 	}
278     }
279     if( pl1_case == LESS_ROWS_CASE || pl1_case == MORE_ROWS_CASE ){
280 	M( WARNMSG, NULL,
281 	"This may affect feed estimation.  To insure the best results,\n" ) ;
282 	M( WARNMSG, NULL, "\trun TimberWolf at least one more time.\n\n" ) ;
283     }
284 
285 
286     /***********************************************************
287     * Now read from circuitName.pl1 file to get explicit feeds.
288     ***********************************************************/
289     /* Now try to open .pl1 file */
290     sprintf( filename, "%s.pl1", cktNameG ) ;
291     fp = TWOPEN( filename, "r", NOABORT ) ;
292     if(!(fp)){
293 	/* no feed data present return false */
294 	return( FALSE ) ;
295     }
296 
297     /* now allocate space for feeds in row */
298     feed_lengthS = 0 ;
299     while( bufferptr = fgets( buffer, LRECL, fp ) ){
300 	tokens = Ystrparser( bufferptr, " \t\n", &numtokens ) ;
301 	if( numtokens != 7 ){
302 	    continue ;
303 	}
304 	if( strncmp( tokens[0], "twfeed", 6 ) == STRINGEQ ){
305 	    feed_lengthS += fdWidthG ;
306 	    row_in_pl1 = atoi( tokens[6] ) ;
307 	    switch( pl1_case ){
308 	    case EQUAL_CASE :
309 		feeds_in_rowG[row_in_pl1]++ ;
310 		break ;
311 	    case LESS_ROWS_CASE :
312 		row = ROUND( (DOUBLE) row_in_pl1 /
313 			(DOUBLE) pl1_rows * (DOUBLE) numRowsG ) ;
314 		feeds_in_rowG[row]++ ;
315 		break ;
316 	    case MORE_ROWS_CASE :
317 		value = (DOUBLE) row_in_pl1 /
318 			(DOUBLE) pl1_rows * (DOUBLE) numRowsG ;
319 		start_row = (INT) floor( value ) ;
320 		if( start_row <= 0 ){
321 		    start_row = 1 ;
322 		}
323 		end_row = (INT) ceil( value ) ;
324 		value = 1.0 / (end_row - start_row + 1) ;
325 		for( row = start_row; row <= end_row; row++ ){
326 		    smooth[row] += value ;
327 		}
328 		break ;
329 	    } /* end switch( pl1_case... */
330 	}
331     } /* end while( bufferptr... */
332 
333     TWCLOSE( fp ) ;
334 
335     if( pl1_case == MORE_ROWS_CASE ){
336 	/* perform the rounding after all feeds have been accounted*/
337 	for( row = 1; row <= numRowsG; row++ ){
338 	    feeds_in_rowG[row] = ROUND( smooth[row] ) ;
339 	}
340 	Ysafe_free( smooth ) ;
341     }
342     feed_statusL = TRUE ; /* feed data is valid at this point */
343 
344     M( MSG, NULL, "\nFeed Taper:\n" ) ;
345     for( row = 1; row <= numRowsG; row++ ){
346 	sprintf( YmsgG, "\trow:%4d num explicit feeds:%d\n",
347 	    row, feeds_in_rowG[row] ) ;
348 	M( MSG, NULL, YmsgG ) ;
349     }
350     M( MSG, NULL, "\n\n" ) ;
351 
352     /* now update the configuration */
353     configuref() ;
354     funccostG = findcostf() ;
355 
356     return( feed_statusL ) ;
357 
358 } /* end read_feed_data */
359