Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / api / stm / stm_API_cache.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI AVERTEC */
4 /* */
5 /* Fichier : stm_API_cache.c */
6 /* */
7 /* © copyright 2003 AVERTEC */
8 /* Tous droits reserves */
9 /* */
10 /* Auteur(s) : Antony PINTO */
11 /* */
12 /****************************************************************************/
13
14 #include "stm_API_cache.h"
15
16 static double THRESHOLD = 120.0;
17 static stm_tree4cache *APISTM_TREE = NULL;
18 static stm_current *CURRENT = NULL;
19
20 static int stm_gettimingfunction_and_signalcapa(char *out, timing_function **fct, double *capa);
21
22 static stm_current *stm_getCurrent(timing_function *fct);
23
24 void stm_createCache(void);
25 double stm_getSlope (double inslope, double outload);
26 double stm_getDelay (double inslope, double outload);
27 void stm_storeSlope (double inslope, double outload, double slope);
28 void stm_storeDelay (double inslope, double outload, double delay);
29 int stm_delayThresholdOK(double inslope, double outload, double threshold);
30 int stm_slopeThresholdOK(double inslope, double outload, double threshold);
31
32 void stm_displayRange(timing_table *table);
33
34 static void stm_storeInTable(timing_table **table, double inslope, double outload, double delay, int mode);
35 static int stm_thresholdOK(timing_table *table, double inslope, double outload, double threshold);
36 static int stm_getBeforeAndAfter(float *range, int max, double value, int *before, int *after);
37 static double stm_thresholdTest(double x0, double x1, double x, double y0, double y1);
38 static void stm_getVar(timing_table *table, double *x0, double *x1, double *y0, double *y1, int bx, int ax, int by, int ay, int mode) ;
39 static int stm_findIndex(float *range, double value, int size);
40 static int stm_copyRangeAndInsert(float *range, float *new, double value, int size);
41
42 static int isEqual(float a, float b);
43 static int isInf(float a, float b);
44
45 static stm_tree4cache *stm_newTree(stm_tree4cache *head);
46 static stm_tree4cache *stm_freeTree(stm_tree4cache *tree);
47 static stm_tree4cache *stm_freeAllTree(stm_tree4cache *tree);
48 static stm_tree4cache *stm_addTree(stm_tree4cache *current, char *orig, char *dest, char *type);
49
50 static void stm_setDelayNSlope(stm_tree4cache *tree, double delay, double slope);
51 static void stm_updateCacheFromTree(stm_tree4cache *tree, double inslope);
52 static double stm_getTreeSlope(stm_tree4cache *tree, char *orig);
53 static void stm_applyTree(double inslope);
54 static double stm_interpol(timing_table *table, double inslope, double outload, float (*func)(timing_table *, float, float), long type);
55 static double stm_getValue(timing_table *table, double inslope, double outload, float (*func)(timing_table *, float, float));
56
57 static void stm_fillFindUpnDown(timing_table *tbl, int xind, int yind, int *up, int *down);
58 static void stm_fillCol(timing_table *tbl, int up, int down, int xind);
59 static void stm_fillNewLine(timing_table *tbl,int yind);
60 static void stm_fillFindLeftnRight(timing_table *tbl, int xind, int yind, int *beg, int *end);
61 static void stm_fillLine(timing_table *tbl, int beg, int end, int yind);
62 static void stm_fillNewCol(timing_table *tbl,int xind);
63 static void stm_fillTbl(timing_table *tbl, int xind, int yind, char type);
64
65 void stm_test_threshold(void);
66
67 /****************************************************************************/
68 /*{{{ stm_API_ActionTerminate() */
69 /* */
70 /* */
71 /****************************************************************************/
72 void stm_API_ActionTerminate() // commentaire pour desactiver l'ajout de token
73 {
74 APISTM_TREE = stm_freeAllTree(APISTM_TREE);
75 }
76 /*}}}************************************************************************/
77 /*{{{ Tree Management */
78 /****************************************************************************/
79 /*{{{ stm_newTree() */
80 /* */
81 /* */
82 /****************************************************************************/
83 static stm_tree4cache *stm_newTree(stm_tree4cache *head)
84 {
85 stm_tree4cache *res;
86
87 res = mbkalloc(sizeof(struct stm_tree4cache));
88
89 res->FLAG = 0;
90 res->NEXT = head;
91
92 return res;
93 }
94
95 /*}}}************************************************************************/
96 /*{{{ stm_freeTree() */
97 /* */
98 /* */
99 /****************************************************************************/
100 static stm_tree4cache *stm_freeTree(stm_tree4cache *tree)
101 {
102 mbkfree(tree);
103
104 return NULL;
105 }
106
107 /*}}}************************************************************************/
108 /*{{{ stm_freeAllTree() */
109 /* */
110 /* */
111 /****************************************************************************/
112 static stm_tree4cache *stm_freeAllTree(stm_tree4cache *tree)
113 {
114 if (tree)
115 {
116 tree->NEXT = stm_freeAllTree(tree->NEXT);
117 tree = stm_freeTree(tree);
118 }
119 return tree;
120 }
121
122 /*}}}************************************************************************/
123 /*{{{ stm_addTree() */
124 /* */
125 /* */
126 /****************************************************************************/
127 static stm_tree4cache *stm_addTree(stm_tree4cache *current, char *orig,
128 char *dest, char *type)
129 {
130 stm_tree4cache treex, *res = NULL;
131
132 orig = namealloc(orig);
133 dest = namealloc(dest);
134 type = namealloc(type);
135 treex.NEXT = current;
136 treex.ORIG = NULL;
137
138 for ( ; treex.NEXT; treex = *(treex.NEXT))
139 if (treex.ORIG == orig && treex.DEST == dest && treex.DIRECTION == type)
140 res = &treex;
141
142 if (res)
143 return res;
144 else
145 {
146 res = stm_newTree(treex.NEXT);
147 treex.NEXT = res;
148 res->NEXT = current;
149 res->ORIG = orig;
150 res->DEST = dest;
151 res->DIRECTION = type;
152 }
153
154 return res;
155 }
156
157 /*}}}************************************************************************/
158 /*{{{ stm_setDelayNSlope() */
159 /* */
160 /* */
161 /****************************************************************************/
162 static void stm_setDelayNSlope(stm_tree4cache *tree, double delay,
163 double slope)
164 {
165 tree->DELAY = delay;
166 tree->SLOPE = slope;
167 }
168
169 /*}}}************************************************************************/
170 /*{{{ stm_updateCacheFromTree() */
171 /* */
172 /* */
173 /****************************************************************************/
174 static void stm_updateCacheFromTree(stm_tree4cache *tree,double inslope)
175 {
176 stm_tree4cache *treex;
177
178 for (treex = tree; tree; tree = tree->NEXT)
179 {
180 if (!treex->FLAG)
181 {
182 timing_function *fct;
183 timing_table *tbl;
184 stm_current *cur;
185 double capa, slope;
186 int mode;
187
188 switch (stm_gettimingfunction_and_signalcapa(treex->DEST,&fct,&capa))
189 {
190 case 0 :
191 case 1 :
192 cur = stm_getCurrent(fct);
193 slope = stm_getTreeSlope(tree,treex->ORIG);
194 inslope = (slope > 0.0) ? slope : inslope;
195 tbl = cur->DELAY;
196 mode = stm_thresholdOK(tbl,inslope,capa, 20);
197 stm_storeInTable(&tbl, inslope, capa, treex->DELAY, mode);
198 cur->DELAY = tbl;
199 tbl = cur->SLOPE;
200 stm_storeInTable(&tbl, inslope, capa, treex->SLOPE, mode);
201 cur->SLOPE = tbl;
202 default :
203 treex->FLAG = 1;
204 }
205 }
206 }
207 }
208
209 /*}}}************************************************************************/
210 /*{{{ stm_getTreeSlope() */
211 /* */
212 /* */
213 /****************************************************************************/
214 static double stm_getTreeSlope(stm_tree4cache *tree, char *orig)
215 {
216 for ( ; tree; tree = tree->NEXT)
217 if (tree->DEST == orig)
218 return tree->SLOPE;
219 return -1.0;
220 }
221
222 /*}}}************************************************************************/
223 /*{{{ SET_DELAY_AND_SLOPE() */
224 /* */
225 /* */
226 /****************************************************************************/
227 void SET_DELAY_AND_SLOPE(char *in, char *out, char *direction, double delay,
228 double slope)
229 {
230 stm_tree4cache *res;
231
232 res = stm_addTree(APISTM_TREE,in,out,direction);
233 stm_setDelayNSlope(res,delay,slope);
234 if (!APISTM_TREE)
235 APISTM_TREE = res;
236 }
237
238 /*}}}************************************************************************/
239 /*{{{ stm_applyTree() */
240 /* */
241 /* */
242 /****************************************************************************/
243 static void stm_applyTree(double inslope)
244 {
245 stm_updateCacheFromTree(APISTM_TREE,inslope);
246 APISTM_TREE = stm_freeAllTree(APISTM_TREE);
247 }
248
249 /*}}}************************************************************************/
250 /*}}}************************************************************************/
251 /*{{{ Extern Funtions */
252 /****************************************************************************/
253 /*{{{ High Level Functions */
254 /* */
255 /* CURRENT VSLOPE represents input slope setted by stm_thresholdOK */
256 /* CURRENT VLOAD represents output capa setted by stm_thresholdOK */
257 /* */
258 /****************************************************************************/
259 void stm_sup_storeDelay(double delay)
260 {
261 stm_storeDelay(CURRENT->VSLOPE,CURRENT->VLOAD,delay);
262 stm_applyTree(CURRENT->VSLOPE);
263 }
264
265 void stm_sup_storeSlope(double slope)
266 {
267 stm_storeSlope(CURRENT->VSLOPE,CURRENT->VLOAD,slope);
268 stm_applyTree(CURRENT->VSLOPE);
269 }
270
271 double stm_sup_getDelay()
272 {
273 return stm_getDelay(CURRENT->VSLOPE,CURRENT->VLOAD);
274 }
275
276 double stm_sup_getSlope()
277 {
278 return stm_getSlope(CURRENT->VSLOPE,CURRENT->VLOAD);
279 }
280
281 /*}}}************************************************************************/
282
283 /*{{{ stm_freeCurrent() */
284 /* */
285 /* */
286 /****************************************************************************/
287 static void stm_freeCurrent(void *x)
288 {
289 stm_current *current;
290
291 current = x;
292 if (current)
293 {
294 stm_freeCurrent(current->NEXT);
295 stm_modtbl_destroy(current->DELAY);
296 stm_modtbl_destroy(current->SLOPE);
297 current->NEXT = NULL;
298 mbkfree(current);
299 }
300 }
301
302 /*}}}************************************************************************/
303 /*{{{ stm_newCurrent() */
304 /* */
305 /* */
306 /****************************************************************************/
307 stm_current *stm_newCurrent(stm_current *head, char *insname)
308 {
309 stm_current *current;
310
311 current = mbkalloc(sizeof(struct stm_current));
312 current->NEXT = head;
313 current->INS = insname;
314 current->DELAY = NULL;
315 current->SLOPE = NULL;
316 current->VSLOPE = 0.0;
317 current->VLOAD = 0.0;
318 current->VDELAY = 0.0;
319 current->TRESRES = 0;
320
321 return current;
322 }
323
324 /*}}}************************************************************************/
325 /*{{{ stm_getCurrentByName() */
326 /* */
327 /* */
328 /****************************************************************************/
329 stm_current *stm_getCurrentByName(ptype_list *ptype, char *name)
330 {
331 stm_current *cur;
332
333 for (cur = ptype->DATA; cur && cur->INS != name; cur = cur->NEXT)
334 ;
335 if (!cur)
336 {
337 ptype->DATA = stm_newCurrent(ptype->DATA,name);
338 cur = ptype->DATA;
339 }
340
341 return cur;
342 }
343
344 /*}}}************************************************************************/
345 /*{{{ stm_getCurrent() */
346 /* */
347 /* */
348 /****************************************************************************/
349 stm_current *stm_getCurrent(timing_function *fct)
350 {
351 ptype_list *ptypex;
352 stm_current *cur;
353
354 ptypex = stm_modfct_getSharedType(fct,STM_CURRENT_TYPE);
355
356 if (!ptypex)
357 cur = stm_modfct_addSharedType(fct,STM_CURRENT_TYPE,
358 stm_newCurrent(NULL,fct->INS),
359 stm_freeCurrent) -> DATA;
360 else
361 cur = stm_getCurrentByName(ptypex,fct->INS);
362
363 return cur;
364 }
365
366 /*}}}************************************************************************/
367 /*{{{ stm_createCache() */
368 /* */
369 /* */
370 /****************************************************************************/
371 void stm_createCache()
372 {
373 CURRENT = stm_getCurrent(stm_get_current_arc());
374 #ifdef _PRINT
375 printf("instance : %s\n",CURRENT->INS);
376 stm_displayTable("slope",CURRENT->SLOPE);
377 stm_displayTable("delay",CURRENT->DELAY);
378 #endif
379 }
380
381 /*}}}************************************************************************/
382 /*{{{ stm_delayThresholdOK() */
383 /* */
384 /* */
385 /****************************************************************************/
386 int stm_delayThresholdOK(double inslope, double outload, double threshold)
387 {
388 stm_createCache();
389
390 #ifdef _PRINT
391 printf("computing delay for slope %4.3g, load %4.3g\n",inslope,outload);
392 #endif
393 CURRENT->TYPE = STM_MODE_DELAY;
394 CURRENT->VSLOPE = inslope;
395 CURRENT->VLOAD = outload;
396 CURRENT->TRESRES = stm_thresholdOK(CURRENT->DELAY,inslope,outload,
397 threshold);
398
399 if (CURRENT->TRESRES&STM_THRESHOLD_NOMATCH)
400 return 0;
401 else
402 {
403 #ifdef _PRINT
404 // printf("delai ok\n");
405 #endif
406 return CURRENT->TRESRES;
407 }
408 }
409
410 /*}}}************************************************************************/
411 /*{{{ stm_slopeThresholdOK() */
412 /* */
413 /* */
414 /****************************************************************************/
415 int stm_slopeThresholdOK(double inslope, double outload, double threshold)
416 {
417 stm_createCache();
418
419 #ifdef _PRINT
420 printf("computing slope for slope %g, load %g\n",inslope,outload);
421 #endif
422 CURRENT->TYPE = STM_MODE_SLOPE;
423 CURRENT->VSLOPE = inslope;
424 CURRENT->VLOAD = outload;
425 CURRENT->TRESRES = stm_thresholdOK(CURRENT->SLOPE,inslope,outload,
426 threshold);
427
428 if (CURRENT->TRESRES & STM_THRESHOLD_NOMATCH)
429 return 0;
430 else
431 {
432 #ifdef _PRINT
433 printf("slope ok\n");
434 #endif
435 return CURRENT->TRESRES;
436 }
437 }
438
439 /*}}}************************************************************************/
440 /*{{{ stm_storeDelay() */
441 /* */
442 /* */
443 /****************************************************************************/
444 void stm_storeDelay(double inslope, double outload, double delay)
445 {
446 stm_storeInTable( &(CURRENT->DELAY),inslope,outload,delay,
447 (CURRENT->TRESRES)&STM_THRESHOLD_MATCH_XY);
448 #ifdef _PRINT
449 stm_displayTable(CURRENT->DELAY);
450 #endif
451 }
452
453 /*}}}************************************************************************/
454 /*{{{ stm_storeSlope() */
455 /* */
456 /* */
457 /****************************************************************************/
458 void stm_storeSlope(double inslope, double outload, double slope)
459 {
460 #ifdef _PRINT
461 printf("inserting %g,%g,%g\n",inslope,outload,slope);
462 #endif
463 stm_storeInTable(&(CURRENT->SLOPE),inslope,outload,slope,
464 (CURRENT->TRESRES)&STM_THRESHOLD_MATCH_XY);
465 #ifdef _PRINT
466 stm_displayTable(CURRENT->SLOPE);
467 #endif
468 }
469
470 /*}}}************************************************************************/
471 /*{{{ stm_getDelay() */
472 /* */
473 /* */
474 /****************************************************************************/
475 double stm_getDelay(double inslope, double outload)
476 {
477 return stm_getValue(CURRENT->DELAY,inslope,outload,stm_modtbl_delay);
478 }
479
480 /*}}}************************************************************************/
481 /*{{{ stm_getSlope() */
482 /* */
483 /* */
484 /****************************************************************************/
485 double stm_getSlope(double inslope, double outload)
486 {
487 return stm_getValue(CURRENT->SLOPE,inslope,outload,stm_modtbl_slew);
488 }
489
490 /*}}}************************************************************************/
491 /*{{{ stm_printVariation() */
492 /* */
493 /* */
494 /****************************************************************************/
495 void stm_printVariation(FILE *fp, double real, double found)
496 {
497 fprintf(fp,"real : %g",real);
498 fprintf(fp,",found : %g",found);
499 fprintf(fp,",variation : %3.1f%%\n",100*(real-found)/real);
500 }
501
502 /*}}}************************************************************************/
503 /*}}}************************************************************************/
504 /*{{{ Static functions */
505 /****************************************************************************/
506 /*{{{ stm_getValue() */
507 /* */
508 /* */
509 /****************************************************************************/
510 static double stm_getValue(timing_table *table, double inslope,
511 double outload,
512 float (*func)(timing_table *, float, float))
513 {
514 // stm_displayTable(table);
515 if (CURRENT->TRESRES == STM_THRESHOLD_MATCH_XY)
516 {
517 int x, y;
518 x = stm_findIndex(table->XRANGE,inslope,table->NX);
519 y = stm_findIndex(table->YRANGE,outload,table->NY);
520 return table->SET2D[x][y];
521 }
522 else
523 return stm_interpol(table,inslope,outload,func,CURRENT->TRESRES);
524 }
525
526 /*}}}************************************************************************/
527 /*{{{ stm_interpol() */
528 /* */
529 /* */
530 /****************************************************************************/
531 static double stm_interpol(timing_table *table, double inslope,
532 double outload,
533 float (*func)(timing_table *, float, float),
534 long type)
535 {
536 float **set2D, set1D[1024], res, *xrange;
537 int nx, x = -1, y = -1, i;
538 long xt;
539
540 set2D = table->SET2D;
541 nx = table->NX;
542 xrange = table->XRANGE;
543 xt = table->XTYPE;
544
545 y = (table->NY == 1) ? 0 : (type&STM_THRESHOLD_MATCH_Y)
546 ? stm_findIndex(table->YRANGE,outload,table->NY): y;
547 x = (table->NX == 1) ? 0 : (type&STM_THRESHOLD_MATCH_X)
548 ? stm_findIndex(table->XRANGE,inslope,table->NX) : x;
549
550 if (y >= 0)
551 {
552 for (i = 0; i < table->NX; i ++)
553 set1D[i] = set2D[i][y];
554 table->SET2D = NULL;
555 table->SET1D = set1D;
556 }
557 else if (x >= 0)
558 {
559 table->SET2D = NULL;
560 table->SET1D = set2D[x];
561 table->NX = table->NY;
562 table->XRANGE = table->YRANGE;
563 table->XTYPE = STM_LOAD;
564 }
565
566 res = (*func)(table,outload,inslope);
567 table->SET2D = set2D;
568 table->SET1D = NULL;
569 table->NX = nx;
570 table->XRANGE = xrange;
571 table->XTYPE = xt;
572 /*
573 if (table->NY == 1)
574 {
575 int i;
576
577 for (i = 0; i < table->NX; i ++)
578 set1D[i] = set2D[i][0];
579 table->SET2D = NULL;
580 table->SET1D = set1D;
581 }
582 else if (table->NX == 1)
583 {
584 table->SET2D = NULL;
585 table->SET1D = set2D[0];
586 table->NX = table->NY;
587 }
588 res = (*func)(table,outload,inslope);
589 table->SET2D = set2D;
590 table->SET1D = NULL;
591 table->NX = nx;
592 */
593
594
595 return res;
596 }
597
598 /*}}}************************************************************************/
599 /*{{{ stm_thresholdOK() */
600 /* */
601 /* */
602 /****************************************************************************/
603 static int stm_thresholdOK(timing_table *table, double inslope,
604 double outload, double threshold)
605 {
606 int bx, ax, by, ay, x, y, res;
607 double x0, x1, y0, y1;
608
609 if (table)
610 {
611 x = stm_getBeforeAndAfter(table->XRANGE,table->NX,inslope,&bx,&ax);
612 y = stm_getBeforeAndAfter(table->YRANGE,table->NY,outload,&by,&ay);
613 res = 0;
614 if (x || y)
615 {
616 if (x && y)
617 {
618 res = STM_THRESHOLD_MATCH_XY;
619 if (table->SET2D[bx][by] == STM_NOVALUE)
620 res |= STM_THRESHOLD_NOMATCH;
621 }
622 else if (x)
623 {
624 res |= STM_THRESHOLD_MATCH_X;
625 if (ay == table->NY || by == -1)
626 res |= STM_THRESHOLD_NOMATCH;
627 else
628 {
629 stm_getVar(table,&x0,&x1,&y0,&y1,bx,ax,by,ay,0);
630 if ( stm_thresholdTest(x0,x1,outload,y0,y1) > threshold )
631 res |= STM_THRESHOLD_NOMATCH;
632 else
633 res |= STM_THRESHOLD_MATCH;
634 }
635 }
636 else
637 {
638 res |= STM_THRESHOLD_MATCH_Y;
639 if (ax == table->NX || bx == -1)
640 res |= STM_THRESHOLD_NOMATCH;
641 else
642 {
643 stm_getVar(table,&x0,&x1,&y0,&y1,bx,ax,by,ay,1);
644 if ( stm_thresholdTest(x0,x1,inslope,y0,y1) > threshold )
645 res |= STM_THRESHOLD_NOMATCH;
646 else
647 res |= STM_THRESHOLD_MATCH;
648 }
649 }
650 }
651 else
652 {
653 if (ax == table->NX || ay == table->NY || by == -1 || bx == -1)
654 res = STM_THRESHOLD_NOMATCH;
655 else
656 {
657 stm_getVar(table,&x0,&x1,&y0,&y1,bx,ax,by,ay,0);
658 if ( stm_thresholdTest(x0,x1,outload,y0,y1) > threshold )
659 res = STM_THRESHOLD_NOMATCH;
660 else
661 {
662 stm_getVar(table,&x0,&x1,&y0,&y1,bx,ax,by,ay,1);
663 if ( stm_thresholdTest(x0,x1,inslope,y0,y1) > threshold )
664 res = STM_THRESHOLD_NOMATCH;
665 else
666 {
667 stm_getVar(table,&x0,&x1,&y0,&y1,bx,ax,by,ay,2);
668 if ( stm_thresholdTest(x0,x1,outload,y0,y1) > threshold )
669 res = STM_THRESHOLD_NOMATCH;
670 else
671 {
672 stm_getVar(table,&x0,&x1,&y0,&y1,bx,ax,by,ay,3);
673 if ( stm_thresholdTest(x0,x1,inslope,y0,y1) > threshold )
674 res = STM_THRESHOLD_NOMATCH;
675 else
676 res |= STM_THRESHOLD_MATCH;
677 }
678 }
679 }
680 }
681 }
682 }
683 else
684 res = STM_THRESHOLD_NOMATCH;
685
686 #ifdef _PRINT
687 printf("test res = %x\n",res);
688 #endif
689 return res;
690 }
691
692 /*}}}************************************************************************/
693 /*{{{ stm_getVar() */
694 /* */
695 /* */
696 /****************************************************************************/
697 static void stm_getVar(timing_table *table, double *x0, double *x1,
698 double *y0, double *y1, int bx, int ax, int by,
699 int ay, int mode)
700 {
701 switch (mode)
702 {
703 case 0 :
704 *x0 = table->YRANGE[by];
705 *x1 = table->YRANGE[ay];
706 *y0 = table->SET2D[bx][by];
707 *y1 = table->SET2D[bx][ay];
708 break;
709 case 1 :
710 *x0 = table->XRANGE[bx];
711 *x1 = table->XRANGE[ax];
712 *y0 = table->SET2D[bx][by];
713 *y1 = table->SET2D[ax][by];
714 break;
715 case 2 :
716 *x0 = table->YRANGE[by];
717 *x1 = table->YRANGE[ay];
718 *y0 = table->SET2D[ax][by];
719 *y1 = table->SET2D[ax][ay];
720 break;
721 case 3 :
722 *x0 = table->XRANGE[bx];
723 *x1 = table->XRANGE[ax];
724 *y0 = table->SET2D[bx][ay];
725 *y1 = table->SET2D[ax][ay];
726 break;
727 }
728 }
729
730 /*}}}************************************************************************/
731 /*{{{ stm_thresholdTest() */
732 /* */
733 /* */
734 /****************************************************************************/
735 static double stm_thresholdTest(double x0, double x1, double x,
736 double y0, double y1)
737 {
738 double res, angle,X0 , Y0, X, Y, a;
739
740 if (y0 == STM_NOVALUE || y1 == STM_NOVALUE)
741 return STM_NOVALUE;
742 else if (y0 == y1)
743 return 0.0;
744 else
745 {
746 X0 = x0/x1;
747 Y0 = y0/y1;
748 a = (1-Y0)/(1-X0);
749 angle = atan(a)/(M_PI/2);
750 Y = log(pow(angle,2));
751 X = (2*(x-x0)/(x1-x0) - 1) * Y;
752 res = exp(-pow(X,2)) * 100 * sqrt(angle);
753 #ifdef _PRINT
754 printf("angle : %4.2f° ",angle*90);
755 printf("threshold : %4.2f%%\n",res);
756 #endif
757 return res;
758 }
759 }
760
761 /*}}}************************************************************************/
762 /*{{{ stm_getBeforeAndAfter() */
763 /* */
764 /* */
765 /****************************************************************************/
766 static int stm_getBeforeAndAfter(float *range, int max, double value,
767 int *before, int *after)
768 {
769 int i, res = 0;
770
771 *before = -1;
772 *after = -1;
773
774 for (i = 0; i < max ; i ++)
775 {
776 if (isInf(value,range[i]))
777 break;
778 *before = i;
779 if ((res = isEqual(range[i],value)))
780 break;
781 }
782 *after = i;
783
784 #ifdef _PRINT
785 printf("value %g, before %d %g, after %d %g %s\n",value,
786 *before,range[*before],*after,range[*after],(res)?"OK":"NOT OK");
787 #endif
788
789 return res;
790 }
791
792 /*}}}************************************************************************/
793 /*{{{ stm_storeInTable() */
794 /* */
795 /* */
796 /****************************************************************************/
797 static void stm_storeInTable(timing_table **curtable, double inslope,
798 double outload, double delay, int mode)
799 {
800 timing_table *restable, *table;
801 int i, j, x, y, dx, dy;
802 char type = 0;
803
804 table = *curtable;
805
806 /*
807 if (table == CURRENT->SLOPE)
808 {
809 printf("before adding------------------------------------------------\n");
810 stm_displayTable(table);
811 }
812 */
813 if (mode == STM_THRESHOLD_MATCH_XY)
814 {
815 x = stm_findIndex(table->XRANGE,inslope, table->NX);
816 y = stm_findIndex(table->YRANGE,outload, table->NY);
817 table->SET2D[x][y] = delay;
818 type = 'M';
819 restable = table;
820 // stm_fillTbl(restable,x,y,type);
821 }
822 else if (table)
823 {
824 switch (mode)
825 {
826 case STM_THRESHOLD_MATCH_X :
827 restable = stm_modtbl_create(table->NX,table->NY + 1,
828 STM_INPUT_SLEW,STM_LOAD);
829 x = stm_findIndex(table->XRANGE,inslope, table->NX);
830 y = stm_copyRangeAndInsert(table->YRANGE, restable->YRANGE,
831 outload,restable->NY);
832 type = 'Y';
833 restable->XRANGE = table->XRANGE;
834 table->XRANGE = NULL;
835 break;
836 case STM_THRESHOLD_MATCH_Y :
837 restable = stm_modtbl_create(table->NX + 1,table->NY,
838 STM_INPUT_SLEW,STM_LOAD);
839 x = stm_copyRangeAndInsert(table->XRANGE, restable->XRANGE,
840 inslope,restable->NX);
841 y = stm_findIndex(table->YRANGE,outload, table->NY);
842 type = 'X';
843 restable->YRANGE = table->YRANGE;
844 table->YRANGE = NULL;
845 break;
846 default :
847 restable = stm_modtbl_create(table->NX + 1,table->NY + 1,
848 STM_INPUT_SLEW,STM_LOAD);
849 x = stm_copyRangeAndInsert(table->XRANGE,
850 restable->XRANGE,
851 inslope,restable->NX);
852 y = stm_copyRangeAndInsert(table->YRANGE,
853 restable->YRANGE,
854 outload,restable->NY);
855 type = 'N';
856 break;
857 }
858 dx = 0;
859 dy = 0;
860 for (j = 0; j < restable->NY; j ++)
861 {
862 dx = 0;
863 if (j == y && mode != STM_THRESHOLD_MATCH_Y)
864 {
865 dy = 1;
866 continue;
867 }
868 for (i = 0; i < restable->NX; i ++)
869 {
870 if (i == x && mode != STM_THRESHOLD_MATCH_X)
871 {
872 dx = 1;
873 continue;
874 }
875 restable->SET2D[i][j] = table->SET2D[i - dx][j - dy];
876 }
877 }
878 restable->SET2D[x][y] = delay;
879 // stm_fillTbl(restable,x,y,type);
880 stm_modtbl_destroy(table);
881 }
882 else
883 {
884 restable = stm_modtbl_create(STM_CACHE_SIZE,STM_CACHE_SIZE,
885 STM_INPUT_SLEW,STM_LOAD);
886 stm_modtbl_setXrangeval(restable,0,inslope);
887 stm_modtbl_setYrangeval(restable,0,outload);
888 stm_modtbl_set2Dval(restable,0,0,delay);
889 }
890 *curtable = restable;
891
892 /*
893 if (table == CURRENT->SLOPE)
894 {
895 printf("after complete\n");
896 stm_displayTable(restable);
897 printf("-------------------------------------------------------------\n");
898 }
899 */
900 }
901
902 /*}}}************************************************************************/
903 /*{{{ stm_findIndex() */
904 /* */
905 /* */
906 /****************************************************************************/
907 static int stm_findIndex(float *range, double value, int size)
908 {
909 int i;
910
911 for (i = 0; i < size; i ++)
912 if (isEqual(range[i],value))
913 return i;
914
915 return -1;
916 }
917
918 /*}}}************************************************************************/
919 /*{{{ stm_copyRangeAndInsert() */
920 /* */
921 /* return index of new value */
922 /* */
923 /****************************************************************************/
924 static int stm_copyRangeAndInsert(float *range, float *new, double value,
925 int size)
926 {
927 int i, res;
928
929 for (i = 0; i < size-1 && range[i] < value; i ++)
930 new[i] = range[i];
931 new[i] = value;
932 res = i;
933 for (i = res + 1; i < size; i ++)
934 new[i] = range[i-1];
935
936 return res;
937 }
938
939 /*}}}************************************************************************/
940 /*{{{ stm_getarcdef() */
941 /* */
942 /* */
943 /****************************************************************************/
944 static char *stm_getarcdef(char *ins, char *local)
945 {
946 char temp[1024];
947
948 sprintf(temp,"%s.%s",ins, local);
949
950 return namealloc(temp);
951 }
952
953 /*}}}************************************************************************/
954 /*{{{ stm_gettimingfunction_and_signalcapa() */
955 /* */
956 /* */
957 /****************************************************************************/
958 static int stm_gettimingfunction_and_signalcapa(char *output,
959 timing_function **tf,
960 double *capa)
961 {
962 timing_function *fct;
963 char *modelname;
964 timing_model *tmodel;
965 losig_list *ls;
966
967 fct = stm_get_current_arc();
968 modelname = stm_getarcdef(fct->INS, fct->LOCALNAME);
969
970 tmodel = stm_getmodel (LATEST_GNS_RUN->FIGNAME, modelname);
971 if (tmodel == NULL)
972 {
973 avt_errmsg(STM_API_ERRMSG, "001", AVT_ERROR, modelname);
974 //fprintf(stderr,"stm model '%s' does not exist\n",modelname);
975 return -1;
976 }
977 if (tmodel->UTYPE != STM_MOD_MODFCT)
978 {
979 avt_errmsg(STM_API_ERRMSG, "002", AVT_ERROR, modelname);
980 // fprintf(stderr,"stm model '%s' is not a function\n",modelname);
981 return -1;
982 }
983 *tf = tmodel->UMODEL.FUNCTION;
984 ls = gen_corresp_sig(gen_makesignalname(output),CUR_CORRESP_TABLE);
985 if (ls == NULL)
986 {
987 *capa = 0.0;
988 return 1;
989 }
990 if (ls->PRCN != NULL)
991 *capa = ls->PRCN->RCCAPA*1e3;
992 else
993 *capa = 0.0;
994
995 return 0;
996 }
997
998 /*}}}************************************************************************/
999 /*{{{ Filling tables utilities */
1000 /****************************************************************************/
1001 /*{{{ stm_fillTbl() */
1002 /* */
1003 /* */
1004 /****************************************************************************/
1005 static void stm_fillTbl(timing_table *tbl, int xind, int yind, char type)
1006 {
1007 int beg, end, up ,down;
1008
1009 switch (type)
1010 {
1011 case 'X' :
1012 stm_fillFindLeftnRight(tbl,xind,yind,&beg,&end);
1013 stm_fillLine(tbl,beg,xind,yind);
1014 stm_fillLine(tbl,xind,end,yind);
1015 stm_fillNewCol(tbl,xind);
1016 break;
1017 case 'Y' :
1018 stm_fillFindUpnDown(tbl,xind,yind,&up,&down);
1019 stm_fillCol(tbl,up,yind,xind);
1020 stm_fillCol(tbl,yind,down,xind);
1021 stm_fillNewLine(tbl,yind);
1022 break;
1023 case 'N' : // New
1024 stm_fillNewCol(tbl,xind);
1025 stm_fillNewLine(tbl,yind);
1026 break;
1027 case 'M' : // Match
1028 stm_fillFindLeftnRight(tbl,xind,yind,&beg,&end);
1029 stm_fillLine(tbl,beg,xind,yind);
1030 stm_fillLine(tbl,xind,end,yind);
1031 stm_fillFindUpnDown(tbl,xind,yind,&up,&down);
1032 stm_fillCol(tbl,up,yind,xind);
1033 stm_fillCol(tbl,yind,down,xind);
1034 break;
1035 }
1036 }
1037
1038 /*}}}************************************************************************/
1039 /*{{{ stm_fillFindUpnDown() */
1040 /* */
1041 /* */
1042 /****************************************************************************/
1043 static void stm_fillFindUpnDown(timing_table *tbl, int xind, int yind,
1044 int *up, int *down)
1045 {
1046 int i;
1047
1048 *up = -1;
1049 *down = -1;
1050 for (i = 0; i < tbl->NY; i ++)
1051 if (tbl->SET2D[xind][i] != STM_NOVALUE)
1052 {
1053 if (i < yind)
1054 *up = i;
1055 else if (i > yind)
1056 {
1057 *down = i;
1058 break;
1059 }
1060 }
1061 }
1062
1063 /*}}}************************************************************************/
1064 /*{{{ stm_fillCol() */
1065 /* */
1066 /* fill a line like this : X */
1067 /* . */
1068 /* . */
1069 /* X */
1070 /* */
1071 /****************************************************************************/
1072 static void stm_fillCol(timing_table *tbl, int up, int down, int xind)
1073 {
1074 if (up != -1 && down != -1)
1075 {
1076 float x0, x1, y0, y1, x;
1077 int i;
1078
1079 x0 = tbl->YRANGE[up];
1080 y0 = tbl->SET2D[xind][up];
1081 x1 = tbl->YRANGE[down];
1082 y1 = tbl->SET2D[xind][down];
1083 for (i = up; i < down; i ++)
1084 {
1085 x = tbl->YRANGE[i];
1086 if (stm_thresholdTest(x0,x1,x,y0,y1) < THRESHOLD)
1087 tbl->SET2D[xind][i] = stm_modtbl_interpol1DCalc(x0,x1,y0,y1,x);
1088 }
1089
1090 }
1091 }
1092
1093 /*}}}************************************************************************/
1094 /*{{{ stm_fillNewLine() */
1095 /* */
1096 /* fill a new column like this : XXX */
1097 /* ... */
1098 /* XXX */
1099 /* */
1100 /****************************************************************************/
1101 static void stm_fillNewLine(timing_table *tbl,int yind)
1102 {
1103 if (yind != 0 && yind != tbl->NY-1)
1104 {
1105 float x0, x1, y0, y1, x;
1106 int i;
1107
1108 for (i = 0; i < tbl->NX; i ++)
1109 if ( tbl->SET2D[i][yind-1] != STM_NOVALUE
1110 && tbl->SET2D[i][yind+1] != STM_NOVALUE)
1111 {
1112 x0 = tbl->YRANGE[yind-1];
1113 y0 = tbl->SET2D[i][yind-1];
1114 x1 = tbl->YRANGE[yind+1];
1115 y1 = tbl->SET2D[i][yind+1];
1116 x = tbl->YRANGE[i];
1117 if (stm_thresholdTest(x0,x1,x,y0,y1) < THRESHOLD)
1118 tbl->SET2D[i][yind] = stm_modtbl_interpol1DCalc(x0,x1,y0,y1,x);
1119 }
1120 }
1121 }
1122
1123 /*}}}************************************************************************/
1124 /*{{{ stm_fillFindLeftnRight() */
1125 /* */
1126 /* */
1127 /****************************************************************************/
1128 static void stm_fillFindLeftnRight(timing_table *tbl, int xind, int yind,
1129 int *beg, int *end)
1130 {
1131 int i;
1132
1133 *beg = -1;
1134 *end = -1;
1135 for (i = 0; i < tbl->NX; i ++)
1136 if (tbl->SET2D[i][yind] != STM_NOVALUE)
1137 {
1138 if (i < xind)
1139 *beg = i;
1140 else if (i > xind)
1141 {
1142 *end = i;
1143 break;
1144 }
1145 }
1146 }
1147
1148 /*}}}************************************************************************/
1149 /*{{{ stm_fillLine() */
1150 /* */
1151 /* fill a line like this : X.....X */
1152 /* */
1153 /****************************************************************************/
1154 static void stm_fillLine(timing_table *tbl, int beg, int end, int yind)
1155 {
1156 if (beg != -1 && end != -1)
1157 {
1158 float x0, x1, y0, y1, x;
1159 int i;
1160
1161 x0 = tbl->XRANGE[beg];
1162 y0 = tbl->SET2D[beg][yind];
1163 x1 = tbl->XRANGE[end];
1164 y1 = tbl->SET2D[end][yind];
1165 for (i = beg; i < end; i ++)
1166 {
1167 x = tbl->XRANGE[i];
1168 if (stm_thresholdTest(x0,x1,x,y0,y1) < THRESHOLD)
1169 tbl->SET2D[i][yind] = stm_modtbl_interpol1DCalc(x0,x1,y0,y1,x);
1170 }
1171
1172 }
1173 }
1174
1175 /*}}}************************************************************************/
1176 /*{{{ stm_fillNewCol() */
1177 /* */
1178 /* fill a new column like this : X.X */
1179 /* X.X */
1180 /* */
1181 /****************************************************************************/
1182 static void stm_fillNewCol(timing_table *tbl,int xind)
1183 {
1184 if (xind != 0 && xind != tbl->NX-1)
1185 {
1186 float x0, x1, y0, y1, x;
1187 int i;
1188
1189 for (i = 0; i < tbl->NY; i ++)
1190 if ( tbl->SET2D[xind-1][i] != STM_NOVALUE
1191 && tbl->SET2D[xind+1][i] != STM_NOVALUE)
1192 {
1193 x0 = tbl->XRANGE[xind-1];
1194 y0 = tbl->SET2D[xind-1][i];
1195 x1 = tbl->XRANGE[xind+1];
1196 y1 = tbl->SET2D[xind+1][i];
1197 x = tbl->XRANGE[i];
1198 if (stm_thresholdTest(x0,x1,x,y0,y1) < THRESHOLD)
1199 tbl->SET2D[xind][i] = stm_modtbl_interpol1DCalc(x0,x1,y0,y1,x);
1200 }
1201 }
1202 }
1203
1204 /*}}}************************************************************************/
1205 /*}}}************************************************************************/
1206 /*}}}************************************************************************/
1207 /*{{{ stm_displayRange() */
1208 /* */
1209 /* */
1210 /****************************************************************************/
1211 void stm_displayRange(timing_table *table)
1212 {
1213 if (table)
1214 {
1215 int i, j, k, nb = 8, x;
1216
1217 for (k = 0; k <= (table->NX)/nb ; k ++)
1218 {
1219 x = k*nb + ((k < (table->NX)/nb) ? nb : (table->NX - k*nb)%nb);
1220 printf("| delay |");
1221 for (i = k*nb; i < x; i ++)
1222 printf(" %+e",table->XRANGE[i]);
1223 printf("\n");
1224
1225 printf("| capa |");
1226 for (j = 0; j < table->NY; j ++)
1227 printf(" %+e",table->YRANGE[j]);
1228 printf("\n");
1229 }
1230 }
1231 }
1232
1233 /*}}}************************************************************************/
1234 /*{{{ stm_test_threshold() */
1235 /* */
1236 /* */
1237 /****************************************************************************/
1238 void stm_test_threshold()
1239 {
1240 double res, y, x0, x1, y0, y1, x, X, Y, nb;
1241 FILE *f;
1242
1243 f = fopen("plot.dat","wt");
1244 x0 = 0;
1245 x1 = 100;
1246 y0 = 0;
1247 y1 = 90;
1248 nb = 50;
1249
1250 for (y = y0; y <= y1; y += (y1-y0)/nb)
1251 {
1252 for (x = x0; x <= x1; x += (x1-x0)/nb)
1253 {
1254 Y = y/90;
1255 // Y = log(pow(Y,(1.0-1/y)));
1256 Y = log(pow(Y,2));
1257 X = (2*(x-x0)/(x1-x0) - 1);
1258 X = X*Y;
1259 res = exp(-pow(X,2)) * 100 * pow(y/90,1.0/3);
1260 // fprintf(f,"%4.3g %4.1f %7.2f\n",x,y,res);
1261 // fprintf(f,"\n");
1262 }
1263 fprintf(f,"\n");
1264 }
1265 EXIT(0);
1266
1267 }
1268
1269 /*}}}************************************************************************/
1270 /*{{{ Math Function */
1271 /****************************************************************************/
1272 /*{{{ stm_arround() */
1273 /* */
1274 /* */
1275 /****************************************************************************/
1276 double stm_arround(double a, double pres)
1277 {
1278 double res;
1279 long cut;
1280
1281 res = a / pres;
1282 cut = (long)(res + 0.5);
1283 res = cut * pres;
1284
1285 return res;
1286 }
1287
1288 /*}}}************************************************************************/
1289 /*{{{ isEqual() */
1290 /* */
1291 /* */
1292 /****************************************************************************/
1293 static int isEqual(float a, float b)
1294 {
1295 if (b == 0)
1296 if (a == 0)
1297 return 1;
1298 else
1299 return ( fabs((b/a) - 1) < STM_ACCURACY);
1300 else
1301 return ( fabs((a/b) - 1) < STM_ACCURACY);
1302 }
1303
1304 /*}}}************************************************************************/
1305 /*{{{ isInf() */
1306 /* */
1307 /* */
1308 /****************************************************************************/
1309 static int isInf(float a, float b)
1310 {
1311 if (isEqual(a,b))
1312 return 0;
1313 else
1314 return a < b;
1315 }
1316
1317 /*}}}************************************************************************/
1318 /*}}}************************************************************************/