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