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: paths.c
42 DESCRIPTION:output length of paths
43 CONTENTS: print_paths.
44 INT calc_incr_time( cell )
45 INT cell ;
46 update_time( cell )
47 INT cell ;
48 INT calc_incr_time2( cella, cellb )
49 INT cella, cellb ;
50 update_time2( cella, cellb )
51 INT cella, cellb ;
52 init_path_set()
53 add2path_set( path )
54 INT path ;
55 PSETPTR enum_path_set()
56 clear_path_set()
57 init_net_set()
58 add2net_set( net )
59 INT net ;
60 BOOL member_net_set( net )
61 clear_net_set()
62 INT dcalc_full_penalty()
63 INT dcalc_path_len(path_num)
64 INT path_num ;
65 DATE: Oct 22, 1988
66 REVISIONS: Dec 3, 1988 - completed timing driven code.
67 Jan 29, 1989 - added \n's for pretty output.
68 Mar 11, 1989 - added statistics to print_paths.
69 - added wirelength to print_paths.
70 Mar 13, 1989 - now output penalty in print_paths.
71 Fri Jan 18 18:32:01 PST 1991 - updated output format.
72 Sun Jan 20 21:34:36 PST 1991 - ported to AIX.
73 ----------------------------------------------------------------- */
74
75 #include <custom.h>
76 #include <yalecad/debug.h>
77 #include <yalecad/file.h>
78 #include <yalecad/stat.h>
79
80 /* Forward declarations */
81
82 INT dcalc_min_path_len();
83 INT dcalc_max_path_len();
84 void add2path_set( INT path );
85 void clear_path_set();
86
print_paths()87 void print_paths( )
88 {
89
90 char filename[LRECL] ;
91 PATHPTR pptr, get_path_list() ;
92 GLISTPTR net ;
93 NETBOXPTR nptr ;
94 PINBOXPTR netptr ;
95 FILE *fp ;
96 DOUBLE mean ;
97 DOUBLE paths ;
98 BOOL pad ;
99 INT *stat ;
100 INT num_paths ;
101 INT length ;
102 INT pathLength ;
103 INT loLength ;
104 INT hiLength ;
105 INT i = 0 ;
106 INT xspan ;
107 INT yspan ;
108 INT in = 0 ;
109 INT above = 0 ;
110 INT below = 0 ;
111 INT penalty = 0 ;
112 INT way_above = 0 ;
113 INT way_below = 0 ;
114 INT really_above = 0 ;
115 INT really_below = 0 ;
116 INT really_way_above = 0 ;
117 INT really_way_below = 0 ;
118
119 /* get total number of paths in timing analysis */
120 num_paths = get_total_paths() ;
121 /* allocate the an array for calculating statistics */
122 if( num_paths ){
123 stat = (INT *) Ysafe_malloc( num_paths * sizeof(INT) ) ;
124 }
125 sprintf(filename, "%s.mpth" , cktNameG ) ;
126 fp = TWOPEN( filename , "w", ABORT ) ;
127 /* first the lengths of the nets */
128 fprintf( fp, "The paths:\n" ) ;
129 fprintf( fp, "##############################################\n" ) ;
130 for( pptr=get_path_list() ;pptr;pptr=pptr->next ){
131 pathLength = 0 ;
132 loLength = 0 ;
133 hiLength = 0 ;
134 xspan = 0 ;
135 yspan = 0 ;
136
137 /* get pathLength for path */
138 fprintf( fp, "path %3d:\n",++i ) ;
139 for( net = pptr->nets ; net ; net = net->next ){
140 nptr = netarrayG[net->p.net] ;
141 fprintf( fp, "\t\t%s\n", nptr->nname ) ;
142 length = nptr->halfPx +
143 (INT)(vertical_path_weightG * (DOUBLE) nptr->halfPy) ;
144 xspan += nptr->halfPx ;
145 yspan += nptr->halfPy ;
146 pathLength += length ;
147 loLength = loLength + (INT)
148 (nptr->max_driver * (FLOAT)length + nptr->driveFactor);
149 hiLength = hiLength + (INT)
150 (nptr->min_driver * (FLOAT)length + nptr->driveFactor);
151 }
152 fprintf( fp, "\tpriority:%d lower bound:%d upper bound:%d\n",
153 pptr->priority, pptr->lower_bound, pptr->upper_bound ) ;
154 fprintf( fp,"\tweighted length:%d fast driver len:%d slow driver len:%d\n",
155 pathLength, loLength, hiLength ) ;
156 fprintf( fp, "\txspan:%d yspan:%d length:%d\n", xspan, yspan,
157 xspan+yspan ) ;
158 if( pptr->priority ){
159 ASSERT( loLength == pptr->lo_path_len,"print_paths",
160 "lo_pathLength does not equal incremental value " ) ;
161 ASSERT( hiLength == pptr->hi_path_len,"print_paths",
162 "hi_pathLength does not equal incremental value " ) ;
163 }
164 if( loLength < pptr->lower_bound ){
165 penalty += pptr->lower_bound - loLength ;
166 /* look for paths with some slack on bound */
167 if( loLength < (INT)( 0.90 * (DOUBLE) pptr->lower_bound) ){
168 below++ ;
169
170 /* check if this path has a net with a pad in it */
171 pad = FALSE ;
172 for( net = pptr->nets ; net ; net = net->next ){
173 netptr = netarrayG[net->p.net]->pins ;
174 for( ; netptr ; netptr = netptr->next ) {
175 if( netptr->cell > numcellsG ) {
176 pad = TRUE ;
177 break ;
178 }
179 }
180 }
181 if( !pad ) {
182 really_below++ ;
183 }
184 }
185 if( loLength < (INT)( 0.80 * (DOUBLE) pptr->lower_bound) ){
186 way_below++ ;
187 if( !pad ) {
188 really_way_below++ ;
189 }
190 }
191 } else if( hiLength > pptr->upper_bound ){
192 penalty += hiLength - pptr->upper_bound ;
193 if( hiLength > (INT)( 1.10 * (DOUBLE) pptr->upper_bound) ){
194 above++ ;
195
196 pad = FALSE ;
197 for( net = pptr->nets ; net ; net = net->next ){
198 netptr = netarrayG[net->p.net]->pins ;
199 for( ; netptr ; netptr = netptr->next ) {
200 if( netptr->cell > numcellsG ) {
201 pad = TRUE ;
202 break ;
203 }
204 }
205 }
206 if( !pad ) {
207 really_above++ ;
208 }
209 }
210 if( hiLength > (INT)( 1.20 * (DOUBLE) pptr->upper_bound) ){
211 way_above++ ;
212 if( !pad ) {
213 really_way_above++ ;
214 }
215 }
216 } else {
217 in++ ;
218 }
219 /* add pathlength to stat array */
220 stat[i-1] = pathLength ;
221
222 }
223 /* first the lengths of the nets */
224 fprintf( fp, "\nThe nets:\n" ) ;
225 fprintf( fp, "##############################################\n" ) ;
226 for( i=1;i<=numnetsG;i++ ){
227 nptr = netarrayG[i] ;
228 fprintf( fp, "net %3d:%s xspan:%d yspan:%d length:%d numpins:%d\n",
229 i, nptr->nname, nptr->halfPx, nptr->halfPy,
230 nptr->halfPx + nptr->halfPy, nptr->numpins ) ;
231 }
232 /* avoid a divide by zero */
233 if( num_paths ){
234 paths = (DOUBLE) num_paths ;
235 fprintf( fp, "\nSummary:\n" ) ;
236 fprintf( fp, "Total wirelength :%5d\n", funccostG ) ;
237 fprintf( fp, "Total time penalty :%5d\n", penalty ) ;
238 fprintf( fp, "Number of paths :%5d\n", num_paths ) ;
239 fprintf( fp, "Number of active paths :%5d\n", numpathsG ) ;
240 fprintf( fp, "Number of paths 10%% below spec :%5d - %4.2f%%\n",
241 below, 100.0 * (DOUBLE) below / paths ) ;
242 fprintf( fp, "Number of paths 10%% above spec :%5d - %4.2f%%\n",
243 above, 100.0 * (DOUBLE) above / paths ) ;
244 fprintf( fp, "Number of paths within spec :%5d - %4.2f%%\n",
245 in, 100.0 * (DOUBLE) in / paths ) ;
246 fprintf( fp, "# of non-pad paths out of spec :%5d\n", really_above +
247 really_below ) ;
248 fprintf( fp, "Number of paths 20%% below spec :%5d - %4.2f%%\n",
249 way_below, 100.0 * (DOUBLE) way_below / paths ) ;
250 fprintf( fp, "Number of paths 20%% above spec :%5d - %4.2f%%\n",
251 way_above, 100.0 * (DOUBLE) way_above / paths ) ;
252 fprintf( fp, "# of non-pad paths out of spec :%5d\n",
253 really_way_above + really_way_below ) ;
254 fprintf( fp, "Min length :%4.2le\n",
255 Ystat_min( stat, num_paths, sizeof(INT) ) ) ;
256 fprintf( fp, "Max length :%4.2le\n",
257 Ystat_max( stat, num_paths, sizeof(INT) ) ) ;
258 mean = Ystat_mean( stat, num_paths, sizeof(INT) ) ;
259 fprintf( fp, "Mean length :%4.2le\n", mean ) ;
260 fprintf( fp, "Standard Dev. length :%4.2le\n",
261 sqrt( Ystat_var( stat, num_paths, sizeof(INT),mean) ) ) ;
262 Ysafe_free( stat ) ;
263 }
264 TWCLOSE( fp ) ;
265
266 } /* end print_paths */
267
268 /* -----------------------------------------------------------------
269 The update path routines
270 The incremental routines speed execution by looking at only those
271 paths connected to the cells that are to be moved. In addition,
272 only those nets which are modified by the move are updated. This
273 gives us an incremental length which we add to old half perimeter
274 to give us total lenght of this net. The penalty is based on this
275 length. We calculate an incremental penalty based on the change
276 in the penalty.
277 ----------------------------------------------------------------- */
278 /* calculate the timing cost incrementally */
calc_incr_time(cell)279 INT calc_incr_time( cell )
280 INT cell ;
281 {
282 INT newpenal ; /* proposed move's timing penalty delta */
283 INT oldpenal ; /* the old penalty of the nets that move */
284 INT length ; /* path length incremental */
285 INT loLength ; /* lo path length incremental */
286 INT hiLength ; /* hi path length incremental */
287 INT path_num ; /* name of path */
288 INT net ; /* net of path */
289 GLISTPTR pptr ; /* pointer to paths of a cell */
290 GLISTPTR net_of_path ;
291 PATHPTR path ;
292 NETBOXPTR dimptr ;
293
294 newpenal = 0 ;
295 oldpenal = 0 ;
296 /* for all paths of the cell that has moved */
297 for( pptr = cellarrayG[cell]->paths; pptr ; pptr = pptr->next ) {
298
299 path_num = pptr->p.path ;
300 ASSERTNCONT( path_num > 0 && path_num <= numpathsG,
301 "calc_incr_time", "path is out of bounds" ) ;
302 path = patharrayG[path_num] ;
303 /* for all nets k of a path i */
304 loLength = 0 ;
305 hiLength = 0 ;
306 for( net_of_path=path->nets;net_of_path;
307 net_of_path=net_of_path->next ){
308 net = net_of_path->p.net ;
309
310 dimptr = netarrayG[net] ;
311
312 /* accumulate length of path */
313 if( member_net_set( net ) ){
314 /* this half - perimeter has changed use update */
315 /* calculate total change on path */
316 length = ( dimptr->newhalfPx - dimptr->halfPx +
317 (INT)(vertical_path_weightG * (DOUBLE)dimptr->newhalfPy) -
318 (INT)(vertical_path_weightG * (DOUBLE)dimptr->halfPy) );
319 loLength = loLength + (INT) (dimptr->max_driver * (FLOAT) length +
320 dimptr->driveFactor ) ;
321 hiLength = hiLength + (INT) (dimptr->min_driver * (FLOAT) length +
322 dimptr->driveFactor ) ;
323 } /* else this half - perimeter has not changed use old */
324 }
325 /* save total result - change to total length */
326 path->new_lo_path_len = loLength += path->lo_path_len ;
327 path->new_hi_path_len = hiLength += path->hi_path_len ;
328
329 ASSERT( loLength == dcalc_min_path_len(path_num), NULL, NULL ) ;
330 ASSERT( hiLength == dcalc_max_path_len(path_num), NULL, NULL ) ;
331
332 /* calculate change in timing penalty */
333 /* no penalty if within target window */
334 /* lowerbound <= length <= upperbound */
335 if( hiLength > path->upper_bound ){
336 newpenal += hiLength - path->upper_bound ;
337 } else if( loLength < path->lower_bound ){
338 newpenal += path->lower_bound - loLength ;
339 }
340 /* now the old penalty */
341 if( path->hi_path_len > path->upper_bound ){
342 oldpenal += path->hi_path_len - path->upper_bound ;
343 } else if( path->lo_path_len < path->lower_bound ){
344 oldpenal += path->lower_bound - path->lo_path_len ;
345 }
346 }
347 /* return the change in penalty */
348 return( newpenal - oldpenal ) ;
349
350 } /* end function calc_incr_time */
351
352
update_time(cell)353 void update_time( cell )
354 INT cell ;
355 {
356
357 INT path_num ; /* name of path */
358 GLISTPTR pptr ; /* pointer to paths of a cell */
359 PATHPTR path ;
360
361 /* for all paths of the cell that has moved */
362 for( pptr = cellarrayG[cell]->paths; pptr ; pptr = pptr->next ) {
363
364 path_num = pptr->p.path ;
365 ASSERTNCONT( path_num > 0 && path_num <= numpathsG,
366 "update_time", "path is out of bounds" ) ;
367 path = patharrayG[path_num] ;
368 /* keep result */
369 path->lo_path_len = path->new_lo_path_len ;
370 path->hi_path_len = path->new_hi_path_len ;
371 }
372
373 } /* end function update_time */
374
375 /* calculate the timing cost incrementally for two cells */
calc_incr_time2(cella,cellb)376 INT calc_incr_time2( cella, cellb )
377 INT cella ;
378 INT cellb ;
379 {
380 INT newpenal ; /* proposed move's timing penalty delta */
381 INT oldpenal ; /* the old penalty of the nets that move */
382 INT length ; /* incremental path length */
383 INT loLength ; /* lo path length incremental */
384 INT hiLength ; /* hi path length incremental */
385 INT path_num ; /* name of path */
386 INT net ; /* net of path */
387 GLISTPTR pptr ; /* pointer to paths of a cell */
388 GLISTPTR net_of_path ;
389 PATHPTR path ;
390 PSETPTR pathlist, enum_path_set() ;
391 NETBOXPTR dimptr ;
392
393 newpenal = 0 ;
394 oldpenal = 0 ;
395 clear_path_set() ;
396
397 /* use add2path_set to get union of paths from cella and cellb */
398 for( pptr = cellarrayG[cella]->paths; pptr ; pptr = pptr->next ) {
399 add2path_set( pptr->p.path ) ;
400 }
401 for( pptr = cellarrayG[cellb]->paths; pptr ; pptr = pptr->next ) {
402 add2path_set( pptr->p.path ) ;
403 }
404
405
406 /* now use UNIQUE list of the union of the two cell's paths */
407 for( pathlist=enum_path_set(); pathlist; pathlist=pathlist->next){
408
409 path_num = pathlist->path ;
410 ASSERTNCONT( path_num > 0 && path_num <= numpathsG,
411 "calc_incr_time2", "path is out of bounds" ) ;
412 path = patharrayG[path_num] ;
413
414 /* for all nets k of a path i */
415 loLength = 0 ;
416 hiLength = 0 ;
417 for( net_of_path=path->nets;net_of_path;
418 net_of_path=net_of_path->next ){
419 net = net_of_path->p.net ;
420
421 dimptr = netarrayG[net] ;
422
423 /* accumulate length of path */
424 if( member_net_set( net ) ){
425 /* this half - perimeter has changed use update */
426 /* calculate total change on path */
427 length = ( dimptr->newhalfPx - dimptr->halfPx +
428 (INT)(vertical_path_weightG * (DOUBLE)dimptr->newhalfPy) -
429 (INT)(vertical_path_weightG * (DOUBLE)dimptr->halfPy) );
430 loLength = loLength + (INT) (dimptr->max_driver * (FLOAT) length +
431 dimptr->driveFactor ) ;
432 hiLength = hiLength + (INT) (dimptr->min_driver * (FLOAT) length +
433 dimptr->driveFactor ) ;
434 } /* else this half - perimeter has not changed use old */
435 }
436 /* save total result - change to total length */
437 path->new_lo_path_len = loLength += path->lo_path_len ;
438 path->new_hi_path_len = hiLength += path->hi_path_len ;
439
440 ASSERT( loLength == dcalc_min_path_len(path_num), NULL, NULL ) ;
441 ASSERT( hiLength == dcalc_max_path_len(path_num), NULL, NULL ) ;
442
443 /* calculate change in timing penalty */
444 /* no penalty if within target window */
445 /* lowerbound <= length <= upperbound */
446 if( hiLength > path->upper_bound ){
447 newpenal += hiLength - path->upper_bound ;
448 } else if( loLength < path->lower_bound ){
449 newpenal += path->lower_bound - loLength ;
450 }
451 /* now the old penalty */
452 if( path->hi_path_len > path->upper_bound ){
453 oldpenal += path->hi_path_len - path->upper_bound ;
454 } else if( path->lo_path_len < path->lower_bound ){
455 oldpenal += path->lower_bound - path->lo_path_len ;
456 }
457 }
458 /* return the change in penalty */
459 return( newpenal - oldpenal ) ;
460
461 } /* end function calc_incr_time2 */
462
update_time2(cella,cellb)463 void update_time2( cella, cellb )
464 INT cella, cellb ;
465 {
466 INT path_num ; /* name of path */
467 PATHPTR path ;
468 PSETPTR pathlist, enum_path_set() ;
469
470 /* now use UNIQUE list of the union of the two cell's paths */
471 for( pathlist=enum_path_set(); pathlist; pathlist=pathlist->next){
472
473 DS( path_num = pathlist->path ; ) ;
474 ASSERTNCONT( path_num > 0 && path_num <= numpathsG,
475 "update_time2", "path is out of bounds" ) ;
476 path = patharrayG[pathlist->path] ;
477 /* keep result */
478 path->lo_path_len = path->new_lo_path_len ;
479 path->hi_path_len = path->new_hi_path_len ;
480 }
481
482 } /* end function update_time */
483 /* -----------------------------------------------------------------
484 The set required in the update path routines needs the following
485 operations done efficiently :
486 membership - O(1)
487 add to set if unique - O(1)
488 clear set - O(1)
489 set enumeration - O( paths in set )
490 Below is a space hungry O( numpaths ) but time efficient implementation
491 We combine two data structures to accomplish this goal. We use array
492 for testing membership and uniqueness but use list for enumeration.
493 By incrementing count we can reinitialize easily.
494 Note: PSETBOX, PSETPTR definitions are in custom.h
495 ----------------------------------------------------------------- */
496 static PSETPTR path_set_listS ; /* list is beginning of set as a list */
497 static PSETPTR *path_set_arrayS ; /* set is an array of path set boxes */
498 static INT path_set_countS ; /* current set count */
499
500 /* initialize set */
init_path_set()501 void init_path_set()
502 {
503 INT i ;
504
505 path_set_arrayS=(PSETPTR *)Ysafe_malloc((numpathsG+1)*sizeof(PSETPTR));
506 for( i=0;i<=numpathsG;i++ ){
507 path_set_arrayS[i] = (PSETPTR) Ysafe_calloc( 1, sizeof(PSETBOX) ) ;
508 }
509 path_set_countS = 1 ;
510 path_set_listS = NULL ;
511 } /* end initset */
512
513 /* add a path to the set if not already in set */
add2path_set(INT path)514 void add2path_set( INT path )
515 {
516 PSETPTR temp, cpath ;
517
518 if( path >= 1 || path <= numpathsG ){
519 cpath = path_set_arrayS[path] ;
520 /* something is a member in set is counts match */
521 if( cpath->member != path_set_countS ){
522 /* new path to be added */
523 /* connect to the single linked list */
524 if( temp = path_set_listS ){
525 /* hook to old list */
526 path_set_listS = cpath ;
527 cpath->next = temp ;
528 } else {
529 path_set_listS = cpath ;
530 /* terminate new list */
531 cpath->next = NULL ;
532 }
533 cpath->path = path ; /* store data */
534 cpath->member = path_set_countS ; /* store membership */
535 }
536
537 } else {
538 M( ERRMSG, "ADD2SET","value of path is out of bounds of set\n" ) ;
539 }
540 } /* end add2path_set */
541
enum_path_set()542 PSETPTR enum_path_set()
543 {
544 return( path_set_listS ) ;
545 }
546
clear_path_set()547 void clear_path_set()
548 {
549 path_set_countS ++ ;
550 path_set_listS = NULL ;
551 } /* end clear_path_set */
552
553 /* -----------------------------------------------------------------
554 Below is a second set of set routines required in the update path
555 routines which operate on nets instead of paths. The following
556 operations need to be done efficiently :
557 membership - O(1)
558 add to set if unique - O(1)
559 clear set - O(1)
560 Since we don't need to enumerate set we only need array to implement
561 this set.
562 ----------------------------------------------------------------- */
563 static INT *net_set_array ; /* set is an array of net set boxes */
564 static INT net_set_count ; /* current set count */
565
566 /* initialize set */
init_net_set()567 void init_net_set()
568 {
569 net_set_array = (INT *) Ysafe_calloc((numnetsG+1), sizeof(INT) );
570 net_set_count = 1 ;
571 } /* end initset */
572
573 /* add a net to the set if not already in set */
add2net_set(net)574 void add2net_set( net )
575 INT net ;
576 {
577 if( net >= 1 || net <= numnetsG ){
578 /* current count make array member a valid member of set */
579 net_set_array[net] = net_set_count ;
580
581 } else {
582 M( ERRMSG, "ADD2SET", "value of path is out of bounds of set" ) ;
583 }
584 } /* end add2net_set */
585
member_net_set(int net)586 BOOL member_net_set( int net )
587 /* test for membership */
588 {
589 if( net_set_array[net] == net_set_count ){
590 return( TRUE ) ;
591 } else {
592 return( FALSE ) ;
593 }
594 } /* end member_net_set */
595
clear_net_set()596 void clear_net_set()
597 {
598 /* to clear set we only need to increment net_set_count */
599 /* we can use this set up to 2 Gig times without any problem */
600 net_set_count ++ ;
601 } /* end clear_path_set */
602
603 /* debug function to make sure calculation is correct */
dcalc_full_penalty()604 INT dcalc_full_penalty()
605 {
606 INT timingpenal ;
607 INT length ; /* path length incremental */
608 INT low_length ; /* lo path length */
609 INT high_length ; /* hi path length */
610 INT pathcount ;
611 INT net ; /* net of path */
612 GLISTPTR net_of_path ;
613 PATHPTR path ;
614 NETBOXPTR dimptr ;
615
616 /* now calculate the penalties */
617 /* first the timing penalty */
618 timingpenal = 0 ;
619 for( pathcount = 1 ; pathcount <= numpathsG ; pathcount++ ) {
620
621 path = patharrayG[pathcount] ;
622 ASSERTNCONT( path, "findcost", "pointer to path is NULL" ) ;
623 /* for all nets k of a path i */
624 low_length = 0 ;
625 high_length = 0 ;
626 for( net_of_path=path->nets;net_of_path;
627 net_of_path=net_of_path->next ){
628 net = net_of_path->p.net ;
629 dimptr = netarrayG[net] ;
630
631
632 /* accumulate length of path */
633 if( member_net_set( net ) ){
634 /* this half - perimeter has changed use update */
635 /* calculate total change on path */
636 length = dimptr->newhalfPx + (INT)(vertical_path_weightG *
637 (DOUBLE) dimptr->newhalfPy) ;
638 } else {
639 /* old length */
640 length = dimptr->halfPx + (INT)(vertical_path_weightG *
641 (DOUBLE) dimptr->halfPy) ;
642 }
643 low_length = low_length + (INT)
644 (dimptr->max_driver * (FLOAT) length +
645 dimptr->driveFactor ) ;
646 high_length = high_length + (INT)
647 (dimptr->min_driver * (FLOAT) length +
648 dimptr->driveFactor ) ;
649 }
650 /* calculate penalty */
651 /* no penalty if within target window */
652 /* lowerbound <= length <= upperbound */
653 if( high_length > path->upper_bound ){
654 timingpenal += high_length - path->upper_bound ;
655 } else if( low_length < path->lower_bound ){
656 timingpenal += path->lower_bound - low_length ;
657 }
658 }
659 return( timingpenal ) ;
660 }
661
dcalc_min_path_len(path_num)662 INT dcalc_min_path_len(path_num)
663 INT path_num ;
664 {
665
666 INT length ; /* path length incremental */
667 INT net ; /* net of path */
668 INT halfP ; /* the modified half perimeter */
669 GLISTPTR net_of_path ;
670 PATHPTR path ;
671 NETBOXPTR dimptr ;
672
673 path = patharrayG[path_num] ;
674 /* for all nets k of a path i */
675 length = 0 ;
676 for( net_of_path=path->nets;net_of_path;
677 net_of_path=net_of_path->next ){
678 net = net_of_path->p.net ;
679 dimptr = netarrayG[net] ;
680
681 /* accumulate length of path */
682 if( member_net_set( net ) ){
683 /* this half - perimeter has changed use update */
684 /* calculate total change on path */
685 halfP = dimptr->newhalfPx + (INT)(vertical_path_weightG *
686 (DOUBLE) dimptr->newhalfPy) ;
687 length = length + (INT) (dimptr->max_driver * halfP +
688 dimptr->driveFactor ) ;
689 } else {
690 /* old length */
691 halfP = dimptr->halfPx + (INT)(vertical_path_weightG *
692 (DOUBLE) dimptr->halfPy) ;
693 length = length + (INT) (dimptr->max_driver * halfP +
694 dimptr->driveFactor ) ;
695 }
696 }
697 return( length ) ;
698 } /* end dcald_min_path_len */
699
dcalc_max_path_len(path_num)700 INT dcalc_max_path_len(path_num)
701 INT path_num ;
702 {
703
704 INT length ; /* path length incremental */
705 INT net ; /* net of path */
706 INT halfP ; /* the modified half perimeter */
707 GLISTPTR net_of_path ;
708 PATHPTR path ;
709 NETBOXPTR dimptr ;
710
711 path = patharrayG[path_num] ;
712 /* for all nets k of a path i */
713 length = 0 ;
714 for( net_of_path=path->nets;net_of_path;
715 net_of_path=net_of_path->next ){
716 net = net_of_path->p.net ;
717 dimptr = netarrayG[net] ;
718
719 /* accumulate length of path */
720 if( member_net_set( net ) ){
721 /* this half - perimeter has changed use update */
722 /* calculate total change on path */
723 halfP = dimptr->newhalfPx + (INT)(vertical_path_weightG *
724 (DOUBLE) dimptr->newhalfPy) ;
725 length = length + (INT) (dimptr->min_driver * halfP +
726 dimptr->driveFactor ) ;
727 } else {
728 /* old length */
729 halfP = dimptr->halfPx + (INT)(vertical_path_weightG *
730 (DOUBLE) dimptr->halfPy) ;
731 length = length + (INT) (dimptr->min_driver * halfP +
732 dimptr->driveFactor ) ;
733 }
734 }
735 return( length ) ;
736 } /* end dcalc_max_path_len */
737