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:	    fixcell.c
42 DESCRIPTION:places fixed cells in the correct position during a
43 	    configuration.
44 CONTENTS:   updateFixedCells( initializeFlag )
45 		BOOL initializeFlag ;
46 	    update_fixed_record( fptr )
47 		FIXEDBOXPTR fptr ;
48 	    build_active_array()
49 	    build_soft_array()
50 	    determine_origin( x, y, left_not_right, bottom_not_top )
51 		INT *x, *y ;
52 		BOOL *left_non_right, *bottom_not_top ;
53 DATE:	    Sept 28, 1988
54 REVISIONS:  Oct  27, 1988 - modified update fixed cells so that it
55 		could handle the following cases: fixed at a point,
56 		cell fixed in a neighborhood, group neighborhood
57 		fixed at a point, group neighborhood free.
58 		Added build_active_array which holds all active core
59 		cell including supercells and groupcells to make uloop
60 		more efficient.
61 	    Jan 20, 1989 - added build_soft_array() to make soft pin
62 		moves more efficient.
63 	    Feb 26, 1989 - added determine_origin for graphics interface.
64 	    Mar 13, 1989 - split updateFixedCells to update_fixed_record
65 		to anticipate group cell moves.
66 	    Apr 27, 1989 - added stdcell to list of active cells.
67 	    May 10, 1989 - now use the HOWMANYORIENT field for valid
68 		orientation calculation.
69 	    Apr 17, 1990 - added error checking.
70 	    May  4, 1990 - fixed for standard cell case.
71 	    Mon Feb  4 02:06:08 EST 1991 - updated determine origin
72 		since arguments changed from BOOL to char *.
73 	    Sun May  5 14:25:12 EDT 1991 - added prototypes. Fixed
74 		missing argument to update_fix_record.  Fixed error
75 		checking.
76 	    Wed Jul 24 20:43:22 CDT 1991 - added delete function
77 		for fixing cells.
78 ----------------------------------------------------------------- */
79 
80 #include <string.h>
81 #include <custom.h>
82 #include <yalecad/base.h>
83 #include <yalecad/debug.h>
84 
85 
86 /* defined routes for error checking */
87 VOID updateFixedCells( P1(BOOL initializeFlag) ) ;
88 static VOID update_fixed_record( P3(CELLBOXPTR ptr,FIXEDBOXPTR fptr,
89 				BOOL initFlag ) ) ;
90 VOID init_fixcell( P4(INT left, INT bottom, INT right, INT top ) ) ;
91 VOID build_active_array() ;
92 VOID build_soft_array() ;
93 VOID determine_origin( P4(INT *x, INT *y,
94     char *left_not_right, char *bottom_not_top ) ) ;
95 
96 static INT initialS = FALSE ;
97 static INT newxspanS ;
98 static INT newyspanS ;
99 static INT oldxspanS ;
100 static INT oldyspanS ;
101 
updateFixedCells(BOOL initializeFlag)102 VOID updateFixedCells( BOOL initializeFlag )
103 {
104 
105     INT i ;
106     CELLBOXPTR ptr ;
107     FIXEDBOXPTR fptr ;
108 
109     /* calculate new span of the core region */
110     newxspanS = blockrG - blocklG ;
111     newyspanS = blocktG - blockbG ;
112 
113     /* update positions of fixed cells */
114     for( i=1;i<=endsuperG;i++ ){
115 	ptr = cellarrayG[i] ;
116 	/* for core cells check fixed record */
117 	/* for group cells check group record */
118 	if( ptr->celltype == GROUPCELLTYPE ){
119 	    ASSERTNCONT( ptr->group, "updateFixedCells", "pointer null");
120 	    fptr = ptr->group->fixed ;
121 	} else {
122 	    fptr = ptr->fixed ;
123 	}
124 	update_fixed_record( ptr, fptr, initializeFlag ) ;
125 
126 	if( initializeFlag && ptr->celltype == GROUPCELLTYPE ){
127 	    /* now we can add tiles to group */
128 	    initializeCorner( i ) ;
129 	    addCorner( fptr->x1, fptr->y1 ) ; /* lower left */
130 	    addCorner( fptr->x1, fptr->y2 ) ; /* upper left */
131 	    addCorner( fptr->x2, fptr->y2 ) ; /* upper right */
132 	    addCorner( fptr->x2, fptr->y1 ) ; /* lower right */
133 	    processCorners( 4 ) ;
134 	}
135     }
136 } /* end updateFixCells */
137 
138 /* update all the variables in the fixed box record - that is the */
139 /* the neighborhood and/or the center of the cell for a fixed point */
update_fixed_record(ptr,fptr,initFlag)140 static VOID update_fixed_record( ptr, fptr, initFlag )
141 CELLBOXPTR ptr ;
142 FIXEDBOXPTR fptr ;
143 BOOL initFlag ;
144 {
145     INT x1, x2, y1, y2 ;
146     BOOL error_flag = FALSE ;
147     DOUBLE temp ;
148 
149     if( fptr ){
150 	D( "update_fixed_record",
151 	    fprintf( stderr, "cell:%s\n", ptr->cname ) ;
152 	    fprintf( stderr, "\tinitialS:%d\n", initialS ) ;
153 	    fprintf( stderr, "\toldxspanS:%d ", oldxspanS ) ;
154 	    fprintf( stderr, "\toldyspanS:%d\n", oldyspanS ) ;
155 	    fprintf( stderr, "\tnewxspanS:%d ",  newxspanS ) ;
156 	    fprintf( stderr, "\tnewyspanS:%d\n", newyspanS ) ;
157 	    fprintf( stderr, "\txc:%d yc:%d x1:%d y1:%d x2:%d y2:%d\n",
158 		fptr->xcenter, fptr->ycenter,
159 		fptr->xloc1,fptr->yloc1,fptr->xloc2,fptr->yloc2 ) ;
160 	    fprintf( stderr, "\tx1:%d y1:%d x2:%d y2:%d\n",
161 		fptr->leftNotRight,fptr->bottomNotTop,
162 		fptr->leftNotRight2,fptr->bottomNotTop2 ) ;
163 	) ; /* end debug macro */
164 
165 	if( fptr->fixedType != POINTFLAG ){
166 	    if( initialS ){
167 		/* get two points of neighborhood */
168 		/* POINT ONE */
169 		temp = (DOUBLE) fptr->xloc1 / oldxspanS * newxspanS ;
170 		if( fptr->leftNotRight ){
171 		    /* from left edge  */
172 		    x1 = blocklG + (INT) temp ;
173 		} else {
174 		    /* from right edge = blockx */
175 		    x1 = blockrG - (INT) temp ;
176 		}
177 		temp = (DOUBLE) fptr->yloc1 / oldyspanS * newyspanS ;
178 		if( fptr->bottomNotTop ){
179 		    /* from bottom edge = 0 */
180 		    y1 = blockbG + (INT) temp ;
181 		} else {
182 		    /* from top edge = blocky */
183 		    y1 = blocktG - (INT) temp ;
184 		}
185 		/* POINT TWO */
186 		temp = (DOUBLE) fptr->xloc2 / oldxspanS * newxspanS ;
187 		if( fptr->leftNotRight2 ){
188 		    /* from left edge  */
189 		    x2 = blocklG + (INT) temp ;
190 		} else {
191 		    /* from right edge = blockx */
192 		    x2 = blockrG - (INT) temp ;
193 		}
194 		temp = (DOUBLE) fptr->yloc2 / oldyspanS * newyspanS ;
195 		if( fptr->bottomNotTop2 ){
196 		    /* from bottom edge = 0 */
197 		    y2 = blockbG + (INT) temp ;
198 		} else {
199 		    /* from top edge = blocky */
200 		    y2 = blocktG - (INT) temp ;
201 		}
202 	    } else {
203 		/* get two points of neighborhood */
204 		/* POINT ONE */
205 		if( fptr->leftNotRight ){
206 		    /* from left edge  */
207 		    x1 = blocklG + fptr->xloc1 ;
208 		} else {
209 		    /* from right edge = blockx */
210 		    x1 = blockrG - fptr->xloc1 ;
211 		}
212 		if( fptr->bottomNotTop ){
213 		    /* from bottom edge = 0 */
214 		    y1 = blockbG + fptr->yloc1 ;
215 		} else {
216 		    /* from top edge = blocky */
217 		    y1 = blocktG - fptr->yloc1 ;
218 		}
219 		/* POINT TWO */
220 		if( fptr->leftNotRight2 ){
221 		    /* from left edge  */
222 		    x2 = blocklG + fptr->xloc2 ;
223 		} else {
224 		    /* from right edge = blockx */
225 		    x2 = blockrG - fptr->xloc2 ;
226 		}
227 		if( fptr->bottomNotTop2 ){
228 		    /* from bottom edge = 0 */
229 		    y2 = blockbG + fptr->yloc2 ;
230 		} else {
231 		    /* from top edge = blocky */
232 		    y2 = blocktG - fptr->yloc2 ;
233 		}
234 	    }
235 	    /* sort points */
236 	    fptr->x1 = MIN( x1, x2 ) ;
237 	    fptr->x2 = MAX( x1, x2 ) ;
238 	    fptr->y1 = MIN( y1, y2 ) ;
239 	    fptr->y2 = MAX( y1, y2 ) ;
240 	    if(!(initFlag)){
241 		/* check to make sure neighborhood is inside core */
242 		if( fptr->x1 < blocklG ){
243 		    if( iterationG >= 2 ) fptr->x1 = blocklG ;
244 		    error_flag = TRUE ;
245 		}
246 		if( fptr->x1 > blockrG ){
247 		    if( iterationG >= 2 ) fptr->x1 = blockrG ;
248 		    error_flag = TRUE ;
249 		}
250 		if( fptr->x2 < blocklG ){
251 		    if( iterationG >= 2 ) fptr->x2 = blocklG ;
252 		    error_flag = TRUE ;
253 		}
254 		if( fptr->x2 > blockrG ){
255 		    if( iterationG >= 2 ) fptr->x2 = blockrG ;
256 		    error_flag = TRUE ;
257 		}
258 		if( fptr->y1 < blockbG ){
259 		    if( iterationG >= 2 ) fptr->y1 = blockbG ;
260 		    error_flag = TRUE ;
261 		}
262 		if( fptr->y1 > blocktG ){
263 		    if( iterationG >= 2 ) fptr->y1 = blocktG ;
264 		    error_flag = TRUE ;
265 		}
266 		if( fptr->y2 < blockbG ){
267 		    if( iterationG >= 2 ) fptr->y2 = blockbG ;
268 		    error_flag = TRUE ;
269 		}
270 		if( fptr->y2 > blocktG ){
271 		    if( iterationG >= 2 ) fptr->y2 = blocktG ;
272 		    error_flag = TRUE ;
273 		}
274 	    }
275 
276 	    /* now perform calculations for speed */
277 	    fptr->xcenter = (fptr->x1 + fptr->x2) / 2 ;
278 	    fptr->ycenter = (fptr->y1 + fptr->y2) / 2 ;
279 	    fptr->xspan = ABS(fptr->x1 - fptr->x2) ;
280 	    fptr->yspan = ABS(fptr->y1 - fptr->y2) ;
281 
282 	    if( error_flag ){
283 		sprintf( YmsgG, "cell:%s neighborhood larger than core\n",
284 		    ptr->cname ) ;
285 
286 		M( WARNMSG,"update_fixed_cells", YmsgG ) ;
287 
288 		if( iterationG >= 2 ){
289 		    /* we can't do anything with this constraint */
290 		    /* throw it out */
291 		    if( ptr->celltype == GROUPCELLTYPE ){
292 			fptr = ptr->group->fixed ;
293 			Ysafe_free( fptr ) ;
294 			ptr->group->fixed = NIL(FIXEDBOXPTR) ;
295 		    } else {
296 			fptr = ptr->fixed ;
297 			Ysafe_free( fptr ) ;
298 			ptr->fixed = NIL(FIXEDBOXPTR) ;
299 		    }
300 		    M( WARNMSG,NULL,"\tconstraint ignored...\n" ) ;
301 		}
302 	    }
303 
304 	} else {  /* cell is fixed at a point */
305 	    if( initialS ){
306 		temp = (DOUBLE) fptr->xcenter / oldxspanS * newxspanS ;
307 		if( fptr->leftNotRight ){
308 		    /* from left edge  */
309 		    ptr->xcenter = blocklG + (INT) temp ;
310 		} else {
311 		    /* from right edge = blockx */
312 		    ptr->xcenter = blockrG - (INT) temp ;
313 		}
314 		if( fptr->bottomNotTop ){
315 		    /* from bottom edge = 0 */
316 		    ptr->ycenter = blockbG + fptr->ycenter ;
317 		} else {
318 		    /* from top edge = blocky */
319 		    ptr->ycenter = blocktG - fptr->ycenter ;
320 		}
321 	    } else {
322 		if( fptr->leftNotRight ){
323 		    /* from left edge  */
324 		    ptr->xcenter = blocklG + fptr->xcenter ;
325 		} else {
326 		    /* from right edge = blockx */
327 		    ptr->xcenter = blockrG - fptr->xcenter ;
328 		}
329 		if( fptr->bottomNotTop ){
330 		    /* from bottom edge = 0 */
331 		    ptr->ycenter = blockbG + fptr->ycenter ;
332 		} else {
333 		    /* from top edge = blocky */
334 		    ptr->ycenter = blocktG - fptr->ycenter ;
335 		}
336 	    }
337 	    if(!(initFlag)){
338 		/* now perform error checking to make sure inside core */
339 		if( ptr->xcenter < blocklG ){
340 		    if( iterationG >= 2 ) ptr->xcenter = blocklG ;
341 		    error_flag = TRUE ;
342 		}
343 		if( ptr->xcenter > blockrG ){
344 		    if( iterationG >= 2 ) ptr->xcenter = blockrG ;
345 		    error_flag = TRUE ;
346 		}
347 		if( ptr->ycenter < blockbG ){
348 		    if( iterationG >= 2 ) ptr->ycenter = blockbG ;
349 		    error_flag = TRUE ;
350 		}
351 		if( ptr->ycenter > blockrG ){
352 		    if( iterationG >= 2 ) ptr->ycenter = blockrG ;
353 		    error_flag = TRUE ;
354 		}
355 	    }
356 	    if( error_flag ){
357 		sprintf( YmsgG, "cell:%s fix point larger than core\n",
358 		    ptr->cname ) ;
359 
360 		M( WARNMSG,"update_fixed_cells", YmsgG ) ;
361 
362 		if( iterationG >= 2 ){
363 		    /* we can't do anything with this constraint */
364 		    /* throw it out */
365 		    if( ptr->celltype == GROUPCELLTYPE ){
366 			fptr = ptr->group->fixed ;
367 			Ysafe_free( fptr ) ;
368 			ptr->group->fixed = NIL(FIXEDBOXPTR) ;
369 		    } else {
370 			fptr = ptr->fixed ;
371 			Ysafe_free( fptr ) ;
372 			ptr->fixed = NIL(FIXEDBOXPTR) ;
373 		    }
374 		    M( WARNMSG,NULL,"\tconstraint ignored...\n" ) ;
375 		}
376 	    }
377 	}
378     } /* end for loop */
379 } /* end function update_fixed_record */
380 
init_fixcell(left,bottom,right,top)381 VOID init_fixcell( left, bottom, right, top )
382 INT left, bottom, right, top ;
383 {
384     initialS = TRUE ;
385     oldxspanS = right - left ;
386     oldyspanS = top - bottom ;
387     if( oldxspanS <= 0 ){
388 	M( ERRMSG, "init_fixcell", "initial x core span <= 0\n" ) ;
389 	initialS = FALSE ;
390     }
391     if( oldyspanS <= 0 ){
392 	M( ERRMSG, "init_fixcell", "initial y core span <= 0\n" ) ;
393 	initialS = FALSE ;
394     }
395 } /* end init_fixcell */
396 
397 /* build active cell list from cells that aren't fixed */
398 VOID
build_active_array()399 build_active_array()
400 {
401     INT i, cell ;
402     CELLBOXPTR cptr ;
403 
404     /* first determine number of active cells */
405     activecellsG = 0 ;
406     for( i=1;i<=totalcellsG;i++ ){
407 	cptr = cellarrayG[i] ;
408 	if( cptr->fixed ){
409 	    if( cptr->celltype == CUSTOMCELLTYPE ||
410 		cptr->celltype == SOFTCELLTYPE ||
411 		cptr->celltype == STDCELLTYPE ){
412 		/* must check to orientations are all fixed also */
413 		if( cptr->orientList[HOWMANYORIENT] >= 2 ){
414 		    /* cell is not totally inactive it may rotate */
415 		    activecellsG++ ;
416 		}
417 	    }
418 
419 	} else if( cptr->celltype == CUSTOMCELLTYPE ||
420 	    cptr->celltype == SOFTCELLTYPE ||
421 	    cptr->celltype == SUPERCELLTYPE ||
422 	    cptr->celltype == STDCELLTYPE ||
423 	    cptr->celltype == GROUPCELLTYPE ){
424 	    activecellsG++ ;
425 	}
426     }
427     /* now build array */
428     activeCellarrayG = (CELLBOXPTR *)
429 	Ysafe_malloc( (activecellsG+1) * sizeof(CELLBOXPTR) ) ;
430     /* now loop again filling in array */
431     cell = 0 ;
432     for( i=1;i<=totalcellsG;i++ ){
433 	cptr = cellarrayG[i] ;
434 	if( cptr->fixed ){
435 	    if( cptr->celltype == CUSTOMCELLTYPE ||
436 		cptr->celltype == SOFTCELLTYPE ||
437 		cptr->celltype == STDCELLTYPE ){
438 		if( cptr->orientList[HOWMANYORIENT] >= 2 ){
439 		    /* cell is not totally inactive it may rotate */
440 		    activeCellarrayG[++cell] = cptr ;
441 		}
442 	    }
443 
444 	} else if( cptr->celltype == CUSTOMCELLTYPE ||
445 	    cptr->celltype == SOFTCELLTYPE ||
446 	    cptr->celltype == SUPERCELLTYPE ||
447 	    cptr->celltype == STDCELLTYPE ||
448 	    cptr->celltype == GROUPCELLTYPE ){
449 	    activeCellarrayG[++cell] = cptr ;
450 	}
451     }
452     ASSERT( cell == activecellsG,"build_active_array",
453 	"Problem with count" ) ;
454 
455 } /* end build_active_array */
456 
457 /* build softPinArrayG so that soft pin moves are more efficient */
458 /* softPinArray will contain the cellptrs of all softcells which */
459 /* have pins that can move.  The zeroth element will contain howmany */
460 VOID
build_soft_array()461 build_soft_array()
462 {
463 
464 #define HOWMANY 0  /* this tells the size of the array */
465 
466     INT i, cell ;
467     CELLBOXPTR cptr ;
468     INT softPins ;
469 
470     softPins = 0 ;
471     if( numsoftG > 0 || numstdcellG > 0 ){
472 	/* first determine number of softcell with uncommitted pins */
473 	for( i=1;i<=totalcellsG;i++ ){
474 	    cptr = cellarrayG[i] ;
475 	    if( cptr->celltype == SOFTCELLTYPE ||
476 	        cptr->celltype == STDCELLTYPE ){
477 		if( cptr->numpins > 0 ){
478 		    softPins++ ;
479 		}
480 	    }
481 	}
482 
483 	/* now build array */
484 	softPinArrayG = (CELLBOXPTR *)
485 	    Ysafe_malloc( (softPins+1) * sizeof(CELLBOXPTR) ) ;
486 	/* now loop again filling in array */
487 	cell = 0 ;
488 	for( i=1;i<=totalcellsG;i++ ){
489 	    cptr = cellarrayG[i] ;
490 	    if( cptr->celltype == SOFTCELLTYPE ||
491 	        cptr->celltype == STDCELLTYPE ){
492 		if( cptr->numpins > 0 ){
493 		    softPinArrayG[++cell] = cptr ;
494 		}
495 	    }
496 	}
497 	ASSERT( cell == softPins,"build_soft_array",
498 	    "Problem with count" ) ;
499 	softPinArrayG[HOWMANY] = (CELLBOXPTR) softPins ;
500 
501     } else {
502 	softPinArrayG = (CELLBOXPTR *) Ysafe_malloc( sizeof(CELLBOXPTR) ) ;
503 	softPinArrayG[HOWMANY] = (CELLBOXPTR) softPins ; /* zero */
504     }
505 
506 } /* end build_soft_array */
507 
508 /* In fixing a cell, determine which side of the core to reference */
509 /* cell so that changes to the position of the cell due to core size */
510 /* changes will be minimized. */
determine_origin(INT * x,INT * y,char * left_not_right,char * bottom_not_top)511 VOID determine_origin( INT *x, INT *y, char *left_not_right, char *bottom_not_top )
512 //INT *x, *y ; /* point of reference */
513 {
514     if( *x <= blockmxG ){
515 	strcpy( left_not_right, "L" ) ;
516     } else {
517 	strcpy( left_not_right, "R" ) ;
518 	/* reference to right side need to change x coordinate */
519 	*x = blockrG - *x ;
520     }
521     if( *y <= blockmyG ){
522 	strcpy( bottom_not_top, "B" ) ;
523     } else {
524 	strcpy( bottom_not_top, "T" ) ;
525 	/* reference to top side need to change x coordinate */
526 	*y = blocktG - *y ;
527     }
528 } /* end determine_origin */
529 
delete_fix_constraint(cell)530 void delete_fix_constraint( cell )
531 INT cell ;
532 {
533     CELLBOXPTR ptr ;
534 
535     ptr = cellarrayG[cell] ;
536     if( ptr->fixed != (FIXEDBOXPTR)NULL ){
537 	Ysafe_free(ptr->fixed) ;
538     }
539     ptr->fixed = NIL(FIXEDBOXPTR) ;
540     ptr->class = 0 ;
541 } /* end delete_fix_constraint */
542