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