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:	    initialize.c
42 DESCRIPTION:This file contains the utility routines called from the
43 	    parser to set up the TimberWolfMC data structures.
44 CONTENTS:
45 	    setErrorFlag()
46 DATE:	    Aug  7, 1988
47 REVISIONS:  Oct 27, 1988 - added add_cell_to_group, initializeCorner
48 		and modified fixCell in order to handle group cells.
49 	    Jan 20, 1989 - added build_soft_array call.
50 	    Jan 29, 1989 - changed msg to YmsgG and added \n's.
51 	    Feb 28, 1989 - added initialization to tile weights.
52 	    Mar  7, 1989 - added cell instances.
53 			 - added cell hash table for instance names.
54 	    Apr  5, 1989 - added multiple tiles for softcells and
55 		added instance handling.  Instances are handled by
56 		disturbing routines as little as possible and using
57 		pointer swaps to switch in a new instance as much as
58 		possible.
59 	    Apr 9, 1989 - added sortpin to cleanupCells for incremental
60 		bounding box scheme.
61 	    Apr 30, 1989 - changed exchange class for group cells.
62 			 - fixed problem with pad group children.
63 	    May  1, 1989 - orient the pads correctly.
64 	    May 11, 1989 - now use the orientList[HOWMANYORIENT] to
65 		specify the number of valid orientations.
66 	    May 12, 1989 - added layer information.
67 	    May 25, 1989 - changed tiles list to FIFO from LIFO for
68 		cell gridding..
69 	    Jul 19, 1989 - added numstdcells to save work for partition case
70 		with no hard or soft cells.
71 	    Sep 29, 1989 - remove max tile limit by making dynamic.
72 	    Oct 18, 1989 - Added tile to pad macros for density calc.
73 	    Apr 15, 1990 - Modified cur_inst fields.  Added vertices
74 		fields to cell box for placing pins.  Moved pintype
75 		field to PINBOX from SOFTBOX.  Made fixed field of
76 		GROUPBOX a pointer.
77 	    Apr 17, 1990 - added load_soft_pins which verifies
78 		user input and correctly sets up wire estimator.
79 	    Apr 23, 1990 - now handle pingroup instances and also
80 		fixed wire area estimator for instances by looking
81 		at all instances when calculating the perimeter.
82 	    Apr 26, 1990 - distinguish arbitrarily assigned layer
83 		information using negative numbers.
84 	    May  2, 1990 - Now all pins on softcells have softinfo
85 		records to avoid access violations.  Added error
86 		checking to processCorners to catch points not entered
87 		in a CW fashion.
88 	    Jun 21, 1990 - moved the location of genorient so that
89 		the pins will be in the correct orientation before the
90 		check.
91 	    Oct 1, 1990 - updated analog input data structures.
92 	    Sun Dec 16 00:38:44 EST 1990 - reworked analog data
93 		structures and added check for rectilinear pins.
94 	    Tue Dec 18 01:29:30 EST 1990 - make sure the buster
95 		check error messages go to screen properly.
96 	    Wed Dec 19 23:58:12 EST 1990 - added check_pos.
97 	    Dec 21, 1990 - added set_pin_pos and rewrote addPin
98 		to make pins more general.
99 	    Thu Jan 17 00:55:28 PST 1991 - added numpins initialization.
100 	    Wed Jan 23 14:42:30 PST 1991 - added findsidestr in order
101 		to make language context free.
102 	    Fri Jan 25 18:05:56 PST 1991 - now scale data correctly.
103 	    Wed Jan 30 14:13:36 EST 1991 - now left justify orientation
104 		rotations.
105 	    Mon Feb  4 02:10:28 EST 1991 - made changes to make new pin
106 		placement code work and fixed numsides bug.
107 	    Wed Feb 13 23:52:38 EST 1991 - modified for new pad code.
108 	    Sat Feb 23 00:21:10 EST 1991 - updated for new pad placement
109 		code.
110 	    Thu Apr 18 01:34:59 EDT 1991 - added more error checking
111 		and fixed problem with initial orientation.
112 	    Sat Apr 27 01:15:05 EDT 1991 - now detect doPartition case
113 		automatically.
114 	    Thu Aug 22 22:10:09 CDT 1991 - fixed problem with
115 		fixed cells moving during pairwise flips.
116 	    Fri Oct 18 00:06:37 EDT 1991 - moved buster code to library
117 		and updated for new NIL definition.
118 ----------------------------------------------------------------- */
119 
120 #include <string.h>
121 #include <custom.h>
122 #include <pads.h>
123 #include <analog.h>
124 #include <initialize.h>
125 #include <yalecad/buster.h>
126 #include <yalecad/hash.h>
127 #include <yalecad/debug.h>
128 #include <yalecad/string.h>
129 #include <findside.h>
130 
131 
132 /* below is what we expect to be a large floorplanning input */
133 /* user may change parameters if they wish. Subject to change */
134 #define EXPECTEDNUMCELLS   500
135 #define EXPECTEDNUMNETS   1000
136 #define EXPECTEDNUMUNCON  100
137 #define EXPECTEDNUMPADS   10
138 #define EXPECTEDCORNERS   8
139 #define EXPECTEDINSTANCES 1
140 #define EXPECTEDPINGRP    1
141 
142 #define PIN   (BOOL)      TRUE       /* for pinFlag below */
143 #define EQUIV (BOOL)      FALSE
144 #define NUMPADMACROS      4 /* there are always 4 pad macros */
145 #define INITIALIZE        (BOOL) TRUE  /* for updateFixedCells */
146 
147 /* ERRORABORT is a macro which forces routines not to do any work */
148 /* when we find a syntax error in the input routine. */
149 #define ERRORABORT() \
150 { \
151     if( errorFlagS ){ \
152 	return ; /* don't do any work for errors */ \
153     } \
154 } \
155 
156 #define ERRORABORTINT() \
157 { \
158     if( errorFlagS ){ \
159 	return -1; /* don't do any work for errors */ \
160     } \
161 } \
162 
163 /* ######################  STATIC definitions ######################### */
164 static INT  curCellTypeS ;  /* current cell type - ie, softcell,pad etc.*/
165 static INT  cellinstanceS ; /* number of instances of current cell      */
166 static INT  cornerCountS ;  /* current number of corners                */
167 static INT  tileptAllocS ;  /* allocation allotted to tile structures   */
168 static INT  xcenterS, ycenterS ;/* current cell center coordinates      */
169 static INT  minxS, minyS ;  /* bounding box of current cell             */
170 static INT  maxxS, maxyS ;  /* bounding box of current cell             */
171 static INT  totPinS ;       /* total number of pins over all instances  */
172 static INT  netAllocS ;     /* current space in netarray                */
173 static INT  cellAllocS ;    /* current space in cellarray               */
174 static INT  childAllocS ;   /* current space in current pptr->children  */
175 static INT  instAllocS ;    /* current number of instance allocated     */
176 static INT  equivpinS ;   /* total number of equivs for the current pin */
177 static INT  totxS, totyS ;  /* counters for equiv pin postions          */
178 static INT  numchildrenS ;  /* # of children in current pad or pingroup */
179 static INT  numpingroupS ;  /* # of pingroups for this cell             */
180 static INT cur_restrict_objS ; /* set by set_restrict type              */
181 static char *curCellNameS ; /* current cell name                        */
182 static char *curPinNameS ;   /* current pin name                        */
183 static BOOL portFlagS ; /* tells whether port(TRUE) or not(FALSE)       */
184 static BOOL errorFlagS ;    /* switch allow us to find multiple errors  */
185 static BOOL analog_errorS ; /* whether an analog error occurs           */
186 static DOUBLE scaleS ;      /* how to scale the data                    */
187 static CELLBOXPTR ptrS ;    /* pointer to current cell box              */
188 static PADBOXPTR pptrS ;    /* pointer to current pad box               */
189 static YBUSTBOXPTR cornerArrayS;/* holds array of pts for cell boundary */
190 static YHASHPTR netTableS ;    /* hash table for cross referencing nets */
191 static YHASHPTR cellTableS ;   /* hash table for referencing cells      */
192 static PSIDEBOX   *pSideArrayS;/* used to calc the side weighs of cell  */
193 static KBOXPTR kArrayS ;       /* used in making sides for softpins     */
194 static GROUPBOXPTR curGroupS ; /* pointer to current group record       */
195 static PINBOXPTR   pinS ;      /* current active pin of cell            */
196 static PINBOXPTR   softpinS ;  /* current active softpin of cell        */
197 static PINBOXPTR pingroupS ;   /* current pin group record              */
198 static ANALOGPTR analogS ;     /* current analog record                 */
199 static SOFTBOXPTR spinptrS ;   /* current softpin record                */
200 static INSTBOXPTR instS ;      /* pointer to current inst record        */
201 PINBOXPTR findTerminal() ;
202 /* ################## END STATIC definitions ########################## */
203 
204 
205 
206 static void check_pos();
207 
208 
209 
210 /* set processing switch to avoid work when an error is found */
setErrorFlag()211 void setErrorFlag()
212 {
213 errorFlagS = TRUE ;
214 } /* end setErrorFlag */
215 /* ***************************************************************** */
216 
217 /* return the net hash table */
getNetTable()218 YHASHPTR getNetTable()
219 {
220 return( netTableS ) ;
221 } /* end getNetTable */
222 /* ***************************************************************** */
223 
224 /* initialize global and static information */
initCellInfo()225 void initCellInfo()
226 {
227 numcellsG = 0 ;
228 numnetsG = 0 ;
229 numsoftG = 0 ;
230 numstdcellG = 0 ;
231 numpadsG = 0 ;
232 numpadgroupsG = 0 ;
233 numsupercellsG = 0 ;
234 numinstancesG = 0 ;
235 numpinsG = 0 ;
236 totalcellsG = 0 ;
237 totalpadsG = 0 ;
238 errorFlagS = FALSE ;
239 analog_errorS = FALSE ;
240 totPinS = 0 ;
241 unique_classG = 0 ;
242 net_cap_matchG = NIL(INT **) ;
243 net_res_matchG = NIL(INT **) ;
244 scaleS = (DOUBLE) scale_dataG ;
245 cornerCountS = 0 ;
246 tileptAllocS = EXPECTEDCORNERS ;
247 cornerArrayS = ( YBUSTBOXPTR )
248     Ysafe_malloc( tileptAllocS * sizeof( YBUSTBOX ) );
249 pSideArrayS  = (PSIDEBOX *) Ysafe_malloc( tileptAllocS * sizeof( PSIDEBOX ) ) ;
250 kArrayS      = (KBOXPTR) Ysafe_calloc( (MAXSITES + 1), sizeof( KBOX ));
251 /* make hash table for nets */
252 netTableS = Yhash_table_create( EXPECTEDNUMNETS ) ;
253 /* make hash table for cells */
254 cellTableS = Yhash_table_create( EXPECTEDNUMCELLS ) ;
255 netAllocS = EXPECTEDNUMNETS ;
256 netarrayG = (NETBOXPTR *) Ysafe_malloc( netAllocS * sizeof(NETBOXPTR));
257 cellAllocS = EXPECTEDNUMCELLS ;
258 cellarrayG = (CELLBOXPTR *)Ysafe_malloc(cellAllocS*sizeof(CELLBOXPTR));
259 } /* end initCellInfo */
260 /* ***************************************************************** */
261 
262 /* cleanup operations at the end of readcells */
cleanupReadCells()263 void cleanupReadCells()
264 {
265     INT cell ;           /* cell counter */
266     PADBOXPTR padptr ;   /* current pad */
267     CELLBOXPTR ptr ;     /* current pad cell */
268 
269 if( errorFlagS || analog_errorS ){
270     /* we found all our syntax errors so abort */
271     closegraphics() ;
272     YexitPgm( FAIL ) ;
273 }
274 
275 /* the last cells - create pad macros for channel graph generator */
276 addCell("pad.macro.l",PADMACROTYPE ) ;
277 /* add a tile for processing borders */
278 ptrS->tiles = (TILEBOXPTR) Ysafe_calloc( 1, sizeof(TILEBOX) ) ;
279 endCell() ;
280 addCell("pad.macro.t",PADMACROTYPE ) ;
281 /* add a tile for processing borders */
282 ptrS->tiles = (TILEBOXPTR) Ysafe_calloc( 1, sizeof(TILEBOX) ) ;
283 endCell() ;
284 addCell("pad.macro.r",PADMACROTYPE ) ;
285 /* add a tile for processing borders */
286 ptrS->tiles = (TILEBOXPTR) Ysafe_calloc( 1, sizeof(TILEBOX) ) ;
287 endCell() ;
288 addCell("pad.macro.b",PADMACROTYPE ) ;
289 /* add a tile for processing borders */
290 ptrS->tiles = (TILEBOXPTR) Ysafe_calloc( 1, sizeof(TILEBOX) ) ;
291 endCell() ;
292 
293 /* reallocate arrays to correct size */
294 netarrayG = (NETBOXPTR *)
295     Ysafe_realloc( netarrayG, (numnetsG+1) * sizeof(NETBOXPTR) ) ;
296 /* allocate and initialize terminal array */
297 termarrayG = (PINBOXPTR *)
298     Ysafe_calloc( (numpinsG + 1), sizeof( PINBOXPTR ) );
299 /* now trim cellarray to proper size */
300 endsuperG = numcellsG + numsupercellsG ;
301 endpadsG = endsuperG + numpadsG ;
302 endpadgrpsG = endpadsG + numpadgroupsG ;
303 ASSERT( totalcellsG == endpadgrpsG+NUMPADMACROS,"cleanupReadCells",
304     "cells don't add up" ) ;
305 cellarrayG = (CELLBOXPTR *)
306     Ysafe_realloc( cellarrayG,(totalcellsG+1)* sizeof(CELLBOXPTR) ) ;
307 
308 /* build the pad arrays */
309 padarrayG = (PADBOXPTR *) Yvector_alloc(1,totalpadsG,sizeof(PADBOXPTR)) ;
310 sortarrayG = (PADBOXPTR *) Yvector_alloc(1,totalpadsG,sizeof(PADBOXPTR));
311 placearrayG = (PADBOXPTR *) Yvector_alloc( 1,numpadsG,sizeof(PADBOXPTR)) ;
312 for( cell = 1; cell <= totalpadsG; cell++ ){
313     ptr = cellarrayG[endsuperG + cell] ;
314     padptr = ptr->padptr ;
315     sortarrayG[cell] = padarrayG[cell] = padptr ;
316     if( padptr->padtype == PADCELLTYPE ){
317 	placearrayG[cell] = padptr ;
318     }
319 }
320 
321 /* set loop index range variables for cellarray */
322 pinsPerLenG = (DOUBLE) totPinS / (DOUBLE) perimG ;
323 setpwates() ;
324 sortpins() ;
325 prnt_netinfo() ;   /* tell user net information */
326 genorient(1,endpadsG ) ;
327 updateFixedCells( INITIALIZE ) ;
328 loadTermArray() ;
329 build_active_array() ;
330 build_soft_array() ;
331 set_up_pinplace() ;   /* for soft cell pin placement */
332 update_pins(TRUE) ;  /* initial pin placement */
333 
334 /* free memory */
335 Ysafe_free(cornerArrayS) ;
336 Ysafe_free(pSideArrayS) ;
337 Ysafe_cfree(kArrayS) ;
338 Ybuster_free() ;
339 
340 } /* end cleanupReadCells */
341 /* ***************************************************************** */
342 
343 /* add another cell to cell list and initialize fields */
addCell(char * cellName,CELLTYPE cellType)344 void addCell( char * cellName, CELLTYPE cellType )
345 {
346 INT i ;
347 INT *data ;
348 
349 curCellNameS = cellName ; /* for error messages */
350 curCellTypeS = cellType ;
351 ERRORABORT() ;
352 
353 /* check memory of cell array */
354 if( ++totalcellsG >= cellAllocS ){
355     cellAllocS += EXPECTEDNUMCELLS ;
356     cellarrayG = (CELLBOXPTR *)
357 	Ysafe_realloc( cellarrayG, cellAllocS*sizeof(CELLBOXPTR) );
358 }
359 ptrS = cellarrayG[totalcellsG] = (CELLBOXPTR)
360     Ysafe_malloc( sizeof(CELLBOX) ) ;
361 
362 /* add cell to hash table */
363 data = (INT *) Ysafe_malloc( sizeof(INT) ) ;
364 *data = totalcellsG ;
365 if( Yhash_search( cellTableS, curCellNameS, (char *) data, ENTER ) ){
366     sprintf( YmsgG, "Cellnames not unique:%s\n", curCellNameS ) ;
367     M(ERRMSG,"addCell",YmsgG ) ;
368     Ysafe_free( data ) ;
369     errorFlagS = TRUE ;
370 }
371 ptrS->cname = cellName ; /* memory allocation in yylex */
372 ptrS->celltype = cellType ;
373 ptrS->xcenter    = 0 ;
374 ptrS->ycenter    = 0 ;
375 ptrS->orient     = 0 ;
376 ptrS->numtiles   = 0 ;
377 ptrS->numpins    = 0 ;
378 ptrS->cur_inst   = 0 ;
379 ptrS->fixed = NULL ;
380 ptrS->group_nested = FALSE ;
381 ptrS->paths = NULL ;
382 ptrS->aspect = 1.0 ;
383 ptrS->aspUB = 1.0 ;
384 ptrS->aspLB = 1.0 ;
385 ptrS->pinptr = NULL ;
386 ptrS->softpins = NULL ;
387 ptrS->instptr = NULL ;
388 ptrS->padptr = NULL ;
389 ptrS->group = NULL ;
390 ptrS->tiles = NULL ;
391 ptrS->bounBox = NULL ;
392 ptrS->nets = NULL ;
393 ptrS->orientList[HOWMANYORIENT] = 0 ;
394 if( cellType == SOFTCELLTYPE || cellType == CUSTOMCELLTYPE ||
395     cellType == STDCELLTYPE ){
396     for( i = 0 ; i < 8 ; i++ ) {
397 	ptrS->orientList[i] = FALSE ;
398     }
399 } else {
400     /* for pads all orientations are valid */
401     for( i = 0 ; i < 8 ; i++ ) {
402 	ptrS->orientList[i] = TRUE ;
403     }
404 }
405 if( cellType == SOFTCELLTYPE ){
406     ptrS->padptr = NULL ;
407     ptrS->softflag = TRUE ;
408     /* allocate space for uncommitted pins array */
409     numcellsG++ ;
410     numsoftG++ ;
411     numpingroupS = 0 ;
412 } else if( cellType == STDCELLTYPE ){
413     ptrS->padptr = NULL ;
414     ptrS->softflag = TRUE ;
415     /* allocate space for uncommitted pins array */
416     numcellsG++ ;
417     numstdcellG++ ;
418     doPartitionG = TRUE ;
419 } else if( cellType == CUSTOMCELLTYPE){
420     ptrS->softflag = FALSE ;
421     ptrS->padptr = NULL ;
422     numcellsG++ ;
423 } else if( cellType == PADCELLTYPE || cellType == PADGROUPTYPE){
424     ptrS->softflag = FALSE ;
425     pptrS =ptrS->padptr =
426 	(PADBOXPTR) Ysafe_malloc( sizeof(PADBOX) ) ;
427     pptrS->fixed = FALSE ;
428     pptrS->padside = ALL ;
429     pptrS->permute = FALSE ;
430     pptrS->ordered = FALSE ;
431     pptrS->lowerbound  = 0.0 ;
432     pptrS->upperbound  = 1.0 ;
433     pptrS->padtype = cellType ;
434     pptrS->cellnum = totalcellsG ;
435     pptrS->valid_side[0] = TRUE ;
436     pptrS->valid_side[1] = FALSE ;
437     pptrS->valid_side[2] = FALSE ;
438     pptrS->valid_side[3] = FALSE ;
439     pptrS->valid_side[4] = FALSE ;
440     totalpadsG++ ;
441     if( cellType == PADGROUPTYPE ){
442 	numchildrenS = 0 ;
443 	childAllocS = EXPECTEDNUMPADS ;
444 	pptrS->children = (INT *)
445 	    Ysafe_malloc((childAllocS)*sizeof(INT));
446 	pptrS->hierarchy  = ROOT;
447 	numpadgroupsG++ ;
448     } else { /* PADCELLTYPE */
449 	pptrS->children = NULL;
450 	pptrS->hierarchy = NONE;
451 	numpadsG++ ;
452     }
453 } else if( cellType == SUPERCELLTYPE || cellType == GROUPCELLTYPE ){
454     numsupercellsG++ ;
455     unique_classG-- ;/* start new exchange class for group cells */
456     /* allocate group record and set static */
457     curGroupS =ptrS->group =
458 	(GROUPBOXPTR) Ysafe_malloc( sizeof(GROUPBOX) ) ;
459     curGroupS->fixed = (FIXEDBOXPTR) Ysafe_calloc( 1,sizeof(FIXEDBOX) ) ;
460     curGroupS->cells = NULL ;
461 } else if( cellType == PADMACROTYPE ){
462     /* do nothing right now */
463 }
464 cellinstanceS = 0 ; /* beginning of possible instancelist */
465 
466 /* save cellnumber */
467 ptrS->cellnum = totalcellsG ;
468 
469 /* reset xmin, ymax, etc. counters */
470 minxS = INT_MAX ;
471 minyS = INT_MAX ;
472 maxxS = INT_MIN ;
473 maxyS = INT_MIN ;
474 cornerCountS = 0 ;
475 portFlagS = FALSE ;
476 
477 } /* end addCell */
478 /* ***************************************************************** */
479 
480 /* perform cleanup operations on a cell */
endCell()481 void endCell()
482 {
483 ERRORABORT() ;
484 
485 /* set the pSideArray for the softpins */
486 load_soft_pins( ptrS, pSideArrayS ) ;
487 
488 if( curCellTypeS == CUSTOMCELLTYPE || curCellTypeS == SOFTCELLTYPE ||
489     curCellTypeS == STDCELLTYPE ){
490     watesides( ptrS, pSideArrayS ) ;
491 }
492 if( curCellTypeS == SOFTCELLTYPE || curCellTypeS == STDCELLTYPE ){
493 } else if( curCellTypeS == PADGROUPTYPE){
494     /* realloc size of children array to final size */
495     pptrS->children = (INT *)
496 	Ysafe_realloc( pptrS->children,(numchildrenS+1) * sizeof(INT));
497     pptrS->children[HOWMANY] = numchildrenS ;
498 }
499 if( cellinstanceS ){
500     /* first save values to instance arrays */
501     instS->tile_inst[cellinstanceS] = ptrS->tiles ;
502     instS->vert_inst[cellinstanceS] = ptrS->vertices ;
503     instS->numtile_inst[cellinstanceS] = ptrS->numtiles ;
504     instS->name_inst[cellinstanceS] = ptrS->cname ;
505     instS->bounBox[cellinstanceS] = ptrS->bounBox ;
506     instS->numsides[cellinstanceS] = ptrS->numsides ;
507     ptrS->cur_inst = cellinstanceS ;
508 }
509 
510 } /* end function endCell */
511 
512 /* ***************************************************************** */
findsidestr(side,direction)513 static INT findsidestr( side, direction )
514 char *side ;
515 BOOL direction ;
516 {
517     if( direction == TRUE ){
518 	/* BT case */
519 	if( strcmp( side, "B" ) == STRINGEQ ){
520 	    return( TRUE ) ;
521 	} else if( strcmp( side, "T" ) == STRINGEQ ){
522 	    return( FALSE ) ;
523 	}
524     } else {
525 	/* LR case */
526 	if( strcmp( side, "L" ) == STRINGEQ ){
527 	    return( TRUE ) ;
528 	} else if( strcmp( side, "R" ) == STRINGEQ ){
529 	    return( FALSE ) ;
530 	}
531     }
532     sprintf( YmsgG, "Unknown side:%s\n", side ) ;
533     M(ERRMSG,"findside", YmsgG ) ;
534     setErrorFlag() ;
535     return( FALSE ) ;
536 } /* end findsidestr */
537 
538 /* ***************************************************************** */
539 
fixCell(INT fixedType,INT xloc,char * lorR,INT yloc,char * borT,INT xloc2,char * lorR2,INT yloc2,char * borT2)540 void fixCell( INT fixedType, INT xloc, char *lorR, INT yloc, char *borT, INT xloc2, char *lorR2, INT yloc2, char *borT2 )
541 //INT fixedType ;  /* valid types - neighborhood. point, group */
542 {
543 
544 INT leftOrRight, bottomOrTop ;
545 INT leftOrRight2, bottomOrTop2 ;
546 FIXEDBOXPTR fixptr ;
547 
548 if( scale_dataG ){
549     xloc  = (INT) ( (DOUBLE) xloc / scaleS )  ;
550     yloc  = (INT) ( (DOUBLE) yloc / scaleS ) ;
551     xloc2 = (INT) ( (DOUBLE) xloc2 / scaleS ) ;
552     yloc2 = (INT) ( (DOUBLE) yloc2 / scaleS ) ;
553 }
554 
555 leftOrRight = findsidestr( lorR, FALSE ) ; /* left right */
556 bottomOrTop = findsidestr( borT, TRUE ) ;  /* bottom top */
557 leftOrRight2 = findsidestr( lorR2, FALSE ) ; /* left right */
558 bottomOrTop2 = findsidestr( borT2, TRUE ) ;  /* bottom top */
559 
560 if( fixedType == GROUPFLAG || fixedType == FIXEDGROUPFLAG ){
561     fixptr = ptrS->group->fixed ;
562     if( fixedType == FIXEDGROUPFLAG ){
563 	/* note that this cell has been fixed */
564        ptrS->fixed = (FIXEDBOXPTR) TRUE ;
565     }
566 } else {
567     fixptr =ptrS->fixed = (FIXEDBOXPTR)
568 	Ysafe_malloc( sizeof(FIXEDBOX) ) ;
569 }
570 fixptr->fixedType = fixedType ;
571 fixptr->xcenter = xloc ;
572 fixptr->ycenter = yloc ;
573 if( leftOrRight == TRUE ){
574     fixptr->leftNotRight = TRUE ;
575 } else if( leftOrRight == FALSE ){
576     fixptr->leftNotRight = FALSE ;
577 } else {
578     M(ERRMSG,"fixCell", "Problem passing arguments to function\n" ) ;
579     setErrorFlag() ;
580 }
581 
582 if( bottomOrTop == TRUE ){
583     fixptr->bottomNotTop = TRUE ;
584 } else if( bottomOrTop == FALSE ){
585     fixptr->bottomNotTop = FALSE ;
586 } else {
587     M(ERRMSG,"fixCell", "Problem passing arguments to function\n" ) ;
588     setErrorFlag() ;
589 }
590 if( fixedType != POINTFLAG ){
591     fixptr->xloc1 = xloc ;
592     fixptr->yloc1 = yloc ;
593     fixptr->xloc2 = xloc2 ;
594     fixptr->yloc2 = yloc2 ;
595     if( leftOrRight2 == TRUE ){
596 	fixptr->leftNotRight2 = TRUE ;
597     } else if( leftOrRight2 == FALSE ){
598 	fixptr->leftNotRight2 = FALSE ;
599     } else {
600 	M(ERRMSG,"fixCell","Problem passing arguments to function\n");
601 	setErrorFlag() ;
602     }
603 
604     if( bottomOrTop2 == TRUE ){
605 	fixptr->bottomNotTop2 = TRUE ;
606     } else if( bottomOrTop2 == FALSE ){
607 	fixptr->bottomNotTop2 = FALSE ;
608     } else {
609 	M(ERRMSG,"fixCell","Problem passing arguments to function\n");
610 	setErrorFlag() ;
611     }
612 }
613 
614 } /* end fixCell */
615 
processCorners(INT numcorners)616 void processCorners( INT numcorners )
617 {
618 char *buster_msg ;           /* message string to used by buster */
619 INT xx1, yy1, xx2, yy2 ;     /* temp points */
620 INT k ;                      /* point counter */
621 INT xsum, ysum ;             /* used to truncate cell correctly */
622 TILEBOXPTR tile ;
623 YBUSTBOXPTR busterptr ;      /* return record for busting routine */
624 VERTBOXPTR vert ;            /* ptr to record of vertices of cell */
625 BOUNBOXPTR bounptr,          /* ptr to bounBox[0] */
626     bounptr_orig ;           /* ptr to bounBox[8] - original bbox */
627 
628 
629 /* +++++++++++++++++++ perform error checking +++++++++++++++++++ */
630 ERRORABORT() ;
631 if( cornerCountS != numcorners ){
632     sprintf( YmsgG, "Incorrect number of corners for cell:%s\n",
633 	curCellNameS ) ;
634     M(ERRMSG,"processCorners", YmsgG ) ;
635     setErrorFlag() ;
636 }
637 if( scale_dataG ){
638     if( maxxS - minxS <= 1 || maxyS - minyS <= 1 ){
639 	sprintf( YmsgG,
640 	"Cell:%s smaller than given scale data - resized to portsize.\n",
641 	curCellNameS ) ;
642 	M( WARNMSG, "processCorners", YmsgG ) ;
643 	/* make into a port instead of a possible 0 width object */
644 	numcorners = cornerCountS = 4 ;
645 	cornerArrayS[1].x = -1 ; cornerArrayS[1].y = -1 ;
646 	cornerArrayS[2].x = -1 ; cornerArrayS[2].y =  1 ;
647 	cornerArrayS[3].x =  1 ; cornerArrayS[3].y =  1 ;
648 	cornerArrayS[4].x =  1 ; cornerArrayS[4].y = -1 ;
649 	minxS = -1 ; maxxS = 1;
650 	minyS = -1 ; maxyS = 1;
651 	/* set portFlag to true so we can move pins to boundary */
652 	portFlagS = TRUE ;
653     }
654 }
655 xsum = minxS + maxxS ;
656 ysum = minyS + maxyS ;
657 xcenterS = xsum / 2 ;
658 ycenterS = ysum / 2 ;
659 if( xsum < 0 && xsum % 2 ){
660     /* cell is asymmetrical and negative */
661     xcenterS-- ;
662 }
663 if( ysum < 0 && ysum % 2 ){
664     /* cell is asymmetrical and negative */
665     ycenterS-- ;
666 }
667 
668 /* save the number of sides */
669 ptrS->numsides = numcorners ;
670 
671 Ybuster_init() ;
672 sprintf( YmsgG, " (cell:%s) ", curCellNameS ) ;
673 buster_msg = Ystrclone( YmsgG ) ;
674 
675 for( k = 1 ; k <= numcorners ; k++ ) {
676     xx1 = cornerArrayS[k].x ;
677     yy1 = cornerArrayS[k].y ;
678     Ybuster_addpt( xx1, yy1 ) ;
679     if( k == numcorners ) {
680 	xx2 = cornerArrayS[1].x ;
681 	yy2 = cornerArrayS[1].y ;
682     } else {
683 	xx2 = cornerArrayS[ k + 1 ].x ;
684 	yy2 = cornerArrayS[ k + 1 ].y ;
685     }
686 }
687 if(!(Ybuster_verify( buster_msg ))){
688     setErrorFlag() ;
689     return ;
690 }
691 Ysafe_free( buster_msg ) ;
692 
693 /* +++++++++++++++++++ end perform error checking +++++++++++++++++++ */
694 /* This data structure allow quick change between x and x_new */
695 /* since placepin always uses the x fields and not x_new */
696 vert = ptrS->vertices = (VERTBOXPTR) Ysafe_malloc( sizeof(VERTBOX) ) ;
697 /* the members of the structure */
698 vert->x = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ;
699 vert->x_orig = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ;
700 vert->x_new = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ;
701 vert->y = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ;
702 vert->y_orig = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ;
703 vert->y_new = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ;
704 vert->numpins = (FLOAT *) Yvector_alloc( 1,numcorners,sizeof(FLOAT) ) ;
705 for( k = 1 ; k <= numcorners ; k++ ) {
706     vert->x[k] = vert->x_orig[k] = cornerArrayS[k].x - xcenterS ;
707     vert->y[k] = vert->y_orig[k] = cornerArrayS[k].y - ycenterS ;
708 }
709 if( curCellTypeS == SOFTCELLTYPE || curCellTypeS == CUSTOMCELLTYPE ||
710     curCellTypeS == STDCELLTYPE ){
711     /* calculate total cell perimeter before bust operation */
712     /* calculate over all instances */
713     perimG += perimeter( cornerArrayS, numcorners ) ;
714     /* load pSideArray for weighing cells in dynamic wiring estimator */
715     for( k = 1 ; k <= numcorners ; k++ ) {
716 	if( k < numcorners ) {
717 	    if( k % 2 == 1 ) {
718 		pSideArrayS[k].length =
719 		    ABS(cornerArrayS[k + 1].y - cornerArrayS[k].y) ;
720 		pSideArrayS[k].vertical = 1 ;
721 		pSideArrayS[k].pincount = 0 ;
722 		pSideArrayS[k].position = cornerArrayS[k].x ;
723 	    } else {
724 		pSideArrayS[k].length =
725 		    ABS(cornerArrayS[k + 1].x - cornerArrayS[k].x) ;
726 		pSideArrayS[k].vertical = 0 ;
727 		pSideArrayS[k].pincount = 0 ;
728 		pSideArrayS[k].position = cornerArrayS[k].y ;
729 	    }
730 	} else {
731 	    pSideArrayS[k].length =
732 		ABS(cornerArrayS[1].x - cornerArrayS[k].x) ;
733 	    pSideArrayS[k].vertical = 0 ;
734 	    pSideArrayS[k].pincount = 0 ;
735 	    pSideArrayS[k].position = cornerArrayS[k].y ;
736 	}
737     } /* end for loop */
738 }
739 /* -----------------now build tiles for cell---------------------- */
740 
741 /* create bounding box of cell bounding box has 8 view for all cells*/
742 /* plus 9 field for original view of the bounding box */
743 ptrS->bounBox = (BOUNBOXPTR *)
744     Ysafe_malloc( 9 * sizeof( BOUNBOXPTR ) ) ;
745 for( k=0;k<=8;k++){
746    ptrS->bounBox[k] = (BOUNBOXPTR)
747 	Ysafe_malloc(sizeof( BOUNBOX ) ) ;
748 }
749 ptrS->boun_valid = FALSE ;
750 /* now save the original bounding box for uaspect in 8 */
751 bounptr = ptrS->bounBox[0] ;
752 bounptr_orig = ptrS->bounBox[8] ;
753 bounptr_orig->l = bounptr->l = minxS - xcenterS ;
754 bounptr_orig->r = bounptr->r = maxxS - xcenterS ;
755 bounptr_orig->b = bounptr->b = minyS - ycenterS ;
756 bounptr_orig->t = bounptr->t = maxyS - ycenterS ;
757 ptrS->xcenter = xcenterS ;
758 ptrS->ycenter = ycenterS ;
759 
760 tile = NIL(TILEBOXPTR) ;
761 while( busterptr = Ybuster() ){
762     /* l = busterptr[1].x */
763     /* r = busterptr[4].x */
764     /* b = busterptr[1].y */
765     /* t = busterptr[2].y */
766     if( tile ){
767 	tile->next = (TILEBOXPTR) Ysafe_malloc( sizeof( TILEBOX ));
768 	tile = tile->next ;
769     } else {
770 	tile = ptrS->tiles =
771 	    (TILEBOXPTR) Ysafe_malloc( sizeof( TILEBOX ));
772     }
773     tile->next = NULL ;
774     ptrS->numtiles++ ;
775     tile->left   = tile->orig_left   = busterptr[1].x - xcenterS ;
776     tile->right  = tile->orig_right  = busterptr[4].x - xcenterS ;
777     tile->bottom = tile->orig_bottom = busterptr[1].y - ycenterS ;
778     tile->top    = tile->orig_top    = busterptr[2].y - ycenterS ;
779     tile->lweight = 0.0 ;
780     tile->rweight = 0.0 ;
781     tile->bweight = 0.0 ;
782     tile->tweight = 0.0 ;
783 }
784 
785 /* add aspect ratio to design */
786 ptrS->orig_aspect = ptrS->aspect =
787     (DOUBLE)(maxyS - minyS) / (DOUBLE)(maxxS - minxS);
788 
789 /* -----------------end build tiles for cell---------------------- */
790 } /* end processCorners */
791 /* ***************************************************************** */
792 
addCorner(INT xpos,INT ypos)793 void addCorner( INT xpos, INT ypos )
794 {
795 if( ++cornerCountS >= tileptAllocS ){
796     tileptAllocS = cornerCountS + 1 ;
797     cornerArrayS = ( YBUSTBOXPTR )
798 	Ysafe_realloc( cornerArrayS, tileptAllocS * sizeof( YBUSTBOX ) );
799     pSideArrayS  = (PSIDEBOX *)
800 	Ysafe_realloc( pSideArrayS, tileptAllocS * sizeof( PSIDEBOX ) ) ;
801 }
802 if( scale_dataG ){
803     if( portFlagS ){
804 	/* port pins need to be on boundary for global router */
805 	xpos = 0 ;
806 	ypos = 1 ;
807     } else {
808 	xpos = (INT) ( (DOUBLE) xpos / scaleS ) ;
809 	ypos = (INT) ( (DOUBLE) ypos / scaleS ) ;
810     }
811 }
812 cornerArrayS[cornerCountS].x = xpos ;
813 cornerArrayS[cornerCountS].y = ypos ;
814 minxS = MIN( minxS, xpos ) ;
815 maxxS = MAX( maxxS, xpos ) ;
816 minyS = MIN( minyS, ypos ) ;
817 maxyS = MAX( maxyS, ypos ) ;
818 } /* end addCorner */
819 /* ***************************************************************** */
820 
initializeCorner(INT cell)821 void initializeCorner( INT cell )
822 {
823 ptrS = cellarrayG[cell] ;
824 curCellTypeS = ptrS->celltype ;
825 cornerCountS = 0 ;
826 } /* end initializeCorner */
827 /* ***************************************************************** */
828 
addClass(INT class)829 void addClass( INT class )
830 {
831 ERRORABORT() ;
832 
833 if( ptrS->class >= 0 ){
834     /* this test is necessary since fix neighborhood may set it negative */
835     /* and we will not want to touch the value of it */
836     ptrS->class = class ;
837 }
838 } /* end addClass */
839 /* ***************************************************************** */
840 
841 /* first in the list is the initial orientation */
initOrient(orient)842 void initOrient( orient )
843 INT orient ;
844 {
845 ERRORABORT() ;
846 
847 ptrS->orient = - orient ;
848 addOrient( orient ) ;
849 } /* end initOrient */
850 /* ***************************************************************** */
851 
852 /* addOrient sets orientation valid for this cell */
addOrient(INT orient)853 void addOrient( INT orient )
854 {
855 ERRORABORT() ;
856 
857 ptrS->orientList[orient] = TRUE ; /* allow this orientation */
858 ptrS->orientList[HOWMANYORIENT]++ ;
859 } /* end addOrient */
860 /* ***************************************************************** */
861 
862 /* if this routine is called it means we are reading the input of
863    a previous TimberWolf run.
864 */
set_cur_orient(INT orient)865 int set_cur_orient( INT orient )
866 {
867 ERRORABORTINT() ;
868 
869 ptrS->orient = orient ;
870 } /* end set_cur_orient */
871 /* ***************************************************************** */
872 
873 /* load aspect ratios */
addAspectBounds(lowerBound,upperBound)874 void addAspectBounds( lowerBound, upperBound )
875 DOUBLE lowerBound, upperBound ;
876 {
877 ERRORABORT() ;
878 
879 ptrS->aspLB = lowerBound ;
880 ptrS->aspUB = upperBound ;
881 
882 } /* end addAspectBounds */
883 /* ***************************************************************** */
884 
addPinAndNet(pinName,signal)885 PINBOXPTR addPinAndNet( pinName, signal )
886 char *pinName, *signal ;
887 {
888     static PINBOXPTR botpinS ; /* keep track of end of list */
889     INT *data, netx ;
890     BOOL notInTable ;
891     PINBOXPTR pinptr ;
892     NETBOXPTR netptr ;
893 
894     notInTable = TRUE ;
895     totPinS++ ; /* count the pins over all instances */
896     if( data = (INT *) Yhash_search( netTableS, signal, NULL, FIND ) ){
897 	netx = *data ;
898 	notInTable = FALSE ;
899     } else {
900 	/* else a new net load data holder */
901 	data = (INT *) Ysafe_malloc( sizeof(INT) ) ;
902 	*data = netx = ++numnetsG ;
903 	if( Yhash_search( netTableS, signal, (char*) data, ENTER )){
904 	    sprintf( YmsgG, "Trouble adding signal:%s to hash table\n",
905 		signal ) ;
906 	    M(ERRMSG,"addPinAndNet",YmsgG ) ;
907 	    errorFlagS = TRUE ;
908 	}
909     }
910     if( cellinstanceS ){
911 	if( notInTable ){
912 	    sprintf(YmsgG,"No match for net:%s in primary instance:%s\n",
913 		pinName, *ptrS->cname ) ;
914 	    M( ERRMSG, "addPinAndNet", YmsgG ) ;
915 	    errorFlagS = TRUE ;
916 	}
917 	/* at this point we are done */
918 	return( NULL ) ;
919     }
920     /* increment number of pins */
921     numpinsG++ ;
922     /* check memory of netarray */
923     if( numnetsG >= netAllocS ){
924 	netAllocS += EXPECTEDNUMNETS ;
925 	netarrayG = (NETBOXPTR *)
926 	    Ysafe_realloc( netarrayG, netAllocS * sizeof(NETBOXPTR) ) ;
927     }
928 
929     /* see if this is the first time for this signal */
930     if( notInTable ){
931 	netptr = netarrayG[netx] =
932 	    (NETBOXPTR) Ysafe_malloc( sizeof(NETBOX) ) ;
933 	netptr->nname = signal ; /* allocated by yylex */
934 	netptr->pins = NULL ; /* initialize list */
935 	netptr->paths = NULL ; /* initialize list */
936 	netptr->skip = 0 ; /* initialize list */
937 	netptr->driveFactor = (FLOAT) 0.0 ; /* initialize timing */
938 	netptr->max_driver = (FLOAT) 1.0 ; /* initialize timing */
939 	netptr->min_driver = (FLOAT) 1.0 ; /* initialize timing */
940 	netptr->analog_info = NIL(ANETPTR) ;
941     } else {
942 	Ysafe_free( signal ) ; /* no need to keep this copy */
943 	netptr = netarrayG[netx] ;
944     }
945     /* create list of pins on the net */
946     pinptr = (PINBOXPTR) Ysafe_malloc( sizeof(PINBOX) );
947     pinptr->next = netptr->pins ;
948     netptr->pins = pinptr ;
949 
950     /* create a list of pins for this cell in order as given */
951     if( ptrS->pinptr ){ /* list has already been started */
952 	botpinS->nextpin = pinptr ;
953     } else {  /* start new list */
954 	ptrS->pinptr = pinptr ;
955     }
956     pinptr->nextpin = NULL ;
957     botpinS = pinptr ;
958 
959     /* now initialize data */
960     pinptr->pinname    = pinName ; /* allocated by yylex */
961     pinptr->pin        = numpinsG ;
962     pinptr->net        = netx ;
963     pinptr->cell       = totalcellsG ;
964     pinptr->xpos       = 0    ;
965     pinptr->ypos       = 0    ;
966     pinptr->instance   = cellinstanceS ;
967     /* allocate only size for one instance by default */
968     pinptr->txpos      = 0 ;
969     pinptr->typos      = 0 ;
970     pinptr->txpos_orig = (INT *) Ysafe_malloc( sizeof(INT) ) ;
971     pinptr->typos_orig = (INT *) Ysafe_malloc( sizeof(INT) ) ;
972     pinptr->newx     = 0    ;
973     pinptr->newy     = 0    ;
974     pinptr->flag     = 0    ;
975     pinptr->skip     = 0    ;
976     pinptr->eqptr  = NULL ;
977     pinptr->analog  = NIL(ANALOGPTR) ;
978 
979     return( pinptr ) ;
980 
981 } /* add pin and net */
982 /* ***************************************************************** */
983 
addPin(pinName,signal,layer,pinType)984 void addPin( pinName, signal, layer, pinType )
985 char *pinName ;
986 char *signal ;
987 INT layer ;
988 INT pinType ;
989 {
990     INT side ;
991     INT howmany ;            /* number of children - equivs */
992     SOFTBOXPTR sptr ;        /* current soft information */
993 
994 
995     curPinNameS = pinName ;
996     analogS = NIL(ANALOGPTR) ;
997     ERRORABORT() ;
998 
999     if( pinType == SOFTEQUIVTYPE ){
1000         /* get signal name from soft pin */
1001 	signal = Ystrclone( netarrayG[softpinS->net]->nname ) ;
1002     }
1003 
1004     pinS = addPinAndNet( pinName, signal ) ;
1005 
1006     equivpinS = 1 ;
1007 
1008     /* Note: initial pin positions will be last instance */
1009     if( pinS ){
1010 	ptrS->numpins++ ;
1011 	pinS->type = pinType ;
1012 	pinS->layer = layer ;
1013     } else if( cellinstanceS ){
1014 	if(!(pinS = findTerminal( pinName, totalcellsG))){
1015 	    sprintf(YmsgG,"No match for pin:%s in primary instance:%s\n",
1016 		pinName, cellarrayG[totalcellsG]->cname ) ;
1017 	    M( ERRMSG, "addHardPin", YmsgG ) ;
1018 	    errorFlagS = TRUE ;
1019 	    return ;
1020 	}
1021 	/* reallocate space if necessary */
1022 	pinS->txpos_orig = (INT *)
1023 	    Ysafe_realloc( pinS->txpos_orig,(cellinstanceS+1)*sizeof(INT));
1024 	pinS->typos_orig = (INT *)
1025 	    Ysafe_realloc( pinS->typos_orig,(cellinstanceS+1)*sizeof(INT));
1026 	pinS->txpos = pinS->txpos_orig[cellinstanceS] = 0 ;
1027 	pinS->typos = pinS->typos_orig[cellinstanceS] = 0 ;
1028     }
1029 
1030     /* now handle soft pin information */
1031     if( ptrS->softflag ){
1032 	/* allocate space for array of instances */
1033 	if( cellinstanceS == 0 ){
1034 	    pinS->soft_inst = (SOFTBOXPTR *)
1035 		Ysafe_malloc( sizeof(SOFTBOXPTR) );
1036 	    pinS->layer = layer ;
1037 	} else {
1038 	    pinS->soft_inst = (SOFTBOXPTR *) Ysafe_realloc(
1039 		pinS->soft_inst,instAllocS * sizeof(SOFTBOXPTR) );
1040 	}
1041 	/*  now allocate space for this instance */
1042 	spinptrS = pinS->soft_inst[cellinstanceS] = pinS->softinfo =
1043 	    (SOFTBOXPTR) Ysafe_malloc(sizeof(SOFTBOX)) ;
1044 	spinptrS->children = NULL ;
1045 	spinptrS->hierarchy = NONE ;
1046 	spinptrS->parent = NULL ;
1047 	/* build the restrict field and initialize HOWMANY [0] to 0 */
1048 	spinptrS->restrict1 = (INT *) Ysafe_calloc( 1, sizeof(INT) ) ;
1049 	spinptrS->permute = FALSE ;
1050 	spinptrS->fixed = FALSE ;
1051 	spinptrS->ordered = FALSE ;
1052 	spinptrS->lowerbound = 0.0 ;
1053 	spinptrS->upperbound = 1.0 ;
1054     }
1055 
1056     if( pinType == SOFTPINTYPE ){
1057 	/* save the main softpin for future equiv use */
1058 	softpinS = pinS ;
1059     } else if( pinType == SOFTEQUIVTYPE ){
1060 	/* add to this pin's children */
1061 	sptr = softpinS->softinfo ;
1062 	if( sptr->children ){
1063 	    howmany = (INT) sptr->children[HOWMANY] ;
1064 	    sptr->children = (PINBOXPTR *)
1065 		Ysafe_realloc( sptr->children,
1066 		    (++howmany+1) * sizeof(PINBOXPTR) ) ;
1067 	} else {
1068 	    howmany = 1 ;
1069 	    sptr->children = (PINBOXPTR *)
1070 		Ysafe_malloc( (howmany+1) * sizeof(PINBOXPTR) ) ;
1071 	}
1072 	sptr->children[HOWMANY] = (PINBOXPTR) howmany ;
1073 	sptr->children[howmany] = pinS ;
1074 	spinptrS->parent = softpinS ;
1075     } else if( !(ptrS->softflag) ){
1076 	pinS->softinfo = NULL ;
1077     }
1078 
1079 } /* end addPin */
1080 /* ***************************************************************** */
1081 
set_pin_pos(xpos,ypos)1082 void set_pin_pos( xpos, ypos )
1083 INT xpos, ypos ;
1084 {
1085     INT side ;
1086     INT howmany ;            /* number of children - equivs */
1087 
1088     ERRORABORT() ;
1089 
1090     if( scale_dataG ){
1091 	if( portFlagS ){
1092 	    xpos = 0 ;
1093 	    ypos = 1 ;
1094 	} else {
1095 	    xpos = (INT) ( (DOUBLE) xpos / scaleS ) ;
1096 	    ypos = (INT) ( (DOUBLE) ypos / scaleS ) ;
1097 	}
1098     }
1099 
1100     check_pos( curPinNameS, xpos, ypos ) ;
1101     side = findside( pSideArrayS, ptrS , xpos , ypos ) ;
1102     loadside( pSideArrayS, side , 1.0 ) ;
1103 
1104     totxS = xpos ;
1105     totyS = ypos ;
1106 
1107     /* set global coordinates */
1108     pinS->xpos = xpos ;
1109     pinS->ypos = ypos ;
1110 
1111     xpos -= xcenterS ;
1112     ypos -= ycenterS ;
1113 
1114     /* Note: initial pin positions will be last instance */
1115     pinS->txpos = pinS->txpos_orig[cellinstanceS] = xpos ;
1116     pinS->typos = pinS->typos_orig[cellinstanceS] = ypos ;
1117 } /* end set_pin_pos */
1118 /* ***************************************************************** */
1119 
check_pos(pinname,xpos,ypos)1120 static void check_pos( pinname, xpos, ypos )
1121 char *pinname ;
1122 INT xpos, ypos ;
1123 {
1124     if( xpos < minxS || xpos > maxxS || ypos < minyS || ypos > maxyS ){
1125 	sprintf( YmsgG, "Pin:%s cell:%s @(%d,%d) is outside cell boundary\n",
1126 	    pinname, curCellNameS, xpos, ypos ) ;
1127 	M( ERRMSG, "check_pos", YmsgG ) ;
1128 	setErrorFlag() ;
1129     }
1130 } /* end check_pos */
1131 
1132 /* add an equivalent pin-updates the pin position to effective position */
addEquivPin(pinName,layer,xpos,ypos,pinType)1133 void addEquivPin( pinName, layer, xpos, ypos, pinType )
1134 char *pinName ;
1135 INT layer ;
1136 INT xpos, ypos ;
1137 INT pinType ;
1138 {
1139     INT side ;
1140     EQUIVPTR temp, eqptr ;
1141 
1142     curPinNameS = pinName ;
1143     ERRORABORT() ;
1144     ASSERTNRETURN( pinS, "addEquivPin", "pinS is NULL" ) ;
1145 
1146     if( pinType != ADDEQUIVTYPE ){
1147 	if( scale_dataG ){
1148 	    if( portFlagS ){
1149 		xpos = 0 ;
1150 		ypos = 1 ;
1151 	    } else {
1152 		xpos = (INT) ( (DOUBLE) xpos / scaleS ) ;
1153 		ypos = (INT) ( (DOUBLE) ypos / scaleS ) ;
1154 	    }
1155 	}
1156 
1157 	if( curCellTypeS == SOFTCELLTYPE ||
1158 	    curCellTypeS == CUSTOMCELLTYPE ||
1159 	    curCellTypeS == STDCELLTYPE ){
1160 	    check_pos( pinName, xpos, ypos ) ;
1161 	    side = findside( pSideArrayS, ptrS , xpos , ypos ) ;
1162 	    loadside( pSideArrayS, side , 1.0 ) ;
1163 	}
1164 	equivpinS++ ;
1165 	totPinS++ ;
1166 	totxS += xpos ;
1167 	totyS += ypos ;
1168 
1169 	/* average pin positions - note we leave _orig fields untouched */
1170 	pinS->txpos = (totxS / equivpinS ) - xcenterS;
1171 	pinS->typos = (totyS / equivpinS ) - ycenterS;
1172     } else {
1173 	/* get pinname from main soft pin */
1174 	pinName = softpinS->pinname ;
1175     }
1176 
1177     /* now save locations of equivalent pins for later output */
1178     if( temp = pinS->eqptr ){
1179 	eqptr = pinS->eqptr = (EQUIVPTR) Ysafe_malloc(sizeof(EQUIVBOX)) ;
1180 	eqptr->next = temp ;
1181     } else {
1182 	eqptr = pinS->eqptr = (EQUIVPTR) Ysafe_malloc(sizeof(EQUIVBOX)) ;
1183 	eqptr->next = NULL ;
1184     }
1185     if( cellinstanceS ){ /* more than one instance */
1186 	eqptr->txpos = (INT *)
1187 	    Ysafe_realloc( eqptr->txpos,(cellinstanceS+1) * sizeof(INT) ) ;
1188 	eqptr->typos = (INT *)
1189 	    Ysafe_realloc( eqptr->typos,(cellinstanceS+1) * sizeof(INT) ) ;
1190     } else {
1191 	/* by default only expect one instance */
1192 	eqptr->txpos      = (INT *) Ysafe_malloc( sizeof(INT) ) ;
1193 	eqptr->typos      = (INT *) Ysafe_malloc( sizeof(INT) ) ;
1194     }
1195     /* now load the data */
1196     eqptr->txpos[cellinstanceS] = xpos - xcenterS;
1197     eqptr->typos[cellinstanceS] = ypos - ycenterS;
1198     eqptr->pinname = pinName ;
1199     /* if the user didn't give us any layer set to 2 for now */
1200     if( layer == 0 ){
1201 	layer = -2 ;
1202     }
1203     eqptr->layer = layer ;
1204     if( pinType == ADDEQUIVTYPE ){
1205 	/* build the restrict field and initialize HOWMANY [0] to 0 */
1206 	eqptr->restrict1 = (INT *) Ysafe_calloc( 1, sizeof(INT) ) ;
1207     } else {
1208 	eqptr->restrict1 = NULL ;
1209     }
1210 
1211 } /* end addEquivPin */
1212 /* ***************************************************************** */
1213 
set_restrict_type(object)1214 void set_restrict_type( object )
1215 INT object ;
1216 {
1217     cur_restrict_objS = object ;
1218 }
1219 /* ***************************************************************** */
1220 
addSideRestriction(side)1221 void addSideRestriction( side )
1222 INT side ;
1223 {
1224 INT howmany ;
1225 SOFTBOXPTR spin ;
1226 EQUIVPTR eqptr ;
1227 
1228 ERRORABORT() ;
1229 if( side < 0 || side > cornerCountS ) {
1230     M(ERRMSG,"addSideRestriction","value of side out of range");
1231     sprintf(YmsgG,"\n\tside:%d  range:1 to %d ", side,
1232 	cornerCountS ) ;
1233     M(MSG,NULL,YmsgG);
1234     sprintf(YmsgG, "current cell is:%d\n", totalcellsG ) ;
1235     M(MSG,NULL,YmsgG);
1236     setErrorFlag() ;
1237 }
1238 
1239 /* this variable set by set_restrict type */
1240 switch( cur_restrict_objS ){
1241     case PINGROUPTYPE:
1242 	spin = pingroupS->softinfo ;
1243 	howmany = ++(spin->restrict1[HOWMANY]) ;
1244 	spin->restrict1 = (INT *) Ysafe_realloc( spin->restrict1,
1245 	    (howmany+1)*sizeof(INT) ) ;
1246 	spin->restrict1[howmany] = side ;
1247 	break ;
1248     case SOFTPINTYPE:
1249     case SOFTEQUIVTYPE:
1250 	spin = pinS->softinfo ;
1251 	howmany = ++(spin->restrict1[HOWMANY]) ;
1252 	spin->restrict1 = (INT *) Ysafe_realloc( spin->restrict1,
1253 	    (howmany+1)*sizeof(INT) ) ;
1254 	spin->restrict1[howmany] = side ;
1255 	break ;
1256     case ADDEQUIVTYPE:
1257 	eqptr = softpinS->eqptr ;
1258 	howmany = ++(eqptr->restrict1[HOWMANY]) ;
1259 	eqptr->restrict1 = (INT *) Ysafe_realloc( eqptr->restrict1,
1260 	    (howmany+1)*sizeof(INT) ) ;
1261 	eqptr->restrict1[howmany] = side ;
1262 	break ;
1263 } /* end switch on current object */
1264 
1265 } /* end addSideRestriction *
1266 /* ***************************************************************** */
1267 
1268 
add_pinspace(lower,upper)1269 void add_pinspace( lower, upper )
1270 DOUBLE lower ;
1271 DOUBLE upper ;
1272 {
1273     char *name ;         /* name of current object */
1274     SOFTBOXPTR spin ;    /* soft pin information of current pin or pg */
1275 
1276     ERRORABORT() ;
1277 
1278     switch( cur_restrict_objS ){
1279 	case PINGROUPTYPE:
1280 	    spin = pingroupS->softinfo ;
1281 	    name = pingroupS->pinname ;
1282 	    break ;
1283 	case SOFTPINTYPE:
1284 	case SOFTEQUIVTYPE:
1285 	    spin = pinS->softinfo ;
1286 	    name = pinS->pinname ;
1287 	    break ;
1288 	case ADDEQUIVTYPE:
1289 	    return ;
1290     } /* end switch on current object */
1291 
1292     spin->fixed = TRUE ;
1293     if( lower > 1.0 || upper > 1.0 ){
1294 	sprintf(YmsgG,
1295 	    "side space must be less or equal to 1.0 for pin: %s\n", name ) ;
1296 	M(ERRMSG,"add_pinspace",YmsgG ) ;
1297 	setErrorFlag() ;
1298     }
1299     if( lower < 0.0 || upper < 0.0 ){
1300 	sprintf(YmsgG,
1301 	    "side space must be greater or equal to 0.0 for pin: %s\n",name ) ;
1302 	M(ERRMSG,"add_pinspace",YmsgG ) ;
1303 	setErrorFlag() ;
1304     }
1305     if( lower > upper ){
1306 	sprintf(YmsgG,
1307 	    "side space upper bound must be greater or equal to lower bound for pin: %s\n",
1308 	    name ) ;
1309 	M(ERRMSG,"add_pinspace",YmsgG ) ;
1310 	setErrorFlag() ;
1311     }
1312     spin->lowerbound = lower ;
1313     spin->upperbound = upper ;
1314 } /* end add_pinspace */
1315 /* ***************************************************************** */
1316 
add_soft_array()1317 void add_soft_array()
1318 {
1319     INT i ;
1320     PINBOXPTR *sarray ;
1321     PINBOXPTR pin ;
1322 
1323     if( cellinstanceS != 0 ){
1324 	return ;
1325     }
1326     sarray = ptrS->softpins = (PINBOXPTR *)
1327 	Ysafe_malloc( (ptrS->numpins+1) * sizeof(PINBOXPTR) ) ;
1328     i = 0 ;
1329     for( pin = ptrS->pinptr; pin ; pin = pin->nextpin ){
1330 	sarray[++i] = pin ;
1331     }
1332     sarray[HOWMANY] = (PINBOXPTR) i ;
1333 }
1334 /* end add_soft_array */
1335 
start_pin_group(pingroup,permute)1336 void start_pin_group( pingroup, permute )
1337 char *pingroup ;
1338 BOOL permute ;
1339 {
1340 
1341 INT i ;
1342 INT curpingroup ;
1343 INT howmany ;
1344 PINBOXPTR *sarray ;
1345 SOFTBOXPTR spin ;
1346 
1347 ERRORABORT() ;
1348 
1349 numchildrenS = 0 ;
1350 childAllocS = 1 ;
1351 
1352 /* allocate space for array of instances */
1353 if( cellinstanceS == 0 ){
1354     /* pins in array go 1 ... numpins, pingroup1, pingroup2 ... */
1355     curpingroup = ptrS->numpins + ++numpingroupS ;
1356     sarray = ptrS->softpins = (PINBOXPTR *)
1357 	    Ysafe_realloc( ptrS->softpins,
1358 	    (curpingroup+1) * sizeof(PINBOXPTR) ) ;
1359 
1360     sarray[HOWMANY] = (PINBOXPTR) curpingroup ;
1361 
1362     /* allocate space for pingroup */
1363     pingroupS = sarray[curpingroup] = (PINBOXPTR)
1364 	Ysafe_calloc( 1, sizeof(PINBOX) );
1365 
1366     /* now initialize data */
1367     pingroupS->pinname    = pingroup ; /* allocated by yylex */
1368     pingroupS->txpos_orig = (INT *) Ysafe_malloc( sizeof(INT) ) ;
1369     pingroupS->typos_orig = (INT *) Ysafe_malloc( sizeof(INT) ) ;
1370     pingroupS->type = PINGROUPTYPE ;
1371 
1372     pingroupS->soft_inst = (SOFTBOXPTR *) Ysafe_malloc( sizeof(SOFTBOXPTR) );
1373 } else {
1374     /* first find pingroup in softpin array */
1375     sarray = ptrS->softpins ;
1376     howmany = (INT) sarray[HOWMANY] ;
1377     pingroupS = NIL(PINBOXPTR) ;
1378     for( i = 1; i <= howmany; i++ ){
1379 	if( strcmp( pingroup, sarray[i]->pinname ) == STRINGEQ ){
1380 	    pingroupS = sarray[i] ;
1381 	    break ;
1382 	}
1383     }
1384     if( pingroupS ){
1385 	pingroupS->soft_inst = (SOFTBOXPTR *) Ysafe_realloc(
1386 	    pingroupS->soft_inst,instAllocS * sizeof(SOFTBOXPTR) );
1387     } else {
1388 	sprintf(YmsgG,"No match for pingroup:%s in primary instance:%s\n",
1389 	    pingroup, cellarrayG[totalcellsG]->cname ) ;
1390 	M( ERRMSG, "start_pin_group", YmsgG ) ;
1391 	errorFlagS = TRUE ;
1392 	return ;
1393     }
1394 }
1395 /*  now allocate space for this instance */
1396 pingroupS->soft_inst[cellinstanceS] = pingroupS->softinfo =
1397     (SOFTBOXPTR) Ysafe_calloc( 1, sizeof(SOFTBOX)) ;
1398 
1399 spin = pingroupS->softinfo ;
1400 spin->permute = permute ;
1401 spin->fixed = FALSE ;
1402 spin->ordered = FALSE ;
1403 spin->hierarchy = ROOT ;
1404 spin->lowerbound = 0.0 ;
1405 spin->upperbound = 1.0 ;
1406 spin->children = (PINBOXPTR *) Ysafe_malloc( sizeof(PINBOXPTR) ) ;
1407 spin->restrict1 = (INT *) Ysafe_calloc( 1, sizeof(INT) ) ;
1408 spin->parent = NULL ;
1409 
1410 } /* end start_pin_group */
1411 /* ***************************************************************** */
1412 
1413 /* add this pad to the current pad group */
add2pingroup(pinName,ordered)1414 void add2pingroup( pinName, ordered )
1415 char *pinName ;
1416 BOOL ordered ;  /* ordered flag is true if padgroup is fixed */
1417 {
1418 
1419 INT i ;
1420 INT howmany ;
1421 PINBOXPTR pin ;
1422 PINBOXPTR cpin ;
1423 SOFTBOXPTR spin ;
1424 SOFTBOXPTR pingroup_spin ;
1425 INT curpingroup ;
1426 
1427 ERRORABORT() ;
1428 
1429 /* check pads for correctness */
1430 for( pin = ptrS->pinptr ; pin ; pin = pin->nextpin ){
1431     spin = pin->softinfo ;
1432     if( strcmp(pinName, pin->pinname) == STRINGEQ ){
1433 
1434 	if( spin->hierarchy == LEAF ){
1435 	    sprintf(YmsgG,
1436 		"pin %s was included in more than 1 pin group\n",
1437 		pin->pinname);
1438 	    M(ERRMSG,"add2pingroup",YmsgG ) ;
1439 	    setErrorFlag() ;
1440 	    return ;
1441 	}
1442 	/* check memory of pin array */
1443 	pingroup_spin = pingroupS->softinfo ;
1444 	if( ++numchildrenS >= childAllocS ){
1445 	    childAllocS += EXPECTEDPINGRP ;
1446 	    pingroup_spin->children = (PINBOXPTR *)
1447 		Ysafe_realloc( pingroup_spin->children,
1448 		childAllocS * sizeof(PINBOXPTR) ) ;
1449 	}
1450 	pingroup_spin->children[numchildrenS] = pin ;
1451 	pingroup_spin->children[HOWMANY] = (PINBOXPTR) numchildrenS ;
1452 	spin->parent = pingroupS ;
1453 	/* now update any equivalent subpins to leaves */
1454 	if( spin->hierarchy == NONE && spin->children ){
1455 	    howmany = (INT) spin->children[HOWMANY] ;
1456 	    for( i = 1; i <= howmany; i++ ){
1457 		cpin = spin->children[i] ;
1458 		if( cpin->type == SOFTEQUIVTYPE ){
1459 		    cpin->softinfo->hierarchy = LEAF ;
1460 		    cpin->softinfo->ordered = ordered ;
1461 		}
1462 	    }
1463 	}
1464 	spin->hierarchy = LEAF ;
1465 	spin->ordered = ordered ;
1466 	return;
1467     }
1468 }
1469 
1470 /* if no match above must be subroot */
1471 curpingroup = ptrS->numpins + numchildrenS ;
1472 for( i = ptrS->numpins ; i < curpingroup; i++ ){
1473     pin = ptrS->softpins[i] ;
1474     spin = pin->softinfo ;
1475     if (strcmp(pinName, pin->pinname) == STRINGEQ) {
1476 	if (spin->hierarchy == SUBROOT) {
1477 	    sprintf(YmsgG,
1478 		"pin group %s was included in more than 1 pin group\n",
1479 		pin->pinname);
1480 	    M(ERRMSG,"add2pingroup",YmsgG ) ;
1481 	    setErrorFlag() ;
1482 	    return ;
1483 	}
1484 	pingroup_spin = pingroupS->softinfo ;
1485 	if( ++numchildrenS >= childAllocS ){
1486 	    childAllocS += EXPECTEDPINGRP ;
1487 	    pingroup_spin->children = (PINBOXPTR *)
1488 		Ysafe_realloc( pingroup_spin->children,
1489 		childAllocS * sizeof(PINBOXPTR) ) ;
1490 	}
1491 	pingroup_spin->children[numchildrenS] = pin ;
1492 	pingroup_spin->children[HOWMANY] = (PINBOXPTR) numchildrenS ;
1493 	spin->parent = pingroupS ;
1494 	spin->hierarchy = SUBROOT ;
1495 	spin->ordered = ordered ;
1496 	return ;
1497     }
1498 }
1499 
1500 sprintf(YmsgG,"cannot find pin <%s> for pin_group <%s>\n",
1501     pinName,ptrS->softpins[curpingroup]->pinname );
1502 M(ERRMSG,"add2pingroup",YmsgG ) ;
1503 return ;
1504 
1505 } /* end add2pingroup */
1506 /* ***************************************************************** */
1507 
addSideSpace(lower,upper)1508 void addSideSpace( lower, upper )
1509 DOUBLE lower ;
1510 DOUBLE upper ;
1511 {
1512     ERRORABORT() ;
1513 
1514     pptrS->fixed = TRUE ;
1515     if( lower > 1.0 || upper > 1.0 ){
1516 	sprintf(YmsgG,
1517 	    "side space must be less or equal to 1.0 for pad: %s\n",ptrS->cname ) ;
1518 	M(ERRMSG,"addSideSpace",YmsgG ) ;
1519 	setErrorFlag() ;
1520     }
1521     if( lower < 0.0 || upper < 0.0 ){
1522 	sprintf(YmsgG,
1523 	    "side space must be greater or equal to 0.0 for pad: %s\n",ptrS->cname ) ;
1524 	M(ERRMSG,"addSideSpace",YmsgG ) ;
1525 	setErrorFlag() ;
1526     }
1527     if( lower > upper ){
1528 	sprintf(YmsgG,
1529 	    "side space upper bound must be greater or equal to lower bound for pad: %s\n",ptrS->cname ) ;
1530 	M(ERRMSG,"addSideSpace",YmsgG ) ;
1531 	setErrorFlag() ;
1532     }
1533     pptrS->lowerbound = lower ;
1534     pptrS->upperbound = upper ;
1535 } /* end addSideSpace */
1536 /* ***************************************************************** */
1537 
addPadSide(side)1538 void addPadSide( side  )
1539 char *side ;
1540 {
1541 
1542     INT numsides ;         /* length of side restriction string */
1543     INT i ;                /* counter */
1544 
1545     ERRORABORT() ;
1546 
1547     pptrS->valid_side[ALL] = FALSE ;
1548     numsides = strlen( side ) ;
1549     for( i = 0 ; i < numsides; i++ ){
1550 	switch( side[i] ){
1551 	    case 'B' :
1552 		pptrS->valid_side[B] = TRUE ;
1553 		break ;
1554 	    case 'L' :
1555 		pptrS->valid_side[L] = TRUE ;
1556 		break ;
1557 	    case 'R' :
1558 		pptrS->valid_side[R] = TRUE ;
1559 		break ;
1560 	    case 'T' :
1561 		pptrS->valid_side[T] = TRUE ;
1562 		break ;
1563 	    default:
1564 		sprintf( YmsgG,
1565 		    "side restriction not specified properly for pad:%s\n",
1566 		    ptrS->cname );
1567 	    M(ERRMSG,"addPadSide",YmsgG ) ;
1568 		setErrorFlag() ;
1569 	} /* end switch */
1570     }
1571 
1572 } /* end addPadSide */
1573 /* ***************************************************************** */
1574 
1575 /* set whether a pad group can be permuted */
setPermutation(int permuteFlag)1576 void setPermutation( int permuteFlag )
1577 {
1578 ERRORABORT() ;
1579 pptrS->permute = permuteFlag ;
1580 } /* end setPermutation */
1581 /* ***************************************************************** */
1582 
1583 /* add this pad to the current pad group */
add2padgroup(padName,ordered)1584 void add2padgroup( padName, ordered )
1585 char *padName ;
1586 BOOL ordered ;  /* ordered flag is true if pad is ordered in padgroup */
1587 {
1588 INT i, endofpads, endofgroups, endofcells ;
1589 
1590 ERRORABORT() ;
1591 endofpads = numcellsG + numpadsG ;
1592 endofcells = numcellsG + numsupercellsG ;
1593 /* check pads for correctness */
1594 for (i = numcellsG + 1; i <= endofpads; ++i) {
1595     if (strcmp(padName, cellarrayG[i]->cname) == STRINGEQ) {
1596 	if (cellarrayG[i]->padptr->hierarchy == LEAF) {
1597 	    sprintf(YmsgG,
1598 		"pad %s was included in more than 1 pad group\n",
1599 		cellarrayG[i]->cname);
1600 	    M(ERRMSG,"add2padgroup",YmsgG ) ;
1601 	    setErrorFlag() ;
1602 	    return ;
1603 	}
1604 	/* check memory of pin array */
1605 	if( ++numchildrenS >= childAllocS ){
1606 	    childAllocS += EXPECTEDNUMPADS ;
1607 	    pptrS->children = (INT *)
1608 		Ysafe_realloc( pptrS->children,
1609 		childAllocS * sizeof(INT) ) ;
1610 	}
1611 	pptrS->children[numchildrenS]  = i - endofcells ;
1612 	cellarrayG[i]->padptr->hierarchy = LEAF ;
1613 	cellarrayG[i]->padptr->ordered = ordered ;
1614 	/* total pins of the leaves */
1615         ptrS->numpins += cellarrayG[i]->numpins;
1616 	return;
1617     }
1618 }
1619 
1620 /* if no match above must be subroot */
1621 endofgroups = numcellsG + numpadsG + numpadgroupsG ;
1622 for (i = endofpads; i <= endofgroups; ++i) {
1623     if (strcmp(padName, cellarrayG[i]->cname) == STRINGEQ) {
1624 	if (cellarrayG[i]->padptr->hierarchy == SUBROOT) {
1625 	    sprintf(YmsgG,"pad group %s was included in more than 1 pad group\n",
1626 		cellarrayG[i]->cname);
1627 	    M(ERRMSG,"add2padgroup",YmsgG ) ;
1628 	    setErrorFlag() ;
1629 	    return ;
1630 	}
1631 	/* check memory of pin array */
1632 	if( ++numchildrenS >= childAllocS ){
1633 	    childAllocS += EXPECTEDNUMPADS ;
1634 	    pptrS->children = (INT *)
1635 		Ysafe_realloc( pptrS->children,
1636 		childAllocS * sizeof(INT) ) ;
1637 	}
1638 	pptrS->children[numchildrenS]  = i - endofcells ;
1639 	cellarrayG[i]->padptr->hierarchy = SUBROOT ;
1640 	cellarrayG[i]->padptr->ordered = ordered ;
1641 	/* total pins of the leaves */
1642 	ptrS->numpins += cellarrayG[i]->numpins;
1643 	return ;
1644     }
1645 }
1646 
1647 sprintf(YmsgG,"cannot find pad <%s> for pad_group <%s>\n",
1648     padName,ptrS->cname);
1649 M(ERRMSG,"add2padgroup",YmsgG ) ;
1650 return ;
1651 
1652 } /* end add2PadGroup */
1653 /* ***************************************************************** */
add_cell_to_group(cellName)1654 void add_cell_to_group( cellName )
1655 char *cellName ;
1656 {
1657 GLISTPTR tempCell ;
1658 INT cell, *data ;
1659 CELLBOXPTR cptr ;
1660 
1661 if(!(data = (INT *) Yhash_search( cellTableS, cellName, NULL, FIND ))){
1662     sprintf( YmsgG, "Couldn't find cellname:%s for group\n",cellName );
1663     M(ERRMSG,"add_cell_to_group",YmsgG ) ;
1664     errorFlagS = TRUE ;
1665     return ;
1666 }
1667 cell = *data ;
1668 
1669 if( tempCell = curGroupS->cells ){
1670     curGroupS->cells = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ;
1671     curGroupS->cells->next = tempCell ;
1672 } else { /* start list */
1673     curGroupS->cells = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ;
1674     curGroupS->cells->next = NULL ;
1675 }
1676 
1677 cptr = cellarrayG[cell] ;
1678 if( cptr->group_nested ){
1679     /* group_nest field should be NULL if cell is not nested */
1680     sprintf( YmsgG, "cell %d:%s appears in more than one group\n",
1681 	cell, cptr->cname ) ;
1682     M(ERRMSG,"add_cell_to_group",YmsgG ) ;
1683     errorFlagS = TRUE ;
1684 } else {
1685     cptr->group = curGroupS ;
1686     /* save cell in generic list */
1687     curGroupS->cells->p.cell = cell ;
1688     cptr->group_nested = TRUE ;
1689 }
1690 /* set exchange class so cells can't leave group thru pairwise swap */
1691 cptr->class = unique_classG ;
1692 
1693 } /* end add_cell_to_group */
1694 
1695 /* add a cell to the instance array of the defining cell */
add_instance(instName)1696 void add_instance( instName )
1697 char *instName ;
1698 {
1699     if( cellinstanceS++ == 0 ){
1700 	/* our first instance we now have two instances */
1701 	instS = ptrS->instptr = (INSTBOXPTR) Ysafe_malloc( sizeof(INSTBOX) ) ;
1702 	ptrS->cur_inst = 0 ;
1703 	instS->numinstances = 1 ;
1704 	instAllocS = 2 ;    /* default is just two instances */
1705 	/* allocate arrays for instances */
1706 	instS->tile_inst = (TILEBOXPTR *)
1707 	    Ysafe_calloc( instAllocS, sizeof(TILEBOXPTR) ) ;
1708 	instS->bounBox = (BOUNBOXPTR **)
1709 	    Ysafe_calloc( instAllocS, sizeof(BOUNBOXPTR *) ) ;
1710 	instS->numtile_inst = (INT *)
1711 	    Ysafe_calloc( instAllocS, sizeof(INT) ) ;
1712 	instS->vert_inst = (VERTBOXPTR *)
1713 	    Ysafe_malloc( instAllocS*sizeof(VERTBOXPTR) ) ;
1714 	instS->name_inst = (char **)
1715 	    Ysafe_malloc( instAllocS*sizeof(char *) ) ;
1716 	/* store main instance in element 0 of arrays */
1717 	instS->tile_inst[0] = ptrS->tiles ;
1718 	instS->bounBox[0] = ptrS->bounBox ;
1719 	instS->numtile_inst[0] = ptrS->numtiles ;
1720 	instS->vert_inst[0] = ptrS->vertices ;
1721 	instS->name_inst[0] = ptrS->cname ;
1722 	instS->name_inst[1] = instName ;
1723 
1724 	/* now for softcells */
1725 	/* allocate arrays for instances */
1726 	instS->numsides = (INT *)
1727 	    Ysafe_calloc( instAllocS, sizeof(INT) ) ;
1728 	/* store main instance in element 0 of arrays */
1729 	instS->numsides[0] = ptrS->numsides ;
1730     } else { /* realloc space for instances */
1731 	/* instances are rare and we are only dealing with pointers so */
1732 	/* always realloc, leave code general enough to change */
1733 	instAllocS += EXPECTEDINSTANCES ;
1734 	instS->tile_inst = (TILEBOXPTR *)
1735 	    Ysafe_realloc(instS->tile_inst,instAllocS*sizeof(TILEBOXPTR));
1736 	instS->vert_inst = (VERTBOXPTR *)
1737 	    Ysafe_realloc(instS->vert_inst,instAllocS*sizeof(VERTBOXPTR));
1738 	instS->numtile_inst = (INT *)
1739 	    Ysafe_realloc( instS->numtile_inst, instAllocS*sizeof(INT) ) ;
1740 	instS->bounBox = (BOUNBOXPTR **)
1741 	    Ysafe_realloc(instS->bounBox,instAllocS*sizeof(BOUNBOXPTR *));
1742 	instS->name_inst = (char **)
1743 	    Ysafe_realloc(instS->name_inst,instAllocS*sizeof(char *) ) ;
1744 	instS->numsides = (INT *)
1745 	    Ysafe_realloc( instS->numsides,instAllocS*sizeof(INT));
1746     }
1747     minxS = INT_MAX ;
1748     minyS = INT_MAX ;
1749     maxxS = INT_MIN ;
1750     maxyS = INT_MIN ;
1751     ptrS->numtiles = 0 ;
1752     cornerCountS = 0 ;
1753     instS->numinstances++ ;
1754     numinstancesG++ ;
1755 
1756 } /* end add_cell_instance */
1757 
get_tile_count()1758 INT get_tile_count()
1759 {
1760     return( tileptAllocS / 2 ) ;
1761 } /* end get_tile_count() */
1762 
add_analog(numcorners)1763 void add_analog( numcorners )
1764 INT numcorners ;
1765 {
1766     ERRORABORT() ;
1767     /* allocate space for array of instances */
1768     if( cellinstanceS == 0 ){
1769 	pinS->ainst = (ANALOGPTR *) Ysafe_malloc( sizeof(ANALOGPTR) );
1770     } else {
1771 	pinS->ainst = (ANALOGPTR *) Ysafe_realloc( pinS->ainst,
1772 	    instAllocS * sizeof(ANALOGPTR) );
1773     }
1774     analogS = pinS->analog = (ANALOGPTR) Ysafe_malloc( sizeof(ANALOGBOX) ) ;
1775     pinS->ainst[cellinstanceS] = analogS ;
1776 
1777     /* now fill in data */
1778     if( numcorners >= 4 ){
1779 	analogS->x_contour = (INT *) Ysafe_malloc( numcorners * sizeof(INT)) ;
1780 	analogS->y_contour = (INT *) Ysafe_malloc( numcorners * sizeof(INT)) ;
1781 	analogS->num_corners = numcorners ;
1782 	cornerCountS = 0 ;
1783     } else {
1784 	analogS->x_contour = NIL(INT *) ;
1785 	analogS->y_contour = NIL(INT *) ;
1786 	analogS->num_corners = 0 ;
1787     }
1788     analogS->current = INIT_CURRENT ;
1789     analogS->power =   (FLOAT) 0.0 ;
1790     analogS->no_layer_change = FALSE ;
1791 
1792 } /* end add_analog */
1793 
add_pin_contour(x,y)1794 void add_pin_contour( x, y )
1795 INT x, y ;
1796 {
1797     if( cornerCountS >= analogS->num_corners ){
1798 	sprintf( YmsgG, "Incorrect number of vertices for pin:%s\n",
1799 	    curPinNameS ) ;
1800 	M(ERRMSG,"add_pin_contour", YmsgG ) ;
1801 	setErrorFlag() ;
1802 	cornerCountS = 0 ; /* reset to avoid numerous error msgs */
1803     }
1804     ERRORABORT() ;
1805     analogS->x_contour[cornerCountS] = x ;
1806     analogS->y_contour[cornerCountS++] = y ;
1807 } /* end start_pin_contour */
1808 
1809 
add_current(current)1810 void add_current( current )
1811 FLOAT current ;
1812 {
1813     if(!(analogS)){
1814 	add_analog( 0 ) ;
1815     }
1816     analogS->current = current ;
1817 } /* end add_current */
1818 
add_power(power)1819 void add_power( power )
1820 FLOAT power ;
1821 {
1822     if(!(analogS)){
1823 	add_analog( 0 ) ;
1824     }
1825     analogS->power = power ;
1826 } /* end add_power */
1827 
no_layer_change()1828 void no_layer_change()
1829 {
1830     if(!(analogS)){
1831 	add_analog( 0 ) ;
1832     }
1833     analogS->no_layer_change = TRUE ;
1834 } /* end no_cross_under */
1835 
process_pin()1836 void process_pin()
1837 {
1838     INT i ;                      /* point counter */
1839     INT side ;                   /* current side for pin */
1840     INT ptx, pty ;               /* current point of interest */
1841     INT xpos, ypos ;             /* center of pin */
1842     INT minx, miny, maxx, maxy ; /* bounding box of pin contour */
1843     char *buster_msg ;           /* message string to used by buster */
1844     INT xx1, yy1, xx2, yy2 ;     /* temp points */
1845 
1846     ERRORABORT() ;
1847 
1848     if(!(analogS) || analogS->num_corners < 4 ){
1849 	return ; /* no work to do */
1850     }
1851 
1852     /* now check the points to make sure they are good */
1853     sprintf( YmsgG, " (cell:%s pin:%s) ", curCellNameS, pinS->pinname ) ;
1854     buster_msg = Ystrclone( YmsgG ) ;
1855     Ybuster_check_rect_init( buster_msg ) ;
1856     minx = INT_MAX ;
1857     miny = INT_MAX ;
1858     maxx = INT_MIN ;
1859     maxy = INT_MIN ;
1860     for( i = 0 ; i < analogS->num_corners ; i++ ) {
1861 	xx1 = analogS->x_contour[i] ;
1862 	yy1 = analogS->y_contour[i] ;
1863 	if( i == analogS->num_corners-1 ) {
1864 	    xx2 = analogS->x_contour[0] ;
1865 	    yy2 = analogS->y_contour[0] ;
1866 	} else {
1867 	    xx2 = analogS->x_contour[ i + 1 ] ;
1868 	    yy2 = analogS->y_contour[ i + 1 ] ;
1869 	}
1870 	if( Ybuster_check_rect( xx1, yy1, xx2, yy2 ) ){
1871 	    analog_errorS = TRUE ;
1872 	}
1873 
1874 	/* find bounding box of pins */
1875 	minx = MIN( minx, xx1 ) ;
1876 	maxx = MAX( maxx, xx1 ) ;
1877 	miny = MIN( miny, yy1 ) ;
1878 	maxy = MAX( maxy, yy1 ) ;
1879     }
1880     Ysafe_free( buster_msg ) ;
1881 
1882     /* now set the center of the pin to this location */
1883     xpos = (minx + maxx) / 2 ;
1884     ypos = (miny + maxy) / 2 ;
1885 
1886     /* now subtract off the cell center */
1887     for( i = 0 ; i < analogS->num_corners ; i++ ) {
1888 	analogS->x_contour[i] -= xcenterS ;
1889 	analogS->y_contour[i] -= ycenterS ;
1890     }
1891     set_pin_pos( xpos, ypos ) ;
1892 
1893 } /* end process_analog_pin */
1894