1 /*
2 * $Id: util_Power.c,v 1.2 2002/09/30 16:21:19 czo Exp $
3 *
4 * /----------------------------------------------------------------\
5 * | |
6 * | A l l i a n c e C A D S y s t e m |
7 * | S i l i c o n E n s e m b l e / A l l i a n c e |
8 * | |
9 * | Author : Jean-Paul CHAPUT |
10 * | E-mail : alliance-users@asim.lip6.fr |
11 * | ============================================================== |
12 * | C Module : "./util_Power.c" |
13 * | ************************************************************** |
14 * | U p d a t e s |
15 * | |
16 * \----------------------------------------------------------------/
17 */
18
19
20 # include "util_Defs.h"
21 # include "debugoff.h"
22
23
24 /* ------------------------------------------------------------------
25 * Local variables (prefix 'LV_').
26 */
27
28 static long LV_XAB1;
29 static long LV_YAB1;
30 static long LV_XAB2;
31 static long LV_YAB2;
32
33
34 /* ----------------------------------------------------------------------
35 * Local functions declarations.
36 */
37
38 static int onSlice __FP((long aY));
39 static void setPowerAB __FP((long XAB1, long YAB1,
40 long XAB2, long YAB2));
41
42
43 /*
44 * /--------------------------------------------------------------------\
45 * | Functions Definitions |
46 * \--------------------------------------------------------------------/
47 */
48
49
50 /* ----------------------------------------------------------------------
51 * Function : "setPowerAB()".
52 */
53
setPowerAB(XAB1,YAB1,XAB2,YAB2)54 static void setPowerAB(XAB1, YAB1, XAB2, YAB2)
55 long XAB1, YAB1, XAB2, YAB2;
56 {
57 LV_XAB1 = XAB1;
58 LV_YAB1 = YAB1;
59 LV_XAB2 = XAB2;
60 LV_YAB2 = YAB2;
61 }
62
63
64
65 /* ----------------------------------------------------------------------
66 * Function : "onSlice()".
67 */
68
onSlice(aY)69 static int onSlice(aY)
70 long aY;
71 {
72 if (aY < LV_YAB1) return (FALSE);
73 if (aY > LV_YAB2) return (FALSE);
74
75 if (!(((aY - MBK_WIDTH_VDD / 2) - LV_YAB1) % MBK_Y_SLICE)) return (TRUE);
76 if (!(((aY + MBK_WIDTH_VDD / 2) - LV_YAB1) % MBK_Y_SLICE)) return (TRUE);
77
78 if (!(((aY - MBK_WIDTH_VSS / 2) - LV_YAB1) % MBK_Y_SLICE)) return (TRUE);
79 if (!(((aY + MBK_WIDTH_VSS / 2) - LV_YAB1) % MBK_Y_SLICE)) return (TRUE);
80
81 return (FALSE);
82 }
83
84 /* ----------------------------------------------------------------------
85 * Function : "addPow()".
86 */
87
88 extern ePow_t *addPow(applPow, aY, aW, aName, aType, aDir)
89 ePow_t **applPow;
90 long aY;
91 long aW;
92 char *aName;
93 char aType;
94 char aDir;
95 {
96 ePow_t *pPow, **ppPow;
97
98
99 pPow = (ePow_t*)mbkalloc(sizeof(ePow_t));
100 pPow->y = aY;
101 pPow->w = aW;
102 pPow->flags = 0;
103 pPow->inter = NULL;
104
105 switch(aDir) {
106 case C_POWER_VERTICAL:
107 pPow->xMin = LV_YAB1;
108 pPow->xMax = LV_YAB2;
109 pPow->min = LV_YAB2;
110 pPow->max = LV_YAB1;
111 break;
112 default:
113 case C_POWER_HORIZONTAL:
114 pPow->xMin = LV_XAB1;
115 pPow->xMax = LV_XAB2;
116 pPow->min = LV_XAB2;
117 pPow->max = LV_XAB1;
118 break;
119 }
120
121 pPow->Name = namealloc(aName);
122 pPow->Type = aType;
123
124
125 /* Insert in the ordered list. */
126 for(ppPow = applPow ; *ppPow != NULL ; ppPow = &((*ppPow)->Next)) {
127 if ((*ppPow)->y >= pPow->y) {
128 pPow->Next = *ppPow;
129 *ppPow = pPow;
130 break;
131 }
132 }
133
134
135 /* The list is empty or the element is the last one. */
136 if (*ppPow == (ePow_t*)NULL) {
137 pPow->Next = *ppPow;
138 *ppPow = pPow;
139 }
140
141
142 return(pPow);
143 }
144
145
146 /* ----------------------------------------------------------------------
147 * Function : "freePow()".
148 */
149
freePow(aplPow)150 extern void freePow(aplPow)
151 struct ePow_s *aplPow;
152 {
153 struct ePow_s *pDel, *pNext;
154
155
156 for (pDel = aplPow; pDel != NULL; ) {
157 pNext = pDel->Next;
158
159 freeinter (pDel->inter);
160 mbkfree (pDel);
161
162 pDel = pNext;
163 }
164 }
165
166
167 /* ----------------------------------------------------------------------
168 * Function : "getPow()".
169 */
170
171 extern ePow_t *getPow(aplPow, aY)
172 ePow_t *aplPow;
173 long aY;
174 {
175 ePow_t *pPow;
176
177
178 for( pPow = aplPow ; pPow != NULL ; pPow = pPow->Next )
179 if (pPow->y == aY) return( pPow );
180
181 return( NULL );
182 }
183
184
185 /* ----------------------------------------------------------------------
186 * Function : "mergeXPow()".
187 */
188
189 extern void mergeXPow(apPow, axMin, axMax, aW)
190 ePow_t *apPow;
191 long axMin, axMax, aW;
192 {
193 if (aW == apPow->w)
194 apPow->inter = addinter (apPow->inter, axMin, axMax);
195
196 apPow->min = m_Min(apPow->min, axMin);
197 apPow->max = m_Max(apPow->max, axMax);
198 }
199
200
201 /* ----------------------------------------------------------------------
202 * Function : "buildPow()".
203 */
204
buildPow(apPhfig,aLayer,aDir,asSuffix)205 extern ePow_t *buildPow(apPhfig, aLayer, aDir, asSuffix)
206 struct phfig *apPhfig;
207 char aLayer;
208 char aDir;
209 char *asSuffix;
210 {
211 ePow_t **pplPow, *plPow, *pPow;
212 phseg_list *pPhseg;
213 phcon_list *pPhcon;
214 char type;
215 char ORIENT1, ORIENT2, *sDir1, *sDir2;
216 long X1, X2, Y1, Y2;
217
218
219 setPowerAB (apPhfig->XAB1, apPhfig->YAB1,
220 apPhfig->XAB2, apPhfig->YAB2);
221
222
223 switch(aDir) {
224 case C_POWER_VERTICAL:
225 sDir1 = "vertical";
226 sDir2 = "NORTH/SOUTH";
227 ORIENT1 = NORTH;
228 ORIENT2 = SOUTH;
229 break;
230 default:
231 case C_POWER_HORIZONTAL:
232 sDir1 = "horizontal";
233 sDir2 = "EAST/WEST";
234 ORIENT1 = EAST;
235 ORIENT2 = WEST;
236 break;
237 }
238
239
240 pplPow = &plPow;
241 *pplPow = NULL;
242
243
244 /* Find power terminals among CALUx segments (new convention). */
245 for(pPhseg = apPhfig->PHSEG ; pPhseg != NULL ; pPhseg = pPhseg->NEXT) {
246 type = C_POWER_ISNONE;
247
248 if (isvdd(pPhseg->NAME)) type = C_POWER_ISVDD;
249 if (isvss(pPhseg->NAME)) type = C_POWER_ISVSS;
250
251 switch(aDir) {
252 case C_POWER_VERTICAL:
253 Y1 = pPhseg->X1;
254 Y2 = pPhseg->X2;
255 X1 = pPhseg->Y1;
256 X2 = pPhseg->Y2;
257 break;
258 default:
259 case C_POWER_HORIZONTAL:
260 Y1 = pPhseg->Y1;
261 Y2 = pPhseg->Y2;
262 X1 = pPhseg->X1;
263 X2 = pPhseg->X2;
264 break;
265 }
266
267 if (type != C_POWER_ISNONE) {
268 if (cmpALU(aLayer, pPhseg->LAYER) & F_CALU) {
269 if (Y1 != Y2) {
270 wprinth(NULL);
271 wprintf("\n In figure \"%s\" :", apPhfig->NAME);
272 wprintf("\n CALU1 Power segment \"%s\" at (%d,%d)",
273 pPhseg->NAME,
274 MBKUNSCALE (pPhseg->X1),
275 MBKUNSCALE (pPhseg->Y1));
276 wprintf(" is not %s.\n", sDir1);
277 continue;
278 }
279
280 if (aDir == C_POWER_HORIZONTAL) {
281 if (!onSlice(Y1)) {
282 wprinth(NULL);
283 wprintf("\n In figure \"%s\" :", apPhfig->NAME);
284 wprintf("\n CALU1 Power segment \"%s\" at (%d,%d)",
285 pPhseg->NAME,
286 MBKUNSCALE (pPhseg->X1),
287 MBKUNSCALE (pPhseg->Y1));
288 wprintf(" is not on a slice boundary.");
289 wprintf("\n (valide slices boundaries are");
290 wprintf(" ((n * %ld) - %ld) or" , Y_SLICE, WIDTH_VSS / 2);
291 wprintf(" ((n * %ld) + %ld) )\n" , Y_SLICE, WIDTH_VSS / 2);
292 continue;
293 }
294 }
295
296 if ((pPow = getPow(plPow, Y1)) == NULL) {
297 pPow = addPow(pplPow ,
298 Y1 ,
299 pPhseg->WIDTH,
300 pPhseg->NAME ,
301 type ,
302 aDir );
303 }
304
305 if (pPhseg->NAME != pPow->Name) {
306 eprinth(NULL);
307 eprintf("\n In figure \"%s\" :", apPhfig->NAME);
308 eprintf("\n CALU1 Power segment \"%s\" at (%d,%d)\n",
309 pPhseg->NAME,
310 MBKUNSCALE (pPhseg->X1),
311 MBKUNSCALE (pPhseg->Y1));
312 eprintf(" conflict with \"%s\" power line at %d.\n",
313 pPow->Name,
314 pPow->y );
315 EXIT(1);
316 }
317
318 mergeXPow(pPow, X1, X2, pPhseg->WIDTH);
319 }
320 }
321 } /* End of "pPhseg" loop. */
322
323
324 /* Find power terminals among terminals (for backward compatibility). */
325 for(pPhcon = apPhfig->PHCON ; pPhcon != NULL ; pPhcon = pPhcon->NEXT) {
326 type = C_POWER_ISNONE;
327
328 if (isvdd(pPhcon->NAME)) type = C_POWER_ISVDD;
329 if (isvss(pPhcon->NAME)) type = C_POWER_ISVSS;
330
331 switch(aDir) {
332 case C_POWER_VERTICAL:
333 Y1 = pPhcon->XCON;
334 X1 = pPhcon->YCON;
335 break;
336 default:
337 case C_POWER_HORIZONTAL:
338 Y1 = pPhcon->YCON;
339 X1 = pPhcon->XCON;
340 break;
341 }
342
343 if (type != C_POWER_ISNONE) {
344 if (cmpALU(aLayer, pPhcon->LAYER)) {
345 if ( (pPhcon->ORIENT != ORIENT1)
346 && (pPhcon->ORIENT != ORIENT2)) {
347 eprinth(NULL);
348 eprintf("\n In figure \"%s\" :", apPhfig->NAME);
349 eprintf("\n ALU1 Power terminal \"%s\" at (%d,%d)",
350 pPhcon->NAME,
351 MBKUNSCALE (pPhcon->XCON),
352 MBKUNSCALE (pPhcon->YCON));
353 eprintf(" is not on %s side.\n", sDir2);
354 EXIT(1);
355 }
356
357 if (aDir == C_POWER_HORIZONTAL) {
358 if (!onSlice(pPhcon->YCON)) {
359 eprinth(NULL);
360 eprintf("\n In figure \"%s\" :", apPhfig->NAME);
361 eprintf("\n ALU1 Power terminal \"%s\" at (%d,%d)",
362 pPhcon->NAME,
363 MBKUNSCALE (pPhcon->XCON),
364 MBKUNSCALE (pPhcon->YCON));
365 eprintf(" is not on a slice boundary.");
366 eprintf("\n (valide slices boundaries are");
367 eprintf(" ((n * %ld) - %ld) or" , Y_SLICE, WIDTH_VSS / 2);
368 eprintf(" ((n * %ld) + %ld) )\n" , Y_SLICE, WIDTH_VSS / 2);
369 EXIT(1);
370 }
371 }
372
373 if ((pPow = getPow(plPow, Y1)) == NULL) {
374 pPow = addPow(pplPow ,
375 Y1 ,
376 pPhcon->WIDTH,
377 pPhcon->NAME ,
378 type ,
379 aDir );
380 }
381
382 if (pPhcon->NAME != pPow->Name) {
383 eprinth(NULL);
384 eprintf("\n In figure \"%s\" :", apPhfig->NAME);
385 eprintf("\n ALU1 Power terminal \"%s\" at (%d,%d)\n",
386 pPhcon->NAME,
387 MBKUNSCALE (pPhcon->XCON),
388 MBKUNSCALE (pPhcon->YCON));
389 eprintf(" conflict with \"%s\" power line at %d.\n",
390 pPow->Name,
391 pPow->y );
392 EXIT(1);
393 }
394
395 mergeXPow(pPow, X1, X1, pPhcon->WIDTH);
396 }
397 }
398 } /* End of "pPhcon" loop. */
399
400
401 /* Look if the power lines are complete. */
402 for (pPow = plPow; pPow != NULL; pPow = pPow->Next) {
403 if ( (pPow->inter->len == 1)
404 && (pPow->inter->min == pPow->xMin)
405 && (pPow->inter->max == pPow->xMax)) {
406 pPow->flags |= F_POWER_COMPLETE;
407 __DBG( printf ("powerline at %ld is complete.\n", pPow->y); )
408 }
409 }
410
411
412 return (plPow);
413 }
414
415
416 /* ----------------------------------------------------------------------
417 * Function : "powToCon()".
418 */
419
powToCon(apPhfig,aLayer,aDir,aplPow,aFlags)420 extern void powToCon(apPhfig, aLayer, aDir, aplPow, aFlags)
421 struct phfig *apPhfig;
422 char aLayer;
423 char aDir;
424 struct ePow_s *aplPow;
425 long aFlags;
426 {
427 struct ePow_s *pPow;
428 char *conName;
429 long w, y, skipFlag;
430
431
432 for (pPow = aplPow; pPow != NULL; pPow = pPow->Next) {
433 skipFlag = FALSE;
434
435 switch (pPow->Type) {
436 default:
437 case C_POWER_ISVSS: conName = "vss"; break;
438 case C_POWER_ISVDD: conName = "vdd"; break;
439 }
440
441 w = pPow->w;
442 y = pPow->y;
443
444 if (aFlags & F_POWER_MERGE) {
445 if ( (pPow->Next != NULL)
446 && (pPow->Next->y == pPow->y + MBKSCALE(6))) {
447 skipFlag = TRUE;
448
449 w = MBKSCALE(12);
450 y += MBKSCALE(3);
451 }
452 }
453
454 if (aDir == C_POWER_HORIZONTAL) {
455 if (pPow->flags & F_POWER_COMPLETE) {
456 addphcon (apPhfig,
457 WEST,
458 conName,
459 pPow->xMin,
460 y,
461 aLayer,
462 w);
463 }
464
465 if (pPow->flags & F_POWER_COMPLETE) {
466 addphcon (apPhfig,
467 EAST,
468 conName,
469 pPow->xMax,
470 y,
471 aLayer,
472 w);
473 }
474 } else {
475 if (pPow->flags & F_POWER_COMPLETE) {
476 addphcon (apPhfig,
477 SOUTH,
478 conName,
479 y,
480 pPow->xMin,
481 aLayer,
482 w);
483 }
484
485 if (pPow->flags & F_POWER_COMPLETE) {
486 addphcon (apPhfig,
487 NORTH,
488 conName,
489 y,
490 pPow->xMax,
491 aLayer,
492 w);
493 }
494 }
495
496 if (skipFlag) pPow = pPow->Next;
497 }
498 }
499