1 /*
2  *   Copyright (C) 1989-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:	    output.c
42 DESCRIPTION:output the placement information.
43 CONTENTS:   output()
44 	    final_free_up()
45 	    create_cel_file()
46 DATE:	    Mar 27, 1989
47 REVISIONS:  July 15, 1989
48 	    Oct   2, 1990 - removed elim_unused feeds and
49 		added check for clength == 0.
50 	    Wed Jan 16 14:25:22 PST 1991 - commented out free
51 		of pairArrayG.
52 	    Wed Jan 23 02:43:33 PST 1991 - output at density.
53 	    Sat May  4 13:47:58 EDT 1991 - now output row field
54 		similar to global routing definition.
55 	    Tue Aug 13 12:47:54 CDT 1991 - fixed create new
56 		cell file.
57 ----------------------------------------------------------------- */
58 
59 /* #define DEC  */
60 /* added on 06/01/90 Sury */
61 /* #define NSC */
62 
63 #include "standard.h"
64 #include "groute.h"
65 #include "main.h"
66 #include "readpar.h"
67 #include "config.h"
68 #include "pads.h"
69 #include <string.h>
70 #include <yalecad/debug.h>
71 #include <yalecad/message.h>
72 
73 /* external functions */
74 char *strtok(); /* added 06/01/90 sury */
75 INT comparex() ;
76 
77 /* global variables */
78 extern INT spacer_widthG ;
79 extern INT actual_feed_thru_cells_addedG ;
80 extern BOOL output_at_densityG ;
81 extern BOOL create_new_cel_fileG ;
82 extern BOOL unused_feed_name_twspacerG ;
83 extern BOOL stand_cell_as_gate_arrayG ;
84 
85 /* static definitions */
86 static char a_lineS[LRECL] ;
87 
88 INT load_a_lineS(FILE *fp);
89 void create_cel_file();
90 void add_new_line( INT x_rel , INT block , char *fixed_ptr , FILE *fp );
91 
output()92 void output()
93 {
94 
95 FILE *fpp1 , *fpp2 ;
96 INT locx , locy , height , width ;
97 INT xloc , i , cell , block , orient ;
98 INT num ;
99 INT xloc2 , yloc2 , yloc ;
100 INT *array , desire , k , limit ;
101 INT left , right , bottom , top , end ;
102 INT *deleted_feeds ;
103 INT eliminated_feeds ;
104 char filename[LRECL] , ctmp[32] ;
105 CBOXPTR cellptr ;
106 TIBOXPTR tptr ;
107 PADBOXPTR pptr ;
108 /* added on 06/01/90 Sury */
109 INT length;
110 INT row ;
111 char instance_name[LRECL], tmp_name[LRECL], *tmp_string;
112 
113 
114 deleted_feeds = (INT *) Ysafe_malloc( numcellsG * sizeof(INT) ) ;
115 eliminated_feeds = 0 ;
116 
117 sprintf( filename , "%s.pl1" , cktNameG ) ;
118 fpp1 = TWOPEN( filename , "w", ABORT ) ;
119 
120 sprintf( filename , "%s.pl2" , cktNameG ) ;
121 fpp2 = TWOPEN( filename , "w", ABORT ) ;
122 
123 for( block = 1 ; block <= numRowsG ; block++ ) {
124 
125     left   = barrayG[block]->bxcenter + barrayG[block]->bleft   ;
126     right  = barrayG[block]->bxcenter + barrayG[block]->bright  ;
127     bottom = barrayG[block]->bycenter + barrayG[block]->bbottom ;
128     top    = barrayG[block]->bycenter + barrayG[block]->btop    ;
129 
130     if( restartG == 0 && costonlyG == 1 ) {
131 	desire = barrayG[block]->desire ;
132     } else {
133 	if( pairArrayG[block][0] > 0 ) {
134 	    cell = pairArrayG[block][ pairArrayG[block][0] ] ;
135 	    end  = carrayG[cell]->cxcenter + carrayG[cell]->tileptr
136 			    ->right ;
137 	    desire = end - left ;
138 	} else {
139 	    desire = 0 ;
140 	}
141     }
142 
143     if( barrayG[block]->borient > 0 ) {
144 	fprintf(fpp2,"%d %d %d  %d %d  0 0\n", block ,
145 			    left, bottom, left + desire, top ) ;
146     } else {
147 	fprintf(fpp2,"%d %d %d  %d %d  0 0\n", block ,
148 			    left, bottom, right, bottom + desire ) ;
149     }
150 
151     num = pairArrayG[block][0] ;
152     if( num == 0 ) {
153 	continue ;
154     }
155     array = pairArrayG[block] + 1 ;
156 
157     for( i = 0 ; i < num ; i++ ) {
158 	cell = array[ i ] ;
159 	cellptr = carrayG[ cell ] ;
160 	if( cellptr->clength == 0 ){
161 	    continue ;
162 	}
163 	if( strcmp( cellptr->cname , "TW_EXCEPT" ) == 0 ) {
164 	    continue ;
165 	}
166 	if( stand_cell_as_gate_arrayG ) {
167 	    if( strcmp( cellptr->cname , "GATE_ARRAY_SPACER" ) == 0 ) {
168 		continue ;
169 	    }
170 	}
171 	if( unused_feed_name_twspacerG ) {
172 	    if( strncmp(cellptr->cname,"twfeed",6) == STRINGEQ ) {
173 		if( tearrayG[cellptr->imptr->terminal] == NULL ) {
174 		    strcpy( ctmp , cellptr->cname ) ;
175 		    cellptr->cname = (char *) Ysafe_realloc(
176 			    cellptr->cname, (strlen(cellptr->cname)+3) *
177 			    sizeof(char) ) ;
178 		    sprintf( cellptr->cname , "%s%s" , "twspacer",
179 				strpbrk(ctmp, "0123456789") ) ;
180 		}
181 	    }
182 	}
183 	orient = cellptr->corient ;
184 
185 	xloc = cellptr->cxcenter + cellptr->tileptr->left ;
186 	yloc = cellptr->cycenter + cellptr->tileptr->bottom ;
187 
188 	xloc2 = cellptr->tileptr->right -
189 		cellptr->tileptr->left ;
190 	yloc2 = cellptr->tileptr->top -
191 		cellptr->tileptr->bottom ;
192 
193 /* The following code was added on 06/01/90 Sury */
194 #ifdef NSC
195 	strcpy( tmp_name , cellptr->cname ) ;
196 	length = strcspn( tmp_name , ":" ) ;
197 	if( length < strlen( tmp_name ) ) {
198 	    tmp_string = strtok( tmp_name , ":" ) ;
199 	    tmp_string = strtok( NULL , ":" ) ;
200 	    sprintf( instance_name, "%s" , tmp_string ) ;
201 	} else {
202 	    sprintf( instance_name , "%s" , tmp_name ) ;
203 	}
204 	fprintf(fpp1,"%s %d %d  %d %d  %d %d\n",
205 			instance_name,
206 			xloc, yloc, xloc + xloc2,
207 			yloc + yloc2, orient, block ) ;
208 #else
209 	fprintf(fpp1,"%s %d %d  %d %d  %d %d\n",
210 			cellptr->cname ,
211 			xloc, yloc, xloc + xloc2,
212 			yloc + yloc2, orient, block ) ;
213 #endif
214     }
215 }
216 
217 if( deleted_feeds[0] > 0 ) {
218     fprintf(fpoG,"Confirming number of eliminated feeds:%d\n",
219 					    eliminated_feeds ) ;
220 }
221 
222 /* now output the pads and macros */
223 for( i = numcellsG + 1 ; i <= lastpadG ; i++ ) {
224     cellptr = carrayG[ i ]  ;
225     orient = cellptr->corient ;
226     tptr = cellptr->tileptr ;
227     left = tptr->left ;
228     right = tptr->right ;
229     bottom = tptr->bottom ;
230     top = tptr->top ;
231     YtranslateT( &left, &bottom, &right, &top, orient ) ;
232     locx = cellptr->cxcenter + left ;
233     locy = cellptr->cycenter + bottom ;
234     height = top - bottom ;
235     width =  right - left ;
236     /* determine row */
237     pptr = cellptr->padptr ;
238     if( pptr->macroNotPad ){
239 	row = 0 ;
240     } else {
241 	switch( pptr->padside ){
242 	    case L:
243 		row = - 1 ;
244 		break ;
245 	    case T:
246 		row = -4 ;
247 		break ;
248 	    case R:
249 		row = - 2 ;
250 		break ;
251 	    case B:
252 		row = - 3 ;
253 		break ;
254 	    default:
255 		M(ERRMSG,"output", "Unknown padside\n" ) ;
256 	}
257     }
258 
259 
260 #ifndef DEC
261 /* The following code was added on 06/01/90 Sury */
262 #ifdef NSC
263 	strcpy( tmp_name , cellptr->cname ) ;
264 	length = strcspn( tmp_name , ":" ) ;
265 	if( length < strlen( tmp_name ) ) {
266 	    tmp_string = strtok( tmp_name , ":" ) ;
267 	    tmp_string = strtok( NULL , ":" ) ;
268 	    sprintf( instance_name, "%s" , tmp_string ) ;
269 	} else {
270 	sprintf( instance_name , "%s" , tmp_name ) ;
271 	}
272     fprintf(fpp1,"%s %d %d  %d %d  %d %d\n", instance_name,
273 				locx, locy, locx + width,
274 				locy + height, orient, row ) ;
275     fprintf(fpp2,"%s %d %d  %d %d  %d %d\n", instance_name,
276 				locx, locy, locx + width,
277 				locy + height, orient, row ) ;
278 #else
279     /* normal case */
280     fprintf(fpp1,"%s %d %d  %d %d  %d %d\n", cellptr->cname ,
281 				locx, locy, locx + width,
282 				locy + height, orient, row ) ;
283     fprintf(fpp2,"%s %d %d  %d %d  %d %d\n", cellptr->cname ,
284 				locx, locy, locx + width,
285 				locy + height, orient, row ) ;
286 #endif
287 #else
288     /* DEC case */
289     fprintf(fpp1,"%s %d %d  %d %d  %d %d\n", cellptr->cname ,
290 		    locx, locy, locx + width,
291 		    locy + height, orient, -cellptr->padside ) ;
292     fprintf(fpp2,"%s %d %d  %d %d  %d %d\n", cellptr->cname ,
293 		    locx, locy, locx + width,
294 		    locy + height, orient, -cellptr->padside ) ;
295 #endif
296 
297 }
298 TWCLOSE( fpp1 ) ;
299 TWCLOSE( fpp2 ) ;
300 
301 if( create_new_cel_fileG ) {
302     create_cel_file() ;
303 }
304 
305 Ysafe_free( deleted_feeds ) ;
306 
307 return ;
308 }
309 
310 
311 
312 
313 
final_free_up()314 void final_free_up()
315 {
316 INT i, j, k, row, pin, net, cell, chan, track ;
317 CBOXPTR cellptr ;
318 DBOXPTR dimptr ;
319 PINBOXPTR ptr, nextptr ;
320 ADJASEGPTR adj, nextadj ;
321 SEGBOXPTR segptr, nextseg ;
322 CHANGRDPTR gdptr, nextgrd ;
323 DENSITYPTR *hdptr ;
324 IPBOXPTR imptr ;
325 FEED_DATA *feedptr ;
326 
327 Ysafe_free( FeedInRowG ) ;
328 for( row = 1 ; row <= numRowsG ; row++ ) {
329     Ysafe_free( impFeedsG[row] ) ;
330 }
331 Ysafe_free( impFeedsG ) ;
332 
333 for( i = 1 ; i <= numRowsG ; i++ ) {
334     feedptr = feedpptrG[i] ;
335     for( j = 1 ; j <= chan_node_noG ; j++ ) {
336 	Ysafe_free( feedptr[j] ) ;
337     }
338     Ysafe_free( feedpptrG[i] ) ;
339 }
340 Ysafe_free( feedpptrG ) ;
341 
342 k = max_tdensityG + 100 ;
343 for( chan = 1 ; chan <= numChansG ; chan++ ) {
344     Ysafe_free( BeginG[chan]->netptr ) ;
345     Ysafe_free( EndG[chan]->netptr ) ;
346     for( gdptr = BeginG[chan] ; gdptr ; gdptr = nextgrd ) {
347 	nextgrd = gdptr->nextgrd ;
348 	Ysafe_free( gdptr->dptr ) ;
349 	Ysafe_free( gdptr ) ;
350     }
351 
352     hdptr = DboxHeadG[chan] ;
353     for( track = 0 ; track <= k ; track++ ) {
354 	Ysafe_free( hdptr[track] ) ;
355     }
356     Ysafe_free( DboxHeadG[chan] ) ;
357 }
358 Ysafe_free( BeginG ) ;
359 Ysafe_free( EndG ) ;
360 Ysafe_free( DboxHeadG ) ;
361 Ysafe_free( maxTrackG ) ;
362 Ysafe_free( nmaxTrackG ) ;
363 
364 k = maxtermG + 2 * numChansG ;
365 for( pin = 1 ; pin <= k ; pin++ ) {
366     Ysafe_free( TgridG[pin] ) ;
367 }
368 Ysafe_free( TgridG ) ;
369 
370 /*
371 Not needed as this is done in findunlap.c
372 for( i = 1 ; i <= numRowsG ; i++ ) {
373     Ysafe_free( pairArrayG[i] ) ;
374 }
375 Ysafe_free( pairArrayG ) ;
376 pairArrayG = NULL ;
377 */
378 
379 for( cell = 1 ; cell <= numcellsG ; cell++ ) {
380     cellptr = carrayG[cell] ;
381     imptr = cellptr->imptr ;
382     if( imptr ) {
383 	for( ; imptr->next; imptr = imptr->next ) {
384 	    if( imptr->next->cell != cell ) break ;
385 	}
386 	imptr->next = NULL ;
387     }
388 }
389 fprintf( fpoG,"Actual # of Feed Cells Added:\t%d\n\n\n",
390     actual_feed_thru_cells_addedG ) ;
391 k = numcellsG + numtermsG + actual_feed_thru_cells_addedG ;
392 for( cell = numcellsG + numtermsG + 1 ; cell <= k ; cell++ ) {
393     cellptr = carrayG[cell] ;
394     cellptr->imptr->next = NULL ;
395     Ysafe_free( cellptr->cname ) ;
396     Ysafe_free( cellptr->tileptr ) ;
397     Ysafe_free( cellptr->imptr->pinname ) ;
398     Ysafe_free( cellptr->imptr->eqpinname ) ;
399     Ysafe_free( cellptr->imptr ) ;
400     Ysafe_free( carrayG[cell] ) ;
401     carrayG[cell] = NULL ;
402 }
403 actual_feed_thru_cells_addedG = 0 ;
404 
405 for( net = 1 ; net <= numnetsG ; net++ ) {
406     for( segptr = netsegHeadG[net] ; segptr ; segptr = nextseg ) {
407 	nextseg = segptr->next ;
408 	Ysafe_free( segptr ) ;
409     }
410     dimptr = netarrayG[net] ;
411     if( !dimptr->pins ) {
412 	continue ;
413     }
414     if( dimptr->pins->terminal > TotRegPinsG ) {
415 	for( ptr = dimptr->pins ; ptr ; ptr = nextptr ) {
416 	    nextptr = ptr->next ;
417 	    for( adj = ptr->adjptr ; adj ; adj = nextadj ) {
418 		nextadj = adj->next ;
419 		Ysafe_free( adj ) ;
420 	    }
421 	    Ysafe_free( ptr->eqptr ) ;
422 	    if( nextptr->terminal <= TotRegPinsG ) break ;
423 	}
424 	dimptr->pins = nextptr ;
425     }
426     for( ptr = dimptr->pins ; ptr ; ptr = ptr->next ) {
427 	for( adj = ptr->adjptr->next ; adj ; adj = nextadj ) {
428 	    nextadj = adj->next ;
429 	    Ysafe_free( adj ) ;
430 	}
431 	ptr->adjptr->next = NULL ;
432     }
433 }
434 Ysafe_free( netsegHeadG ) ;
435 
436 }
437 
438 
439 
440 
create_cel_file()441 void create_cel_file()
442 {
443 
444 
445 FILE *fpoG2 , *fp ;
446 char *token , fixed_string[32] , filename[256] ;
447 char cell_name[32] ;
448 INT ignore_line , block , offset , test , carrayG_index , is_a_cell ;
449 
450 
451 if( rowsG > 0 ) {
452     sprintf( filename , "%s.scel" , cktNameG ) ;
453     fp = TWOPEN( filename, "r" , ABORT ) ;
454 } else {
455     sprintf( filename , "%s.cel" , cktNameG ) ;
456     fp = TWOPEN( filename, "r" , ABORT ) ;
457 }
458 sprintf( filename , "%s.ncel" , cktNameG ) ;
459 fpoG2 = TWOPEN( filename, "w" , ABORT ) ;
460 
461 strcpy( fixed_string , "" ) ;
462 carrayG_index = 0 ;
463 while(  load_a_lineS(fp)  ) {
464     ignore_line = 0 ;
465     if( (token = strtok( a_lineS , " 	" )) != NULL ) {
466 	if( strcmp( token , "cell" ) == 0 ) {
467 	    is_a_cell = 1 ;
468 	    fprintf(fpoG2, "%s ", token ) ;
469 	    token = strtok( NULL , " 	" ) ;
470 	    fprintf(fpoG2, "%s ", token ) ;
471 	    strcpy( cell_name , strtok( NULL , " 	" ) ) ;
472 	    fprintf(fpoG2, "%s ", cell_name ) ;
473 	    do {
474 		test = strcmp( carrayG[ ++carrayG_index ]->cname,
475 					cell_name ) ;
476 	    } while( test != 0 ) ;
477 	 } else if( strcmp( token , "left" ) == 0 ) {
478 	    if( is_a_cell ) {
479 		block  = carrayG[carrayG_index]->cblock ;
480 		offset = carrayG[carrayG_index]->cxcenter +
481 			 carrayG[carrayG_index]->tileptr->left -
482 			(barrayG[block]->bxcenter +
483 			 barrayG[block]->bleft) ;
484 
485 		if( strcmp( fixed_string , "" ) != 0 ) {
486 		    add_new_line( offset , block , fixed_string , fpoG2 ) ;
487 		    strcpy( fixed_string , "" ) ;
488 		} else {
489 		    add_new_line( offset , block , "nonfixed" , fpoG2 ) ;
490 		}
491 	    }
492 	    fprintf(fpoG2, "%s ", token ) ;
493 	    is_a_cell = 0 ;
494 	} else if( strcmp( token , "initially" ) == 0 ) {
495 	    ignore_line = 1 ;
496 	    strcpy( fixed_string , strtok( NULL , " 	" ) ) ;
497 	} else if( strcmp( token , "\n" ) != 0 ) {
498 	    fprintf(fpoG2, "%s ", token ) ;
499 	}
500 	while( (token = strtok( NULL , " 	" )) != NULL ) {
501 	    if( !ignore_line ) {
502 		fprintf(fpoG2, "%s ", token ) ;
503 	    }
504 	}
505     }
506     if( !ignore_line ) {
507 	fprintf(fpoG2, "\n");
508     }
509 }
510 TWCLOSE(fp) ;
511 TWCLOSE(fpoG2) ;
512 }
513 
514 
515 
add_new_line(INT x_rel,INT block,char * fixed_ptr,FILE * fp)516 void add_new_line( INT x_rel , INT block , char *fixed_ptr , FILE *fp )
517 {
518 
519 fprintf(fp, "initially %s %d from left of block %d\n",
520 				fixed_ptr , x_rel , block ) ;
521 return ;
522 }
523 
524 
525 
load_a_lineS(FILE * fp)526 INT load_a_lineS(FILE *fp)
527 {
528 
529 INT i ;
530 char tmp ;
531 
532 if( (int) (tmp = fgetc(fp)) != EOF ) {
533     a_lineS[0] = tmp ;
534     i = 1 ;
535     if( tmp != '\n' ) {
536 	while( (a_lineS[i] = fgetc(fp)) != '\n' ) {
537 	    i++ ;
538 	}
539     }
540     a_lineS[i] = '\0' ;
541     return(1) ;
542 } else {
543     return(0) ;
544 }
545 }
546 
547 /* ******************************************************************** */
density()548 void density()
549 {
550     /* set all the cells at density */
551     INT row ;
552     INT cell ;
553     INT block ;
554     INT rowtop ;
555     INT corient ;
556     INT rowcenter ;
557     CBOXPTR cellptr ;
558     PINBOXPTR pin ;
559 
560     /* first update all the y coordinates of rows */
561     if (maxTrackG){   /* only perform if global routing is performed */
562 	for( row = 1 ; row <= numRowsG ; row++ ) {
563 	    if( row == 1 ){
564 		rowcenter = barrayG[1]->bheight / 2 +
565 			maxTrackG[1]*track_pitchG + route2actG ;
566 	    } else {
567 		rowcenter = rowtop + barrayG[row]->bheight / 2 +
568 		    maxTrackG[row]*track_pitchG + route2actG ;
569 	    }
570 	    rowtop = rowcenter + barrayG[row]->bheight -
571 		        barrayG[row]->bheight / 2;
572 	    D( "twsc/buildDensityArray",
573 		fprintf( stderr, "row:%d oldy:%d newy:%d tracks:%d\n",
574 		    row, barrayG[row]->bycenter, rowcenter,
575 		    maxTrackG[row] ) ;
576 	    ) ;
577 	    barrayG[row]->bycenter = rowcenter ;
578 	}
579     } else {
580 	return ;
581     }
582 
583     for( cell = 1; cell <= numcellsG; cell++ ){
584 	cellptr = carrayG[cell] ;
585 	block = cellptr->cblock ;
586 	corient = cellptr->corient ;
587 	if( block != 0 ){
588 	    cellptr->cycenter = barrayG[block]->bycenter ;
589 	    /* update the y positions on this cell */
590 	    for( pin = cellptr->pins;pin;pin=pin->nextpin ) {
591 		pin->ypos = pin->typos[corient%2] + cellptr->cycenter;
592 	    }
593 	}
594     }
595 
596 } /* end density */
597