Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / api / stb / stb_API_display.c
1 #include MUT_H
2 #include MLO_H
3 #include MLU_H
4 #include RCN_H
5 #include MSL_H
6 #include AVT_H
7 #include INF_H
8 #include ELP_H
9 #include CNS_H
10 #include YAG_H
11 #include TLC_H
12 #include TRC_H
13 #include STM_H
14 #include TTV_H
15 #include MCC_H
16 #include SIM_H
17 #include TAS_H
18 #include FCL_H
19 #include BEH_H
20 #include CBH_H
21 #include LIB_H
22 #include TLF_H
23 #include STB_H
24
25 #define API_USE_REAL_TYPES
26
27 #include "../ttv/ttv_API_LOCAL.h"
28 #include "ttv_API.h"
29 #include "../ttv/ttv_API_display.h"
30 #include "../ttv/ttv_API_util.h"
31 #include "stb_LOCAL.h"
32 #include "stb_API.h"
33
34 #define DEC " "
35 #define DEC0 " "
36
37 static char *
38 vecname(char *name)
39 {
40 return mbk_vect(mbk_decodeanyvector(name), '[', ']');
41 }
42
43
44 static char dirconv(char dir)
45 {
46 if (dir=='u') return 'R';
47 else if (dir=='d') return 'F';
48 exit(5);
49 }
50
51 static void stb_get_path_info(ttvsig_list *tvs, int setup, ttvsig_list **start, ttvsig_list **latch)
52 {
53 ttvsig_list *inssig;
54 chain_list *list;
55 ttvpath_list *pth;
56 stbdebug_list *max;
57 double val;
58 long lastmode;
59 SH_info shi;
60 char search[4];
61
62 *latch=*start=NULL;
63 lastmode=stbsetdebugflag(STB_DIFFERENTIATE_INPUT_EVENTS);
64
65 val=getsetuphold(tvs,setup,2,NULL, NULL, NULL, &shi);
66 max=shi.dbl;
67 /*
68 if (setup)
69 val=___findworst(tvs, &max, stb_GetSetup);
70 else
71 val=___findworst(tvs, &max, stb_GetHold);
72 */
73 if (max!=NULL)
74 {
75 inssig=stb_GetPathInputSignal(max);
76
77 sprintf(search, "?%c", shi.latch_event);
78 ttv_activate_path_and_access_mode(1);
79 if (setup) list=ttv_internal_GetAccess(inssig, tvs, "*", search, 1); //max
80 else list=ttv_internal_GetAccess(inssig, tvs, "*", search, 0); // min
81 ttv_activate_path_and_access_mode(0);
82
83 list=ttv_internal_filterpathbycommand(list, max->CMD_EVENT, max->SIG1_EVENT, 1);
84
85 if (list!=NULL)
86 {
87 pth=(ttvpath_list *)list->DATA;
88 if (pth->LATCH!=NULL) *latch=pth->LATCH->ROOT;
89 *start=pth->NODE->ROOT;
90 }
91 ttv_FreePathList(list);
92 freechain(list);
93 }
94 stbsetdebugflag(lastmode);
95 }
96
97
98 void stb_DisplayErroneousSignals (FILE *f, chain_list *errorlist)
99 {
100 chain_list *ch;
101 ttvsig_list *sig, *start, *latch;
102 char *name, buf1[15];
103 double setup, hold;
104 int i, who=-1;
105 Board *b;
106
107 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayErroneousSignals");
108
109 if (f==NULL) return;
110
111 b=Board_CreateBoard();
112
113 Board_SetSize(b, COL_INDEX, 5, 'r');
114 _ttv_Board_SetSize(STAB_CONFIG_SHOW, COL_START, b, COL_START, 10, 'l');
115 _ttv_Board_SetSize(STAB_CONFIG_SHOW, COL_LATCH, b, COL_LATCH, 10, 'l');
116 _ttv_Board_SetSep(STAB_CONFIG_SHOW, COL_START, b, COL_ERRL_SEP0);
117 _ttv_Board_SetSep(STAB_CONFIG_SHOW, COL_LATCH, b, COL_ERRL_SEP1);
118 Board_SetSize(b, COL_NAME, 10, 'l');
119 Board_SetSize(b, COL_SETUP, 7, DISPLAY_number_justify);
120 Board_SetSize(b, COL_HOLD, 7, DISPLAY_number_justify);
121 Board_SetSep(b, COL_ERRL_SEP2);
122 Board_SetSep(b, COL_ERRL_SEP3);
123
124 Board_NewLine(b);
125 Board_SetValue(b, COL_NAME, "To Node");
126 sprintf(buf1,"Setup");
127 Board_SetValue(b, COL_SETUP, buf1);
128 sprintf(buf1,"Hold");
129 Board_SetValue(b, COL_HOLD, buf1);
130 _ttv_Board_SetValue(STAB_CONFIG_SHOW, COL_START, b, COL_START, "From node");
131 _ttv_Board_SetValue(STAB_CONFIG_SHOW, COL_LATCH, b, COL_LATCH, "Thru node");
132
133 Board_NewSeparation(b);
134
135 for (i=0,ch=errorlist ; ch ; ch=ch->NEXT, i++)
136 {
137 Board_NewLine(b);
138 sig = (ttvsig_list*)ch->DATA;
139 name = ttv_GetFullSignalName_COND (ttv_GetSignalTopTimingFigure(sig), sig);
140 setup = __stb_GetSignalSetup(sig, '?'); //stb_GetErroneousSignalSetup (sig);
141 hold = __stb_GetSignalHold(sig, '?'); //stb_GetErroneousSignalHold (sig);
142
143 sprintf(buf1,"%d",i+1);
144 Board_SetValue(b, COL_INDEX, buf1);
145
146 if (setup==-1) strcpy(buf1,"none"); else sprintf(buf1,DISPLAY_time_format,setup*DISPLAY_time_unit);
147 Board_SetValue(b, COL_SETUP, buf1);
148
149 if (hold==-1) strcpy(buf1,"none"); else sprintf(buf1,DISPLAY_time_format,hold*DISPLAY_time_unit);
150 Board_SetValue(b, COL_HOLD, buf1);
151
152 Board_SetValue(b, COL_NAME, name);
153
154 if (setup==-1) { if (hold!=-1) who=0; }
155 else if (hold==-1) { if (setup!=-1) who=1; }
156 else if (setup!=-1 && hold!=-1) { if (hold<setup) who=0; else who=1; }
157
158 if (who!=-1 && (STAB_CONFIG_SHOW[COL_START] || STAB_CONFIG_SHOW[COL_LATCH]))
159 {
160 stb_get_path_info(sig, who, &start, &latch);
161 _ttv_Board_SetValue(STAB_CONFIG_SHOW, COL_START, b, COL_START, ttv_GetFullSignalName_COND (ttv_GetSignalTopTimingFigure(start), start));
162 if (latch!=NULL)
163 _ttv_Board_SetValue(STAB_CONFIG_SHOW, COL_LATCH, b, COL_LATCH, ttv_GetFullSignalName_COND (ttv_GetSignalTopTimingFigure(latch), latch));
164 }
165 }
166
167 Board_NewSeparation(b);
168
169 avt_fprintf(f, " *** Error report (unit:[%s]) ***\n\n", DISPLAY_time_string);
170
171 Board_Display(f, b, "");
172 Board_FreeBoard(b);
173
174 avt_fprintf(f, "\n");
175 }
176
177 void stb_DisplayErrorList (FILE *f, stbfig_list *stbfig, double margin, int nberror)
178 {
179 long minsetup ;
180 long minhold ;
181 int errnum;
182 chain_list *errlist;
183
184 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayErrorList");
185 if (stbfig==NULL) return;
186
187 if (margin>1e-3) margin=1e-3;
188 margin*=TTV_UNIT;
189 errlist = stb_geterrorlist (stbfig, (long)(margin*1e12), nberror, &minsetup, &minhold, &errnum);
190 stb_DisplayErroneousSignals (f, errlist);
191 freechain(errlist);
192 }
193
194
195
196 static void stb_DisplayRanges (FILE *f, chain_list *ranges, double period)
197 {
198 chain_list *ch;
199 double start, end;
200 char buf[20], buf1[20];
201
202 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayRanges");
203 if (f==NULL) return;
204
205 for (ch=ranges ; ch ; ch=ch->NEXT) {
206 start = stb_GetInstabilityRangeStart((stbpair_list*)ch->DATA);
207 /* while (start < 0)
208 start += period;*/
209 end = stb_GetInstabilityRangeEnd((stbpair_list*)ch->DATA);
210 /* while (end < 0)
211 end += period;*/
212 fprintf (f, "___[%s %s]___", FormaT(start*DISPLAY_time_unit, buf, DISPLAY_time_format), FormaT(end*DISPLAY_time_unit, buf1, DISPLAY_time_format));
213 }
214 }
215
216 void stb_DisplayInputInstabilityRanges (FILE *f, stbdebug_list *input)
217 {
218 chain_list *range;
219 double period;
220 ttvsig_list *sg;
221
222 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayInputInstabilityRanges");
223 if (f==NULL) return;
224
225 period = stb_GetClockPeriod (input);
226 range = stb_GetInputInstabilityRanges(input, 'm');
227 sg=stb_GetPathInputSignal(input);
228 fprintf (f, DEC"Input (%s) : ", ttv_GetFullSignalName_COND (ttv_GetSignalTopTimingFigure(sg), sg));
229 stb_DisplayRanges (f, range, period);
230 freechain (range);
231 fprintf (f, "\n");
232 }
233
234 void stb_DisplayOutputInstabilityRanges (FILE *f, stbdebug_list *input)
235 {
236 chain_list *range;
237 double period;
238 ttvsig_list *sg;
239
240 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayOutputInstabilityRanges");
241 if (f==NULL) return;
242
243 period = stb_GetClockPeriod (input);
244 range = stb_GetOutputInstabilityRanges (input, 'm');
245 sg=stb_GetPathOutputSignal(input);
246 fprintf (f, DEC"Output (%s) : ", ttv_GetFullSignalName_COND (ttv_GetSignalTopTimingFigure(sg), sg));
247 stb_DisplayRanges (f, range, period);
248 freechain (range);
249 fprintf (f, "\n");
250 }
251
252 void stb_DisplayClock (FILE *f, stbdebug_list *input, int clock)
253 {
254 double ckup_time, ckdn_time, ckup_delta, ckdn_delta;
255 char buf[20], buf1[20];
256
257 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayClock");
258 if (f==NULL) return;
259
260 ckup_time = stb_GetClockTime (input, clock, 'u');
261 ckdn_time = stb_GetClockTime (input, clock, 'd');
262 if ((ckup_time==-1)||(ckdn_time==-1))
263 return;
264 ckup_delta = stb_GetClockDelta (input, clock, 'u');
265 ckdn_delta = stb_GetClockDelta (input, clock, 'd');
266
267 switch (clock) {
268 case INPUT_CLOCK : fprintf (f, DEC0"input clock : "); break;
269 case OUTPUT_CLOCK : fprintf (f, DEC0"output clock : "); break;
270 case MAIN_CLOCK : fprintf (f, DEC0"clock (%s) : ", stb_GetClockName (input)); break;
271 }
272
273 if (ckup_delta > 0)
274 fprintf (f, "RISE (%s:%s), ", FormaT(ckup_time*DISPLAY_time_unit, buf, DISPLAY_time_format), FormaT((ckup_time+ckup_delta)*DISPLAY_time_unit, buf1, DISPLAY_time_format));
275 else
276 fprintf (f, "RISE %s, ", FormaT(ckup_time*DISPLAY_time_unit, buf, DISPLAY_time_format));
277
278 if (ckdn_delta > 0)
279 fprintf (f, "FALL (%s:%s) ", FormaT(ckdn_time*DISPLAY_time_unit, buf, DISPLAY_time_format), FormaT((ckdn_time+ckdn_delta)*DISPLAY_time_unit, buf1, DISPLAY_time_format));
280 else
281 fprintf (f, "FALL %s ", FormaT(ckdn_time*DISPLAY_time_unit, buf, DISPLAY_time_format));
282
283
284 if (clock == MAIN_CLOCK)
285 fprintf (f, ", PERIOD = %s", FormaT(stb_GetClockPeriod (input)*DISPLAY_time_unit, buf, DISPLAY_time_format));
286
287 fprintf (f, "\n");
288 }
289
290 void stb_DisplayOutputSpecificationRanges (FILE *f, stbdebug_list *input)
291 {
292 chain_list *range;
293 double period;
294
295 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayOutputSpecificationRanges");
296 if (f==NULL) return;
297
298 if ((range=stb_GetOutputSpecificationRanges (input, 'm'))) {
299 period = stb_GetClockPeriod (input);
300 fprintf (f, DEC"Specs : ");
301 stb_DisplayRanges (f, range, period);
302 freechain (range);
303 fprintf (f, "\n");
304 }
305 }
306
307 void stb_DisplayInfos (FILE *f, stbdebug_list *input)
308 {
309 double margin;
310 char buf[1024], *str;
311 double s;
312 ttvsig_list *isg, *osg;
313
314 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayInfos");
315 if (f==NULL) return;
316
317 if ((str = stb_GetCommandName (input)))
318 sprintf (buf, " (%s) ", str);
319 else
320 strcpy (buf," ");
321
322 isg=stb_GetPathInputSignal(input);
323 osg=stb_GetPathOutputSignal(input);
324 fprintf (f, "%s%s-> %s :", ttv_GetFullSignalName_COND (ttv_GetSignalTopTimingFigure(isg), isg), buf, ttv_GetFullSignalName_COND (ttv_GetSignalTopTimingFigure(osg), osg));
325 if ((s=stb_GetSetup (input))!=-1) fprintf (f, " setup = %s", FormaT(s*DISPLAY_time_unit, buf, DISPLAY_time_format));
326 if ((s=stb_GetHold (input))!=-1) fprintf (f, " hold = %s", FormaT(s*DISPLAY_time_unit, buf, DISPLAY_time_format));
327 if ((margin = stb_GetSetupMargin (input)) > 0)
328 fprintf (f, " setup margin = %s", FormaT(margin*DISPLAY_time_unit, buf, DISPLAY_time_format));
329 if ((margin = stb_GetHoldMargin (input)) > 0)
330 fprintf (f, " hold margin = %s", FormaT(margin*DISPLAY_time_unit, buf, DISPLAY_time_format));
331
332 fprintf (f, "\n");
333 }
334
335 void stb_DisplayInputInfos (FILE *f, stbdebug_list *input)
336 {
337 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayInputInfos");
338 stb_DisplayInfos (f, input);
339 stb_DisplayClock (f, input, MAIN_CLOCK);
340 stb_DisplayClock (f, input, INPUT_CLOCK);
341 stb_DisplayInputInstabilityRanges (f, input);
342 stb_DisplayClock (f, input, OUTPUT_CLOCK);
343 stb_DisplayOutputInstabilityRanges (f, input);
344 stb_DisplayOutputSpecificationRanges (f, input);
345 }
346
347
348 void stb_DisplaySetupTimeReport (FILE *f, stbdebug_list *max, char datadir)
349 {
350 double ckup_time, ckdn_time, ckup_delta, ckdn_delta, val=DBL_MAX, v, add;
351 double maxdd=-DBL_MAX;
352 chain_list *cl, *ch;
353 ttvsig_list *tvs;
354 char buf[20], buf1[20];
355 char *rise="RISE", *fall="FALL", *ckname;
356 stbnode *node;
357 stbfig_list *sb;
358 ttvfig_list *tvf;
359 ttvevent_list *tve;
360 int inverted=0;
361
362 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplaySetupTimeReport");
363 if (max==NULL || f==NULL) return;
364
365 tvs=stb_GetPathOutputSignal(max);
366
367 if ((val=stb_GetSetup(max))==-1) val=DBL_MAX; //val=___findworst(tvs, &max, stb_GetSetup);
368
369 cl=stb_GetOutputInstabilityRanges(max,'m');
370 for (ch=cl; ch!=NULL; ch=ch->NEXT)
371 {
372 v=stb_GetInstabilityRangeEnd((stbpair_list *)ch->DATA);
373 if (v>maxdd) { maxdd=v; }
374 }
375 freechain(cl);
376
377 if (maxdd==-DBL_MAX) return;
378
379 v=stb_GetClockPeriod (max);
380
381 ckup_time = stb_GetClockTime (max, MAIN_CLOCK, 'u');
382 ckdn_time = stb_GetClockTime (max, MAIN_CLOCK, 'd');
383
384 if (!(ckup_time==-1 || ckdn_time==-1))
385 {
386 ckup_time+=stb_periodmove('x', max);
387 ckdn_time+=stb_periodmove('x', max);
388 ckup_delta = stb_GetClockDelta (max, MAIN_CLOCK, 'u');
389 ckdn_delta = stb_GetClockDelta (max, MAIN_CLOCK, 'd');
390
391 avt_fprintf(f, DEC"CLOCK %-5s :", stb_GetClockName (max));
392 if (ckup_delta>0) avt_fprintf (f, " RISE = (%s:%s)", FormaT(ckup_time*DISPLAY_time_unit, buf, DISPLAY_time_format), FormaT((ckup_time+ckup_delta)*DISPLAY_time_unit, buf1, DISPLAY_time_format));
393 else avt_fprintf (f, " RISE = %s", FormaT(ckup_time*DISPLAY_time_unit, buf, DISPLAY_time_format));
394 if (ckdn_delta>0) avt_fprintf (f, " FALL = (%s:%s)", FormaT(ckdn_time*DISPLAY_time_unit, buf, DISPLAY_time_format), FormaT((ckdn_time+ckdn_delta)*DISPLAY_time_unit, buf1, DISPLAY_time_format));
395 else avt_fprintf (f, " FALL = %s", FormaT(ckdn_time*DISPLAY_time_unit, buf, DISPLAY_time_format));
396 avt_fprintf (f, " PERIOD = %s", FormaT(stb_GetClockPeriod(max)*DISPLAY_time_unit, buf, DISPLAY_time_format));
397 avt_fprintf(f,"\n");
398 }
399
400 ckup_time = stb_GetClockTime (max, OUTPUT_CLOCK, 'u');
401 ckdn_time = stb_GetClockTime (max, OUTPUT_CLOCK, 'd');
402
403 if (!(ckup_time==-1 || ckdn_time==-1))
404 {
405 ckup_time+=stb_periodmove('u', max);
406 ckdn_time+=stb_periodmove('d', max);
407 ckup_delta = stb_GetClockDelta (max, OUTPUT_CLOCK, 'u');
408 ckdn_delta = stb_GetClockDelta (max, OUTPUT_CLOCK, 'd');
409
410 if (max->CMD_EVENT!=NULL)
411 {
412 tvf=ttv_GetSignalTopTimingFigure(max->CMD_EVENT->ROOT);
413 if (datadir=='d') tve=stb_GetPathOutputSignal(max)->NODE;
414 else tve=stb_GetPathOutputSignal(max)->NODE+1;
415 ckname=ttv_GetFullSignalName_COND(tvf, max->CMD_EVENT->ROOT);
416 node=stb_getstbnode(tve);
417 if (node!=NULL)
418 {
419 sb= stb_getstbfig(tvf);
420 stb_getgoodclock_and_status(sb, node->CK, max->CMD_EVENT, tve, &inverted);
421 if (inverted) rise="FALL", fall="RISE";
422 }
423 }
424 else ckname="";
425 avt_fprintf(f, DEC"CLOCK %-5s :", ckname);
426 avt_fprintf (f, " %s = %s [MIN]", rise, FormaT(ckup_time*DISPLAY_time_unit, buf, DISPLAY_time_format));
427 avt_fprintf (f, " %s = %s [MIN]", fall, FormaT(ckdn_time*DISPLAY_time_unit, buf, DISPLAY_time_format));
428 avt_fprintf(f,"\n");
429 }
430
431 if (stb_GetSetupMargin(max)!=-1) add=stb_GetSetupMargin(max); else add=0;
432 avt_fprintf(f, DEC"DATA DELAY : %s [MAX]", FormaT((maxdd+add)*DISPLAY_time_unit, buf, DISPLAY_time_format));
433 if (add!=0)
434 avt_fprintf(f, " (%s + %s)", FormaT((maxdd)*DISPLAY_time_unit, buf1, DISPLAY_time_format), FormaT(add*DISPLAY_time_unit, buf, DISPLAY_time_format));
435 avt_fprintf(f, "\n");
436
437 if (val!=DBL_MAX)
438 avt_fprintf(f, DEC"SETUP : %s%s¤.\n", val<0?"¤6":"", FormaT(val*DISPLAY_time_unit, buf, DISPLAY_time_format));
439 else
440 avt_fprintf(f, DEC"SETUP : none\n");
441 }
442
443 void stb_DisplayHoldTimeReport (FILE *f, stbdebug_list *max, char datadir)
444 {
445 double ckup_time, ckdn_time, ckup_delta, ckdn_delta, val=DBL_MAX, v, sub;
446 double mindd=DBL_MAX;
447 chain_list *cl, *ch;
448 ttvsig_list *tvs;
449 char buf[20], buf1[20];
450 char *rise="RISE", *fall="FALL", *ckname;
451 stbnode *node;
452 stbfig_list *sb;
453 ttvfig_list *tvf;
454 ttvevent_list *tve;
455 int inverted=0;
456
457 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayHoldTimeReport");
458 if (max==NULL || f==NULL) return;
459
460 tvs=stb_GetPathOutputSignal(max);
461
462 if ((val=stb_GetHold(max))==-1) val=DBL_MAX; // val=___findworst(tvs, &max, stb_GetHold);
463
464 cl=stb_GetOutputInstabilityRanges(max, 'm');
465 for (ch=cl; ch!=NULL; ch=ch->NEXT)
466 {
467 v=stb_GetInstabilityRangeStart((stbpair_list *)ch->DATA);
468 if (v<mindd) { mindd=v; }
469 }
470 freechain(cl);
471
472 if (mindd==DBL_MAX) return;
473
474 v=stb_GetClockPeriod (max);
475
476 ckup_time = stb_GetClockTime (max, MAIN_CLOCK, 'u');
477 ckdn_time = stb_GetClockTime (max, MAIN_CLOCK, 'd');
478 if (!(ckup_time==-1 || ckdn_time==-1))
479 {
480 ckup_time+=-v+stb_periodmove('x', max);
481 ckdn_time+=-v+stb_periodmove('x', max);
482
483 ckup_delta = stb_GetClockDelta (max, MAIN_CLOCK, 'u');
484 ckdn_delta = stb_GetClockDelta (max, MAIN_CLOCK, 'd');
485
486 avt_fprintf(f, DEC"CLOCK %-5s :", stb_GetClockName (max));
487 if (ckup_delta>0) avt_fprintf (f, " RISE = (%s:%s)", FormaT(ckup_time*DISPLAY_time_unit, buf, DISPLAY_time_format), FormaT((ckup_time+ckup_delta)*DISPLAY_time_unit, buf1, DISPLAY_time_format));
488 else avt_fprintf (f, " RISE = %s", FormaT(ckup_time*DISPLAY_time_unit, buf, DISPLAY_time_format));
489 if (ckdn_delta>0) avt_fprintf (f, " FALL = (%s:%s)", FormaT(ckdn_time*DISPLAY_time_unit, buf, DISPLAY_time_format), FormaT((ckdn_time+ckdn_delta)*DISPLAY_time_unit, buf1, DISPLAY_time_format));
490 else avt_fprintf (f, " FALL = %s", FormaT(ckdn_time*DISPLAY_time_unit, buf, DISPLAY_time_format));
491 avt_fprintf (f, " PERIOD = %s", FormaT(stb_GetClockPeriod(max)*DISPLAY_time_unit, buf, DISPLAY_time_format));
492 avt_fprintf(f,"\n");
493 }
494
495 ckup_time = stb_GetClockTime (max, OUTPUT_CLOCK, 'u');
496 ckdn_time = stb_GetClockTime (max, OUTPUT_CLOCK, 'd');
497
498 if (!(ckup_time==-1 || ckdn_time==-1))
499 {
500 ckup_time+=-v+stb_periodmove('u', max);
501 ckdn_time+=-v+stb_periodmove('d', max);
502 ckup_delta = stb_GetClockDelta (max, OUTPUT_CLOCK, 'u');
503 ckdn_delta = stb_GetClockDelta (max, OUTPUT_CLOCK, 'd');
504
505 if (max->CMD_EVENT!=NULL)
506 {
507 tvf=ttv_GetSignalTopTimingFigure(max->CMD_EVENT->ROOT);
508 if (datadir=='d') tve=stb_GetPathOutputSignal(max)->NODE;
509 else tve=stb_GetPathOutputSignal(max)->NODE+1;
510 ckname=ttv_GetFullSignalName_COND(tvf, max->CMD_EVENT->ROOT);
511 node=stb_getstbnode(tve);
512 if (node!=NULL)
513 {
514 sb= stb_getstbfig(tvf);
515 stb_getgoodclock_and_status(sb, node->CK, max->CMD_EVENT, tve, &inverted);
516 if (inverted) rise="FALL", fall="RISE";
517 }
518 }
519 else ckname="";
520 avt_fprintf(f, DEC"CLOCK %-5s :", ckname);
521 avt_fprintf (f, " %s = %s [MAX]", rise, FormaT((ckup_time+ckup_delta)*DISPLAY_time_unit, buf, DISPLAY_time_format));
522 avt_fprintf (f, " %s = %s [MAX]", fall, FormaT((ckdn_time+ckdn_delta)*DISPLAY_time_unit, buf, DISPLAY_time_format));
523 avt_fprintf(f,"\n");
524 }
525
526 if (stb_GetHoldMargin(max)!=-1) sub=stb_GetHoldMargin(max); else sub=0;
527 avt_fprintf(f, DEC"DATA DELAY : %s [MIN]", FormaT((mindd-sub)*DISPLAY_time_unit, buf, DISPLAY_time_format));
528 if (sub!=0)
529 avt_fprintf(f, " (%s - %s)", FormaT(mindd*DISPLAY_time_unit, buf1, DISPLAY_time_format), FormaT(sub*DISPLAY_time_unit, buf, DISPLAY_time_format));
530 avt_fprintf(f, "\n");
531 if (val!=DBL_MAX)
532 avt_fprintf(f, DEC"HOLD : %s%s¤.\n", val<0?"¤6":"", FormaT(val*DISPLAY_time_unit, buf, DISPLAY_time_format));
533 else
534 avt_fprintf(f, DEC"HOLD : none\n");
535 }
536
537 void stb_DisplayClockRoute(FILE *f, stbdebug_list *max, char type)
538 {
539 ttvevent_list *tve;
540 ttvsig_list *tvs;
541
542 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayClockRoute");
543 type=tolower(type);
544 if (type!='s' && type!='h')
545 {
546 avt_errmsg(STB_API_ERRMSG, "005", AVT_ERROR);
547 //avt_fprintf(f, "valid values for type is 's' (setup) or 'h' (hold)");
548 return;
549 }
550
551 if (f==NULL) return;
552
553 tvs=stb_GetPathOutputSignal(max);
554
555 if (max->CMD_EVENT==NULL) {avt_fprintf(f, "¤6<no path to clock found, unknown command node>¤."); return; }
556
557 if (max->CMD_EVENT->TYPE & TTV_NODE_UP) tve=max->CMD_EVENT->ROOT->NODE;
558 else tve=max->CMD_EVENT->ROOT->NODE+1;
559
560 ttv_DisplayRoute(f, tve, type=='s'?'m':'M', NULL, 0);
561 }
562
563 void stb_DisplayDataRoute(FILE *f, stbdebug_list *max, char type, char datadir)
564 {
565 ttvsig_list *inssig, *tvs;
566 chain_list *cl, *list;
567 chain_list *detail, *detailbase;
568 ttvcritic_list *tc;
569 char *nodename, *col, *_type;
570 ttvpath_list *pth;
571 char search[4];
572
573 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplayDataRoute");
574 if (max==NULL || f==NULL) return;
575
576 type=tolower(type);
577
578 tvs=stb_GetPathOutputSignal(max);
579
580 if (type!='s' && type!='h')
581 {
582 max=NULL;
583 avt_errmsg(STB_API_ERRMSG, "005", AVT_ERROR);
584 // avt_fprintf(f, "valid values for type is 's' (setup) or 'h' (hold), ");
585 }
586
587 if (max!=NULL)
588 {
589 inssig=stb_GetPathInputSignal(max);
590
591 sprintf(search,"?%c",datadir);
592
593 ttv_activate_path_and_access_mode(1);
594 if (type=='s') list=ttv_internal_GetAccess(inssig, tvs, "*", search, 1); //max
595 else list=ttv_internal_GetAccess(inssig, tvs, "*", search, 0); // min
596 ttv_activate_path_and_access_mode(0);
597
598 list=ttv_internal_filterpathbycommand(list, max->CMD_EVENT, max->SIG1_EVENT, 1);
599
600 cl=list;
601
602 if (cl!=NULL)
603 {
604 pth=(ttvpath_list *)cl->DATA;
605 detailbase=detail=ttv_GetPathDetail(pth);
606 avt_fprintf(f, "(");
607 while (detail!=NULL)
608 {
609 tc=(ttvcritic_list *)detail->DATA;
610 if (detail==detailbase || !(DISPLAY_nodemode==0 && strcasecmp(ttv_GetDetailType(tc),"rc")==0))
611 {
612 if (detail!=detailbase) avt_fprintf(f, " - ");
613 nodename=ttv_GetDetailSignalName_COND(tc);
614
615 _type=ttv_GetDetailSignalType(tc);
616 if (strstr(_type,"latch")!=NULL || strstr(_type,"flip-flop")!=NULL) col="¤4";
617 else col="";
618 avt_fprintf(f, "%s%s¤.(%c)", col, nodename, dirconv(ttv_GetDetailDirection(tc)));
619 }
620 detail=detail->NEXT;
621 }
622 avt_fprintf(f, ")");
623
624 ttv_FreePathDetail(detailbase);
625 freechain(detailbase);
626 }
627 else
628 avt_fprintf(f, "¤6<access not found>¤.");
629 ttv_FreePathList(list);
630 freechain(list);
631 }
632 else avt_fprintf(f, "¤6<not found>¤.");
633 }
634
635
636 void stb_DisplaySignalStabilityReport (FILE *f, stbfig_list *stbfig, char *name)
637 {
638 stbdebug_list *max;
639 double val;
640 long lastmode;
641 SH_info shi;
642 ttvsig_list *tvs;
643
644 avt_errmsg(STB_API_ERRMSG, "007", AVT_WARNING, "stb_DisplaySignalStabilityReport");
645 if (!stbfig) return;
646
647 tvs = ttv_getsig(stbfig->FIG, vecname(name));
648
649 if (tvs==NULL || f==NULL) return;
650 lastmode=stbsetdebugflag(STB_DIFFERENTIATE_INPUT_EVENTS);
651
652 avt_fprintf(f,"¤2Signal '%s'¤. (unit:[%s])\n", ttv_GetFullSignalName_COND(ttv_GetSignalTopTimingFigure(tvs), tvs), DISPLAY_time_string);
653
654 val=getsetuphold(tvs,1,2,NULL, NULL, NULL, &shi);
655 max=shi.dbl;
656 // val=___findworst(tvs, &max, stb_GetSetup);
657 if (stb_GetSetup(max)==-1)
658 avt_fprintf(f," [¤+No Setup Time Available¤.]\n");
659 else if (val!=DBL_MAX && val>=0)
660 avt_fprintf(f," [Setup Time]\n");
661 else
662 avt_fprintf(f," [¤6Setup Time Error¤.]\n");
663
664 //display setup path
665 avt_fprintf(f, DEC0"Data route : ");
666 if (max!=NULL) { stb_DisplayDataRoute(f, max, 's', shi.latch_event); avt_fprintf(f, "\n"); }
667 avt_fprintf(f, DEC0"Closing Clock route : ");
668 if (max!=NULL) { stb_DisplayClockRoute(f, max, 's'); avt_fprintf(f, "\n"); }
669 avt_fprintf(f, "\n");
670 stb_DisplaySetupTimeReport (f, max, shi.latch_event);
671
672 avt_fprintf(f, "\n");
673
674 val=getsetuphold(tvs,0,2,NULL, NULL, NULL, &shi);
675 max=shi.dbl;
676 // val=___findworst(tvs, &max, stb_GetHold);
677 if (stb_GetHold(max)==-1)
678 avt_fprintf(f," [¤+No Hold Time Available¤.]\n");
679 else if (val!=DBL_MAX && val>=0)
680 avt_fprintf(f," [Hold Time]\n");
681 else
682 avt_fprintf(f," [¤6Hold Time Error¤.]\n");
683
684 //display hold path
685 avt_fprintf(f, DEC0"Data route : ");
686 if (max!=NULL) { stb_DisplayDataRoute(f, max, 'h', shi.latch_event); avt_fprintf(f, "\n"); }
687 avt_fprintf(f, DEC0"Closing Clock route : ");
688 if (max!=NULL) { stb_DisplayClockRoute(f, max, 'h'); avt_fprintf(f, "\n"); }
689 avt_fprintf(f, "\n");
690 stb_DisplayHoldTimeReport (f, max, shi.latch_event);
691 avt_fprintf(f, "\n");
692 stbsetdebugflag(lastmode);
693 }
694
695 static int isclock(ttvsig_list *ts)
696 {
697 if (getptype(ts->USER, TTV_SIG_CLOCK)!=NULL) return 1;
698 return 0;
699 }
700
701 void ttv_CheckTransformToIdeal(ttvpath_list * tp)
702 {
703 chain_list *cl, *ch;
704 long sub, subr;
705 ttvcritic_list *tc;
706 int latchideal=0, clockideal=0, mode=0;
707
708 if (tp==NULL) return;
709
710 if (tp->LATCH && getptype(tp->LATCH->ROOT->USER, STB_IDEAL_CLOCK)!=NULL) latchideal=1;
711 if (getptype(tp->NODE->ROOT->USER, STB_IDEAL_CLOCK)!=NULL) clockideal=1;
712
713 ch=cl=ttv_GetPathDetail(tp);
714 sub=subr=0;
715 while (cl!=NULL)
716 {
717 tc=(ttvcritic_list *)cl->DATA;
718 if (cl!=ch)
719 {
720 if (tc->NODE_FLAG & TTV_NODE_FLAG_ISLATCH_ACCESS)
721 {
722 if (!latchideal) break;
723 mode=1;
724 }
725 else if ((mode==0 && clockideal) || (mode==1 && latchideal))
726 {
727 sub+=tc->DELAY; tc->DELAY=0;
728 subr+=tc->REFDELAY; tc->REFDELAY=0;
729 if (tc->SIMDELAY!=TTV_NOTIME) tc->SIMDELAY=0;
730 }
731 }
732 cl=delchain(cl,cl);
733 }
734 freechain(cl);
735 tp->DELAY-=sub;
736 tp->REFDELAY-=subr;
737 //tp->USER=addptype(tp->USER, STB_IDEAL_CLOCK, NULL);
738 }
739
740
741 static char *typeconv(char *type)
742 {
743 if (strstr(type,"connector")!=NULL) return "S";
744 if (strstr(type,"latch")!=NULL) return "L";
745 if (strstr(type,"precharge")!=NULL) return "N";
746 if (strstr(type,"flip-flop")!=NULL) return "F";
747 if (strstr(type,"breakpoint")!=NULL) return "B";
748 if (strstr(type,"command")!=NULL) return "K";
749 return "";
750 }
751
752 static int slacksort(const void *a0, const void *b0)
753 {
754 int res;
755 slackinfo *a=(slackinfo *)a0, *b=(slackinfo *)b0;
756 if (a->slack<b->slack) return -1;
757 if (a->slack>b->slack) return 1;
758 if ((res=mbk_casestrcmp(a->debugl.SIG2->NAME, b->debugl.SIG2->NAME))<0) return -1;
759 else if (res>0) return 1;
760 else if ((res=mbk_casestrcmp(a->debugl.SIG1->NAME, b->debugl.SIG1->NAME))<0) return -1;
761 else if (res>0) return 1;
762 return 0;
763 }
764
765 static ttvevent_list *stb_getpathstart(ttvfig_list *tvf, ttvevent_list *inev, char *start, int dirin, int *access, unsigned char phase, ttvevent_list *startcmd, int notanaccess, ttvevent_list *startclock)
766 {
767 ttvevent_list *input=NULL, *testev;
768 stbck *ck;
769 stbnode *node;
770 int checkdir;
771 ptype_list *pt, *pt0;
772
773 if (notanaccess || (inev->ROOT->TYPE & (TTV_SIG_L|TTV_SIG_R|TTV_SIG_B))==0 || (startcmd==NULL && ttv_IsClock(inev->ROOT)))
774 {
775 *access=0;
776 if ((inev->TYPE & TTV_NODE_UP)==TTV_NODE_UP) checkdir=1;
777 else checkdir=0;
778 if ((dirin==2 || checkdir==dirin) && mbk_TestREGEX(ttv_GetFullSignalName(tvf, inev->ROOT), start))
779 input=inev;
780 }
781 else if ((inev->ROOT->TYPE & TTV_SIG_B)!=0)
782 {
783 pt=ttv_getlatchaccess(tvf, inev, TTV_FIND_MAX);
784 for (pt0=pt; pt0!=NULL; pt0=pt0->NEXT)
785 {
786 node=stb_getstbnode((ttvevent_list *)pt0->DATA);
787 testev=NULL;
788 ck=node->CK;
789 if (ck!=NULL)
790 {
791 if (ck->ORIGINAL_CLOCK!=NULL) testev=ck->ORIGINAL_CLOCK;
792 else if (stb_getclocknode(stb_getstbfig(tvf), ck->CKINDEX, NULL, &testev, NULL)==NULL)
793 testev=NULL;
794 }
795 if (testev!=NULL)
796 {
797 if ((testev->TYPE & TTV_NODE_UP)==TTV_NODE_UP) checkdir=1;
798 else checkdir=0;
799 if ((dirin==2 || checkdir==dirin) && mbk_TestREGEX(ttv_GetFullSignalName(tvf, testev->ROOT), start))
800 break;
801 }
802 }
803 freeptype(pt);
804 if (pt0!=NULL && testev!=NULL) input=testev, *access=1;
805 else input=inev, *access=0;
806 }
807 else
808 {
809 // recherche de la clock
810 *access=1;
811 if (startclock!=NULL && (inev->ROOT->TYPE & TTV_SIG_R)==0)
812 {
813 if ((startclock->TYPE & TTV_NODE_UP)==TTV_NODE_UP) checkdir=1;
814 else checkdir=0;
815 if ((dirin==2 || checkdir==dirin) && mbk_TestREGEX(ttv_GetFullSignalName(tvf, startclock->ROOT), start))
816 input=startclock;
817 else
818 input=NULL;
819 }
820 else
821 {
822 node=stb_getstbnode(inev);
823 for (ck=node->CK; ck!=NULL; ck=ck->NEXT)
824 {
825 if (phase!=STB_NO_INDEX && ck->CKINDEX!=phase) continue;
826 if (ck->ORIGINAL_CLOCK!=NULL)
827 testev=ck->ORIGINAL_CLOCK;
828 else if (stb_getclocknode(stb_getstbfig(tvf), ck->CKINDEX, NULL, &testev, NULL)==NULL)
829 testev=NULL;
830
831 if (testev!=NULL)
832 {
833 if ((testev->TYPE & TTV_NODE_UP)==TTV_NODE_UP) checkdir=1;
834 else checkdir=0;
835 if ((dirin==2 || checkdir==dirin) && mbk_TestREGEX(ttv_GetFullSignalName(tvf, testev->ROOT), start))
836 {
837 if ((ck->FLAGS & (STBCK_MAX_EDGE_HZ|STBCK_MIN_EDGE_HZ))!=0)
838 *access=0, testev=inev;
839 else if ((ck->FLAGS & (STBCK_FAKE_DOWN|STBCK_FAKE_UP))!=0)
840 {
841 ttvevent_list *tve;
842 if (ck->CMD!=NULL) tve=ck->CMD;
843 else
844 {
845 if ((pt=getptype(node->EVENT->USER, STB_BREAK_TEST_EVENT))!=NULL)
846 tve=(ttvevent_list *)pt->DATA;
847 else
848 tve=node->EVENT;
849 }
850 if ((inev->ROOT->TYPE & TTV_SIG_L)!=0 && (tve->TYPE & TTV_NODE_UP)!=(ck->ORIGINAL_CLOCK->TYPE & TTV_NODE_UP))
851 checkdir=(checkdir+1) & 1;
852 if ((checkdir==0 && (ck->FLAGS & STBCK_FAKE_DOWN)!=0)
853 || (checkdir==1 && (ck->FLAGS & STBCK_FAKE_UP)!=0))
854 *access=0, testev=inev;
855 }
856 break;
857 }
858 }
859 }
860 if (ck!=NULL)
861 input=testev;
862 }
863 }
864 return input;
865 }
866
867
868 static inline int stb_could_enter_range(ttvsig_list *tvs, int setuphold, double top, int nb, int max)
869 {
870 int i;
871 stbnode *ptnode;
872 double val;
873
874 if (!V_BOOL_TAB[__STB_SETUP_HOLD_UPDATE].VALUE) return 1;
875 if (nb<max) return 1;
876
877 for(i = 0 ; i < 2 ; i++)
878 {
879 if((ptnode = stb_getstbnode(tvs->NODE+i)) == NULL)
880 continue ;
881 val=-1;
882 if (setuphold && ptnode->SETUP!=STB_NO_TIME)
883 {
884 val=ptnode->SETUP*1e-12/TTV_UNIT;
885 }
886 else if (!setuphold && ptnode->HOLD!=STB_NO_TIME)
887 {
888 val=ptnode->HOLD*1e-12/TTV_UNIT;
889 }
890
891 if (val!=-1 && val<top) return 1;
892 }
893 return 0;
894 }
895
896 static int checkkeepslack(int flag, int forced)
897 {
898 if ((flag & STB_DEBUG_HZPATH)==0 && forced==TTV_API_ONLY_HZ) return 0;
899 if ((flag & STB_DEBUG_HZPATH)!=0 && forced==TTV_API_ONLY_NOTHZ) return 0;
900 return 1;
901 }
902
903 static chain_list *getslackinfo_grab(ttvfig_list *tvf, ttvsig_list *sig, int setup, char *start, char *end, int dirin, int dirout, double margin, chain_list *old, double *top, int *nb, int max, int forced, char *thru)
904 {
905 stbdebug_list *dbl, *savedbl;
906 double val, ckt;
907 char ckdir;
908 Setup_Hold_Computation_Detail_INFO *detail;
909 long d_req, d_valid;
910 ttvsig_list *inputsig;
911 ttvevent_list *path_start_sig;
912 slackinfo *si;
913 int access, i;
914 chain_list *lst, *ch;
915
916 if (!stb_could_enter_range(sig, setup, *top, *nb, max)) return old;
917
918 if (mbk_TestREGEX(ttv_GetFullSignalName(tvf, sig), end) || mbk_TestREGEX(ttv_GetFullSignalNetName(tvf, sig), end))
919 {
920 lst=stb_internal_GetSignalStabilityPaths(sig, setup?STB_COMPUTE_SETUP_ONLY:STB_COMPUTE_HOLD_ONLY);
921 for (ch=lst; ch!=NULL; ch=ch->NEXT)
922 {
923 dbl=(stbdebug_list *)ch->DATA;
924 for (i=0;i<2;i++)
925 {
926 if (dirout==2 || dirout==i)
927 {
928 if (setup) detail=&dbl->detail[i].setup;
929 else detail=&dbl->detail[i].hold;
930
931 val=detail->VALUE*1e-12/TTV_UNIT;
932 if (detail->VALUE!=STB_NO_TIME && val<=margin && (*nb<max || val<*top) && checkkeepslack(detail->flags, forced))
933 {
934 inputsig=dbl->SIG1;
935 if ((path_start_sig=stb_getpathstart(tvf, dbl->SIG1_EVENT, start, dirin, &access, detail->phase_origin, dbl->START_CMD_EVENT, 0, dbl->START_CLOCK))!=NULL)
936 {
937 if (thru==NULL
938 || (!access && (mbk_TestREGEX(ttv_GetFullSignalName(tvf, path_start_sig->ROOT), thru) || mbk_TestREGEX(ttv_GetFullSignalNetName(tvf, path_start_sig->ROOT), thru)))
939 || (access && (mbk_TestREGEX(ttv_GetFullSignalName(tvf, dbl->SIG1), thru) || mbk_TestREGEX(ttv_GetFullSignalNetName(tvf, dbl->SIG1), thru)))
940 )
941 {
942 d_valid=detail->instab+detail->data_margin;
943 if (setup)
944 d_req=detail->clock+detail->clock_margin-detail->margin+detail->skew-detail->uncertainty;
945 else
946 {
947 d_req=detail->clock+detail->clock_margin+detail->margin-detail->period-detail->skew+detail->uncertainty;
948 d_valid+=detail->misc;
949 }
950
951 // correction pour multicycle sur le required
952 /*d_valid+=detail->mc_setup_period-detail->mc_hold_period;
953 d_req+=detail->mc_setup_period-detail->mc_hold_period;*/
954 d_valid+=-detail->datamoved-detail->mc_hold_period;
955 d_req+=-detail->datamoved-detail->mc_hold_period;
956
957 if (!setup)
958 {
959 if (dbl->CKREFUP_MAX<dbl->CKREFDN_MAX)
960 ckt=(dbl->CKREFUP_MAX/TTV_UNIT)*1e-12, ckdir='u';
961 else
962 ckt=(dbl->CKREFDN_MAX/TTV_UNIT)*1e-12, ckdir='d';
963 }
964 else
965 {
966 if (dbl->CKREFUP_MIN<dbl->CKREFDN_MIN)
967 ckt=(dbl->CKREFUP_MIN/TTV_UNIT)*1e-12, ckdir='u';
968 else
969 ckt=(dbl->CKREFDN_MIN/TTV_UNIT)*1e-12, ckdir='d';
970 }
971
972 si=(slackinfo *)mbkalloc(sizeof(slackinfo));
973
974 si->slack=detail->VALUE*1e-12/TTV_UNIT;
975
976 si->datavalid=(d_valid/TTV_UNIT)*1e-12;
977 /* if ((detail->flags & STB_DEBUG_DIRECTIVE)==0)
978 {
979 if (dbl->CKREFUP_MAX==STB_NO_TIME)
980 si->datavalidclock=-1;
981 else
982 si->datavalidclock=ckt;
983 si->datavalidclockdir=ckdir;
984 }
985 else
986 {
987 si->datavalidclock=0; // a faire
988 si->datavalidclockdir='u';
989 }
990 */
991 if (dbl->PERIODE==STB_NO_TIME)
992 si->period=-1;
993 else
994 si->period=(dbl->PERIODE/TTV_UNIT)*1e-12;
995 si->datareq=(d_req/TTV_UNIT)*1e-12;
996 si->path=NULL;
997 si->dirout=i;
998 si->lag=(detail->lag/TTV_UNIT)*1e-12;
999 /* if (detail->flags & STB_DEBUG_DIRECTIVE_FALLING) si->dirin=0;
1000 else if (detail->flags & STB_DEBUG_DIRECTIVE_RISING) si->dirin=1;
1001 else */si->dirin=(path_start_sig->TYPE & TTV_NODE_UP)==TTV_NODE_UP?1:0;
1002 si->access=access;
1003 si->hzpath=(detail->flags & STB_DEBUG_HZPATH)!=0?1:0;
1004 si->phase=detail->phase_origin;
1005 si->flags=detail->flags;
1006 si->jump=1;
1007
1008 memcpy(savedbl=&si->debugl, dbl, sizeof(stbdebug_list));
1009
1010 /* if (savedbl->CHRONO!=NULL)
1011 {
1012 savedbl->CHRONO=mbkalloc(sizeof(stbchrono_list));
1013 memcpy(savedbl->CHRONO, dbl->CHRONO, sizeof(stbchrono_list));
1014 savedbl->CHRONO->SPECS=stb_dupstbpairlist(dbl->CHRONO->SPECS);
1015 savedbl->CHRONO->SPECS_U=stb_dupstbpairlist(dbl->CHRONO->SPECS_U);
1016 savedbl->CHRONO->SPECS_D=stb_dupstbpairlist(dbl->CHRONO->SPECS_D);
1017 }*/
1018
1019 old=addchain(old, si);
1020 (*nb)++;
1021 if (val>*top) *top=val;
1022 }
1023 }
1024 }
1025 }
1026 }
1027 }
1028 freechain(lst);
1029 }
1030 return old;
1031 }
1032
1033 static chain_list *stb_get_directive_paths(ttvfig_list *tf, int max, ttvsig_list *sig, int sigdir, int clock, int retrypath, long thisarrival, ttvevent_list **tve, chain_list *speedinput)
1034 {
1035 chain_list *cl, *ch, *clks, *ret=NULL;
1036 int checkdir;
1037 ttvpath_list *tp;
1038 long arrival;
1039
1040 *tve=NULL;
1041 ttv_activate_multi_cmd_critic_mode(1);
1042 ttv_activate_multi_end_cmd_critic_mode(1);
1043 ch=addchain(NULL, sig);
1044 if (clock)
1045 {
1046 clks=ttv_getclocksiglist(tf);
1047 ttv_search_mode(1, TTV_MORE_OPTIONS_USE_CLOCK_START);
1048 }
1049 else
1050 {
1051 ttv_search_mode(1, TTV_MORE_OPTIONS_USE_DATA_START);
1052 clks=speedinput;
1053 }
1054 cl=ttv_internal_GetPaths_EXPLICIT(tf, NULL, clks, ch, "??", 0, "critic", clock?"path":retrypath?"path":"access", max?"max":"min");
1055 if (clks!=speedinput) freechain(clks);
1056 freechain(ch);
1057 ttv_search_mode(0, TTV_MORE_OPTIONS_USE_CLOCK_START|TTV_MORE_OPTIONS_USE_DATA_START);
1058 ttv_activate_multi_end_cmd_critic_mode(0);
1059 ttv_activate_multi_cmd_critic_mode(0);
1060
1061 for (ch=cl; ch!=NULL; ch=ch->NEXT)
1062 {
1063 tp=(ttvpath_list *)ch->DATA;
1064 if ((tp->ROOT->TYPE & TTV_NODE_UP)==TTV_NODE_UP) checkdir=1;
1065 else checkdir=0;
1066 if (retrypath &&
1067 ((tp->NODE->ROOT->TYPE & TTV_SIG_C)==0
1068 || ttv_IsClock(tp->NODE->ROOT))
1069 ) continue;
1070 if (ttv_PathIsHZ(tp)) continue;
1071
1072 if (checkdir==sigdir)
1073 {
1074 arrival=tp->DELAY+tp->DATADELAY;
1075 if (tp->CROSSMINDELAY!=TTV_NOTIME)
1076 arrival+=tp->CROSSMINDELAY;
1077 else
1078 arrival+=tp->DELAYSTART;
1079 if ((clock && getptype(tp->NODE->ROOT->USER, STB_IDEAL_CLOCK)!=NULL) || arrival==thisarrival)
1080 {
1081 ret=addchain(ret, tp);
1082 ch->DATA=NULL;
1083 break;
1084 }
1085 }
1086 }
1087
1088 if (!retrypath && !clock && ret==NULL)
1089 ret=stb_get_directive_paths(tf, max, sig, sigdir, clock, 1, thisarrival, tve, speedinput);
1090
1091 if (!retrypath && ret==NULL && (sig->TYPE & TTV_SIG_C)!=0)
1092 {
1093 *tve=&sig->NODE[sigdir];
1094 }
1095
1096 ttv_FreePathList(cl);
1097 freechain(cl);
1098 return ret;
1099 }
1100
1101
1102 static ttvpath_list *change_path_start_considering_start_phase(ttvfig_list *tf, ttvpath_list *tp, char phase, chain_list **list)
1103 {
1104 long start;
1105 start=ttv_getinittime(tf,tp->NODE,STB_NO_INDEX,tp->TYPE,phase,NULL) ;
1106 if (start!=tp->DELAYSTART)
1107 {
1108 tp=ttv_duppath(tp);
1109 tp->DELAYSTART=start;
1110 *list=addchain(*list, tp);
1111 }
1112 return tp;
1113 }
1114
1115 static int stb_assoc_start_mode(slackinfo *a)
1116 {
1117 if (a->access) return 2; // clock mode
1118 if (ttv_IsClock(a->debugl.SIG1))
1119 {
1120 if (a->debugl.START_CMD_EVENT==NULL) return 2; // clock mode
1121 else return 1; //data mode
1122 }
1123 return 0;
1124 }
1125 static chain_list *stb_associate_paths(ttvfig_list *tf, char *dir, int setuphold, char *start, int dirin, slackinfo *tab, int cur, int tot, chain_list *allpaths, chain_list *speedinput)
1126 {
1127 chain_list *cl, *ch, *clks;
1128 int i, access, checkdir, specinmode=0, sm;
1129 char checkhz;
1130 ttvpath_list *tp;
1131 ttvevent_list *path_start_ev;
1132 stbnode *node;
1133 if (tab[cur].path==NULL)
1134 {
1135 ttv_activate_multi_cmd_critic_mode(1);
1136 ttv_activate_multi_end_cmd_critic_mode(1);
1137 ttv_search_mode(1, TTV_MORE_OPTIONS_DONT_FILTER_ENDING_NODE);
1138 ch=addchain(NULL, tab[cur].debugl.SIG2);
1139 if (tab[cur].access)
1140 {
1141 clks=ttv_getclocksiglist(tf);
1142 ttv_search_mode(1, TTV_MORE_OPTIONS_USE_CLOCK_START);
1143 if (tab[cur].debugl.SIG2==tab[cur].debugl.SIG1 && (tab[cur].debugl.SIG2->TYPE & TTV_SIG_C)!=0)
1144 ttv_search_mode(1, TTV_MORE_OPTIONS_MOST_DIRECT_ACCESS);
1145 }
1146 else clks=NULL;
1147 sm=stb_assoc_start_mode(&tab[cur]);
1148 if (sm==1) ttv_search_mode(1, TTV_MORE_OPTIONS_USE_DATA_START);
1149 else if (sm==2) ttv_search_mode(1, TTV_MORE_OPTIONS_USE_CLOCK_START);
1150
1151 cl=ttv_internal_GetPaths_EXPLICIT(tf, clks, speedinput, ch, dir, 0, "critic", tab[cur].access?"access":"path", setuphold?"max":"min");
1152 freechain(clks);
1153 freechain(ch);
1154 ttv_search_mode(0, TTV_MORE_OPTIONS_DONT_FILTER_ENDING_NODE);
1155 ttv_search_mode(0, TTV_MORE_OPTIONS_MOST_DIRECT_ACCESS);
1156
1157 if (cl==NULL)
1158 {
1159 node=stb_getstbnode(tab[cur].debugl.SIG1_EVENT);
1160 if (node->SPECIN!=NULL)
1161 {
1162 cl=addchain(NULL, ttv_create_one_node_path(tf, tf, tab[cur].debugl.SIG1_EVENT, setuphold?TTV_FIND_MAX:TTV_FIND_MIN));
1163 specinmode=1;
1164 }
1165 }
1166 ttv_search_mode(0, TTV_MORE_OPTIONS_USE_CLOCK_START|TTV_MORE_OPTIONS_USE_DATA_START);
1167 ttv_activate_multi_end_cmd_critic_mode(0);
1168 ttv_activate_multi_cmd_critic_mode(0);
1169 /*
1170 sort_by_absolute_time(cl);
1171 if (setuphold==0) cl=reverse(cl);
1172 */
1173 for (i=cur; i<tot; i+=tab[i].jump)
1174 {
1175 if (tab[i].path!=NULL) continue;
1176 // if (tab[i].flags & STB_DEBUG_DIRECTIVE) continue;
1177 if (tab[i].access==tab[cur].access && tab[i].debugl.SIG2==tab[cur].debugl.SIG2 && stb_assoc_start_mode(&tab[i])==sm)
1178 {
1179 path_start_ev=stb_getpathstart(tf, tab[i].debugl.SIG1_EVENT, start, dirin, &access, tab[i].phase, tab[i].debugl.START_CMD_EVENT, !tab[i].access, tab[i].debugl.START_CLOCK);
1180 for (ch=cl; ch!=NULL; ch=ch->NEXT)
1181 {
1182 tp=(ttvpath_list *)ch->DATA;
1183 if ((tp->ROOT->TYPE & TTV_NODE_UP)==TTV_NODE_UP) checkdir=1;
1184 else checkdir=0;
1185 if (ttv_PathIsHZ(tp)) checkhz=1; else checkhz=0;
1186
1187 if ((specinmode || checkdir==tab[i].dirout) && checkhz==tab[i].hzpath)
1188 {
1189 if (tab[cur].access==0)
1190 {
1191 if (tp->NODE==tab[i].debugl.SIG1_EVENT)
1192 {
1193 tab[i].path=change_path_start_considering_start_phase(tf, tp, tab[i].phase, &cl);
1194 tab[i].path->MD++;
1195 break;
1196 }
1197 }
1198 else
1199 {
1200 if (tp->LATCH==tab[i].debugl.SIG1_EVENT && tp->NODE==path_start_ev
1201 && ((tab[i].flags & STB_DEBUG_DIRECTIVE)!=0 || tp->CMD==tab[i].debugl.CMD_EVENT)
1202 && ((tp->LATCH->ROOT->TYPE & (TTV_SIG_R|TTV_SIG_B))!=0 || tp->CMDLATCH==tab[i].debugl.START_CMD_EVENT)
1203 )
1204 {
1205 tab[i].path=change_path_start_considering_start_phase(tf, tp, tab[i].phase, &cl);
1206 tab[i].path->MD++;
1207 break;
1208 }
1209 }
1210 }
1211 }
1212 }
1213 }
1214 for (ch=cl; ch!=NULL; ch=ch->NEXT)
1215 {
1216 tp=(ttvpath_list *)ch->DATA;
1217 if (tp->MD!=NULL) allpaths=addchain(allpaths, tp), ch->DATA=NULL;
1218 }
1219 ttv_FreePathList(cl);
1220 freechain(cl);
1221 }
1222 return allpaths;
1223 }
1224
1225 #define ZINAPS_TEMP_TYPE 0xfab70228
1226
1227 static slackinfo *__stb_getslacklist(stbfig_list *sbf, int setuphold, char *start, char *end, int dirin, int dirout, double margin, int maxnb, int *total, int forced, char *thru)
1228 {
1229 int tot, max, nbtot=0;
1230 slackinfo *tab;
1231 chain_list *cl, *chainsig, *chain, *all, *prev;
1232 double topval=1e10;
1233 ptype_list *pt;
1234 ttvsig_list *tvs;
1235
1236 if (sbf==NULL) { *total=0; return NULL; }
1237
1238 all=NULL;
1239 chainsig = ttv_getsigbytype(sbf->FIG, NULL, TTV_SIG_TYPEALL, NULL) ;
1240 for(chain = chainsig; chain ; chain = chain->NEXT)
1241 {
1242 tvs=(ttvsig_list *)chain->DATA;
1243 all=getslackinfo_grab(sbf->FIG, tvs, setuphold, start, end, dirin, dirout, margin, all, &topval, &nbtot, maxnb, forced, thru);
1244 if (maxnb!=INT_MAX && nbtot>maxnb*2)
1245 {
1246 tab=(slackinfo *)mbkalloc(sizeof(slackinfo)*nbtot);
1247 for (tot=0, cl=all; tot<nbtot && cl!=NULL; tot++, cl=cl->NEXT)
1248 {
1249 memcpy(&tab[tot], cl->DATA, sizeof(slackinfo));
1250 }
1251
1252 qsort(tab, tot, sizeof(slackinfo), slacksort);
1253
1254 for (tot=0, cl=all; tot<maxnb; tot++, cl=cl->NEXT)
1255 {
1256 prev=cl;
1257 memcpy(cl->DATA, &tab[tot], sizeof(slackinfo));
1258 }
1259 prev->NEXT=NULL;
1260 while (cl!=NULL)
1261 {
1262 mbkfree(cl->DATA);
1263 cl=delchain(cl, cl);
1264 }
1265 topval=tab[maxnb-1].slack;
1266 nbtot=maxnb;
1267 mbkfree(tab);
1268 }
1269 }
1270 freechain(chainsig);
1271
1272 max=countchain(all);
1273 tab=(slackinfo *)mbkalloc(sizeof(slackinfo)*max);
1274 for (tot=0; all!=NULL; all=delchain(all, all))
1275 {
1276 memcpy(&tab[tot], all->DATA, sizeof(slackinfo));
1277 mbkfree(all->DATA);
1278 tot++;
1279 }
1280
1281 qsort(tab, tot, sizeof(slackinfo), slacksort);
1282
1283 *total=tot;
1284
1285 for (max=0; max<tot; max++)
1286 {
1287 if ((pt=getptype(tab[max].debugl.SIG2->USER, ZINAPS_TEMP_TYPE))==NULL)
1288 tab[max].debugl.SIG2->USER=addptype(tab[max].debugl.SIG2->USER, ZINAPS_TEMP_TYPE, (void *)(long)max);
1289 else
1290 {
1291 tab[(int)(long)pt->DATA].jump=max-(int)(long)pt->DATA;
1292 pt->DATA=(void *)(long)max;
1293 }
1294 }
1295
1296 for (max=0; max<tot; max++)
1297 {
1298 if ((pt=getptype(tab[max].debugl.SIG2->USER, ZINAPS_TEMP_TYPE))!=NULL)
1299 {
1300 tab[(int)(long)pt->DATA].jump=tot-(int)(long)pt->DATA;
1301 tab[max].debugl.SIG2->USER=delptype(tab[max].debugl.SIG2->USER, ZINAPS_TEMP_TYPE);
1302 }
1303 }
1304
1305 return tab;
1306 }
1307
1308 static chain_list *__stb_getslackpaths(ttvfig_list *tvf, slackinfo *tab, char *start, int dirin, char *direction, int setuphold, int i, int tot, chain_list *allpaths, chain_list **requiredpath, chain_list *speedinput)
1309 {
1310 Setup_Hold_Computation_Detail_INFO *detail;
1311 chain_list *chain;
1312 int dir;
1313 ttvevent_list *clockcon, *pathcmd;
1314 *requiredpath=NULL;
1315
1316 /* if (tab[i].flags & STB_DEBUG_DIRECTIVE)
1317 allpaths=stb_associate_directive_paths(tvf, setuphold, tab, i, tot, allpaths, (tab[i].flags & STB_DEBUG_DIRECTIVE_DATA_IS_CLOCK)?1:0, 0, speedinput);
1318 else*/
1319 allpaths=stb_associate_paths(tvf, direction, setuphold, start, dirin, tab, i, tot, allpaths, speedinput);
1320 if (tab[i].path)
1321 {
1322 if (ttv_GetPathEndDirection(tab[i].path)=='u') dir=1; else dir=0;
1323 if (setuphold) detail=&tab[i].debugl.detail[dir].setup;
1324 else detail=&tab[i].debugl.detail[dir].hold;
1325
1326 tab[i].path->CMD=tab[i].debugl.CMD_EVENT;
1327
1328 if (!(tab[i].flags & STB_DEBUG_SPECOUTMODE) && !(tab[i].flags & STB_DEBUG_DIRECTIVE_DELAYMODE))
1329 {
1330 if (tab[i].flags & STB_DEBUG_DIRECTIVE)
1331 {
1332 chain=stb_get_directive_paths(tvf, !setuphold, tab[i].debugl.CMD_EVENT->ROOT, (tab[i].flags & STB_DEBUG_DIRECTIVE_RISING)?1:0,(tab[i].flags & STB_DEBUG_DIRECTIVE_CLOCK_IS_DATA)?0:1, 0, detail->clock-detail->moved_clock_period, &clockcon, speedinput);
1333 }
1334 else
1335 chain=ttv_GetClockPath(tab[i].path, &clockcon, &pathcmd);
1336 if (chain==NULL && clockcon!=NULL)
1337 {
1338 if ((tab[i].flags & STB_DEBUG_DIRECTIVE)==0 || (tab[i].flags & STB_DEBUG_DIRECTIVE_CLOCK_IS_DATA)==0)
1339 ttv_search_mode(1, TTV_MORE_OPTIONS_USE_CLOCK_START);
1340 else
1341 ttv_search_mode(1, TTV_MORE_OPTIONS_USE_DATA_START);
1342
1343 chain=addchain(NULL, ttv_create_one_node_path(tab[i].path->FIG, tab[i].path->FIG, clockcon, (tab[i].path->TYPE & TTV_FIND_MAX)!=0?TTV_FIND_MIN:TTV_FIND_MAX));
1344 ttv_search_mode(0, TTV_MORE_OPTIONS_USE_CLOCK_START|TTV_MORE_OPTIONS_USE_DATA_START);
1345 }
1346 }
1347 else chain=NULL;
1348 *requiredpath=chain;
1349 }
1350
1351 return allpaths;
1352 }
1353
1354 static ttvpath_list *stb_GetSlackPath(slackobject *so, char which)
1355 {
1356 // which=0 data_valid else data_required
1357 chain_list *allpaths, *chain;
1358 Setup_Hold_Computation_Detail_INFO *detail;
1359
1360 if (so->SI.path==NULL)
1361 {
1362 int oldttvmode=TTV_QUIET_MODE, oldprecisionlevel;
1363 TTV_QUIET_MODE=1;
1364 oldprecisionlevel=ttv_SetPrecisionLevel(0);
1365
1366 allpaths=__stb_getslackpaths(ttv_GetSignalTopTimingFigure(so->SI.debugl.SIG2), &so->SI, "*", 2, "??", so->setuphold, 0, 1, NULL, &chain, NULL);
1367 so->data_required=chain!=NULL?chain->DATA:NULL;
1368 freechain(chain);
1369 so->data_valid=so->SI.path;
1370 for (chain=allpaths; chain!=NULL && chain->DATA!=so->SI.path; chain=chain->NEXT) ;
1371 if (chain!=NULL) chain->DATA=NULL;
1372 ttv_FreePathList(allpaths);
1373 freechain(allpaths);
1374
1375 ttv_SetPrecisionLevel(oldprecisionlevel);
1376 TTV_QUIET_MODE=oldttvmode;
1377
1378 if (so->setuphold) detail=&so->SI.debugl.detail[(int)so->SI.dirout].setup;
1379 else detail=&so->SI.debugl.detail[(int)so->SI.dirout].hold;
1380
1381 // if (so->data_valid!=NULL) so->data_valid->DELAYSTART+=detail->datamoved+detail->misc;
1382
1383 if (so->data_required!=NULL)
1384 {
1385 /* long pm;
1386 pm=detail->moved_clock_period;
1387 if (so->setuphold==0) pm-=detail->period;
1388 so->data_required->DELAYSTART+=pm;*/
1389 so->data_required->DELAYSTART+=-detail->datamoved-detail->misc+detail->moved_clock_period;
1390 if (so->setuphold==0) so->data_required->DELAYSTART-=detail->period;
1391 }
1392 if (so->data_valid) ttv_CheckTransformToIdeal(so->data_valid);
1393 if (so->data_required) ttv_CheckTransformToIdeal(so->data_required);
1394 }
1395 if (which=='v') return so->data_valid;
1396 return so->data_required;
1397 }
1398
1399 static void stb_GetAllSlackPath(chain_list *sl)
1400 {
1401 chain_list *cl, *chain, *allpaths, *speedinput;
1402 slackobject *so;
1403 slackinfo *tab;
1404 int nb, setuphold, i;
1405 ttvpath_list *pth;
1406 ttvfig_list *tvf;
1407 for (nb=0, cl=sl; cl!=NULL; cl=cl->NEXT)
1408 {
1409 so=(slackobject *)cl->DATA;
1410 setuphold=so->setuphold;
1411 tvf=so->SI.debugl.SIG2->ROOT;
1412 if (so->SI.path==NULL) nb++;
1413 }
1414
1415 if (nb>0)
1416 {
1417 tab=(slackinfo *)mbkalloc(nb*sizeof(slackinfo));
1418 for (nb=0, cl=sl; cl!=NULL; cl=cl->NEXT)
1419 {
1420 so=(slackobject *)cl->DATA;
1421 if (so->SI.path==NULL)
1422 memcpy(&tab[nb++], &so->SI, sizeof(slackinfo));
1423 }
1424 tvf=ttv_GetTopTimingFigure(tvf);
1425 speedinput = ttv_getsigbytype_and_netname(tvf,NULL,TTV_SIG_C|TTV_SIG_L|TTV_SIG_R|TTV_SIG_B,NULL) ;
1426 allpaths=NULL;
1427 for (i=0, cl=sl; cl!=NULL; cl=cl->NEXT)
1428 {
1429 so=(slackobject *)cl->DATA;
1430 if (so->SI.path==NULL)
1431 {
1432 allpaths=__stb_getslackpaths(tvf, tab, "*", 2, "??", setuphold, i, nb, allpaths, &chain, speedinput);
1433 so->data_required=chain!=NULL?ttv_duppath((ttvpath_list *)chain->DATA):NULL;
1434 freechain(chain);
1435 so->data_valid=ttv_duppath(tab[i].path);
1436 i++;
1437 }
1438 }
1439 freechain(speedinput);
1440 for (chain=allpaths; chain!=NULL; chain=chain->NEXT)
1441 {
1442 pth=(ttvpath_list *)chain->DATA;
1443 if (pth!=NULL) pth->MD=NULL;
1444 }
1445 ttv_FreePathList(allpaths);
1446 freechain(allpaths);
1447 mbkfree(tab);
1448 }
1449 }
1450
1451 static void __stb_DisplaySlackReport_grab(FILE *f, stbfig_list *stbfig, char *start, char *end, char *direction, int setuphold, double margin, int sumaonly, int maxnb, int addit, char *thru, chain_list *given_objects, int simple)
1452 {
1453 char *startsig, *endsig;
1454 ttvsig_list *sg;
1455 char startdir, enddir;
1456 char buf[1024];
1457 int count=1, tot, max, i, dir, dirin, dirout, access, countfree;
1458 Board *b;
1459 slackinfo *tab;
1460 slackobject **sotab=NULL;
1461 long lastmode;
1462 Setup_Hold_Computation_Detail_INFO *detail;
1463 chain_list *chain, *allpaths, *speedinput=NULL;
1464 ttvevent_list *path_start_ev;
1465 ttvpath_list *pth;
1466 long old0, old1, save_req;
1467 float pm, sh_m;
1468 int forced;
1469
1470
1471 ttv_DirectionStringToIndices(direction, &dirin, &dirout);
1472 forced=ttv_DirectionStringToIndicesHZ(direction);
1473
1474 lastmode=stbsetdebugflag(STB_DIFFERENTIATE_INPUT_EVENTS);
1475 ttv_setsearchexclude(0,0,&old0, &old1);
1476
1477 b=Board_CreateBoard();
1478
1479 Board_SetSize(b, COL_INDEX, 5, 'r');
1480 Board_SetSize(b, COL_SLACK, 7, DISPLAY_number_justify);
1481 Board_SetSize(b, COL_DV_TIME, 7, DISPLAY_number_justify);
1482 Board_SetSize(b, COL_DV_REL, 7, DISPLAY_number_justify);
1483 Board_SetSize(b, COL_DR_TIME, 7, DISPLAY_number_justify);
1484 Board_SetSize(b, COL_DR_REL, 7, DISPLAY_number_justify);
1485 Board_SetSize(b, COL_STARTEND, 3, 'c');
1486 Board_SetSize(b, COL_FROMNODE, 20, 'l');
1487 Board_SetSize(b, COL_FROMNODEDIR, 3, 'l');
1488 Board_SetSize(b, COL_TONODE, 20, 'l');
1489 Board_SetSize(b, COL_TONODEDIR, 4, 'l');
1490
1491 if (addit & 2)
1492 Board_SetSize(b, COL_THRUDEBUG, 20, 'l');
1493
1494 if (addit & 1)
1495 {
1496 Board_SetSize(b, COL_DATAPATHMARGIN, 6, DISPLAY_number_justify);
1497 Board_SetSize(b, COL_CLOCKPATHMARGIN, 6, DISPLAY_number_justify);
1498 Board_SetSize(b, COL_INTRINSIC_MARGIN, 10, DISPLAY_number_justify);
1499 Board_SetSep(b, COL_SLACK_SEP6);
1500 }
1501
1502 Board_SetSep(b, COL_SLACK_SEP0);
1503 Board_SetSep(b, COL_SLACK_SEP1);
1504 Board_SetSep(b, COL_SLACK_SEP2);
1505 Board_SetSep(b, COL_SLACK_SEP3);
1506 Board_SetSep(b, COL_SLACK_SEP4);
1507 Board_SetSep(b, COL_SLACK_SEP5);
1508
1509 Board_NewLine(b);
1510
1511 Board_SetValue(b, COL_INDEX, "Path");
1512 Board_SetValue(b, COL_SLACK, "Slack");
1513 Board_SetValue(b, COL_DV_TIME, "éData");
1514 Board_SetValue(b, COL_DV_REL, "èvalid");
1515 Board_SetValue(b, COL_DR_TIME, "éData");
1516 Board_SetValue(b, COL_DR_REL, "èrequired");
1517 Board_SetValue(b, COL_FROMNODE, "From_node");
1518 Board_SetValue(b, COL_TONODE, "To_node");
1519
1520 if (addit & 1)
1521 {
1522 Board_SetValue(b, COL_DATAPATHMARGIN, "D-Margin");
1523 Board_SetValue(b, COL_CLOCKPATHMARGIN, "C-Margin");
1524 Board_SetValue(b, COL_INTRINSIC_MARGIN, "IntrMargin");
1525 }
1526 if (addit & 2)
1527 Board_SetValue(b, COL_THRUDEBUG, "Thru_node");
1528
1529 Board_NewSeparation(b);
1530
1531 if (!given_objects)
1532 tab=__stb_getslacklist(stbfig, setuphold, start, end, dirin, dirout, margin, maxnb, &tot, forced,thru);
1533 else
1534 {
1535 tot=countchain(given_objects);
1536 if (tot>0)
1537 {
1538 tab=mbkalloc(sizeof(slackinfo)*tot);
1539 sotab=mbkalloc(sizeof(slackobject *)*tot);
1540 for (chain=given_objects, i=0; chain!=NULL; chain=chain->NEXT, i++)
1541 {
1542 sotab[i]=(slackobject *)chain->DATA;
1543 memcpy(&tab[i], &((slackobject *)chain->DATA)->SI, sizeof(slackinfo));
1544 }
1545 }
1546 }
1547
1548 for (i=0; i<tot && i<maxnb; i++)
1549 {
1550 Board_NewLine(b);
1551 sprintf(buf,"%d", count);
1552 Board_SetValue(b, COL_INDEX, buf);
1553 if (sotab)
1554 {
1555 if (sotab[i]->SI.path!=NULL)
1556 path_start_ev=sotab[i]->SI.path->NODE;
1557 else
1558 path_start_ev=stb_getpathstart(ttv_GetSignalTopTimingFigure(sotab[i]->SI.debugl.SIG2), sotab[i]->SI.debugl.SIG1_EVENT, "*", (int)sotab[i]->SI.dirin, &access, sotab[i]->SI.phase, sotab[i]->SI.debugl.START_CMD_EVENT, !sotab[i]->SI.access, sotab[i]->SI.debugl.START_CLOCK);
1559 }
1560 else
1561 path_start_ev=stb_getpathstart(stbfig->FIG, tab[i].debugl.SIG1_EVENT, start, dirin, &access, tab[i].phase,tab[i].debugl.START_CMD_EVENT, !tab[i].access, tab[i].debugl.START_CLOCK);
1562
1563 sg=path_start_ev->ROOT;
1564 startsig=ttv_GetFullSignalName_COND(ttv_GetSignalTopTimingFigure(sg), sg);
1565
1566 sg=tab[i].debugl.SIG2;
1567 endsig=ttv_GetFullSignalName_COND(ttv_GetSignalTopTimingFigure(sg), sg);
1568
1569 startdir=dirconv(tab[i].dirin?'u':'d');
1570 enddir=dirconv(tab[i].dirout?'u':'d');
1571 sprintf(buf,"(%c)",startdir);
1572 Board_SetValue(b, COL_FROMNODEDIR, buf);
1573 buf[0]='(';
1574 buf[1]=enddir;
1575 if (tab[i].hzpath) {strcpy(&buf[2],"Z)");}
1576 else {strcpy(&buf[2],")"); }
1577 Board_SetValue(b, COL_TONODEDIR, buf);
1578 Board_SetValue(b, COL_FROMNODE, startsig);
1579 Board_SetValue(b, COL_TONODE, endsig);
1580
1581 if (/*(tab[i].flags & STB_DEBUG_DIRECTIVE)==0 && */(tab[i].access || (tab[i].debugl.SIG1_EVENT->ROOT->TYPE & TTV_SIG_C)==0))
1582 {
1583 char buf1[1024];
1584
1585 if (tab[i].debugl.START_CMD_EVENT!=NULL)
1586 {
1587 startsig=ttv_GetFullSignalName_COND(ttv_GetSignalTopTimingFigure(tab[i].debugl.START_CMD_EVENT->ROOT), tab[i].debugl.START_CMD_EVENT->ROOT);
1588 sprintf(buf1, " cmd: %s (%c)", startsig, dirconv(ttv_GetTimingEventDirection(tab[i].debugl.START_CMD_EVENT)));
1589 }
1590 else strcpy(buf1,"");
1591 startsig=ttv_GetFullSignalName_COND(ttv_GetSignalTopTimingFigure(tab[i].debugl.SIG1_EVENT->ROOT), tab[i].debugl.SIG1_EVENT->ROOT);
1592 sprintf(buf, "%s (%c)%s", startsig, dirconv(ttv_GetTimingEventDirection(tab[i].debugl.SIG1_EVENT)), buf1);
1593 Board_SetValue(b, COL_THRUDEBUG, buf);
1594 }
1595
1596 if (tab[i].datavalid<1)
1597 {
1598 Board_SetValue(b, COL_DV_TIME, FormaT(tab[i].datavalid*DISPLAY_time_unit, buf, DISPLAY_time_format));
1599 if ((tab[i].flags & STB_DEBUG_DIRECTIVE)==0)
1600 {
1601 char buf0[1024];
1602 if (tab[i].lag>0)
1603 sprintf(buf, "[%s lag]", FormaT(tab[i].lag*DISPLAY_time_unit, buf0, DISPLAY_time_format));
1604 else
1605 strcpy(buf,"");
1606 Board_SetValue(b, COL_DV_REL, buf);
1607 }
1608 }
1609 else
1610 {
1611 Board_SetValue(b, COL_DV_TIME, "void");
1612 // Board_SetValue(b, COL_DV_REL, "void");
1613 }
1614 Board_SetValue(b, COL_DR_TIME, FormaT(tab[i].datareq*DISPLAY_time_unit, buf, DISPLAY_time_format));
1615 /* if ((tab[i].flags & STB_DEBUG_DIRECTIVE)==0)
1616 {
1617 if (tab[i].period>0)
1618 sprintf(buf, "%s B%c", FormaT(fmod(tab[i].datavalidclock-tab[i].datareq, tab[i].period)*DISPLAY_time_unit, buf, DISPLAY_time_format), tab[i].datavalidclockdir=='u'?'R':'F');
1619 else
1620 strcpy(buf,"");
1621 Board_SetValue(b, COL_DR_REL, buf);
1622 }*/
1623 if (tab[i].datavalid<1)
1624 {
1625 Board_SetValue(b, COL_SLACK, FormaT(tab[i].slack*DISPLAY_time_unit, buf, DISPLAY_time_format));
1626 }
1627 else Board_SetValue(b, COL_SLACK, "void");
1628
1629 if ((tab[i].flags & STB_DEBUG_DIRECTIVE)==0)
1630 {
1631 if (isclock(path_start_ev->ROOT))
1632 startsig="C";
1633 else
1634 {
1635 startsig=typeconv(ttv_GetSignalType(path_start_ev->ROOT));
1636 // if (strcmp(startsig, "S")==0) startsig="s";
1637 }
1638
1639 if (isclock(tab[i].debugl.SIG2))
1640 endsig="C";
1641 else
1642 endsig=typeconv(ttv_GetSignalType(tab[i].debugl.SIG2));
1643 }
1644 else
1645 {
1646 if (tab[i].flags & STB_DEBUG_DIRECTIVE_DATA_IS_CLOCK)
1647 startsig="CP";
1648 else
1649 startsig="DP";
1650 if (tab[i].flags & STB_DEBUG_DIRECTIVE_DELAYMODE)
1651 endsig="CST";
1652 else if (tab[i].flags & STB_DEBUG_DIRECTIVE_CLOCK_IS_DATA)
1653 endsig="DP";
1654 else
1655 endsig="CP";
1656 }
1657
1658 sprintf(buf,"%s-%s", startsig, endsig);
1659
1660 Board_SetValue(b, COL_STARTEND, buf);
1661
1662 if (addit & 1)
1663 {
1664 if (setuphold) detail=&tab[i].debugl.detail[(int)tab[i].dirout].setup;
1665 else detail=&tab[i].debugl.detail[(int)tab[i].dirout].hold;
1666 Board_SetValue(b, COL_DATAPATHMARGIN, FormaT((detail->data_margin*1e-12/TTV_UNIT)*DISPLAY_time_unit, buf, DISPLAY_time_format));
1667 Board_SetValue(b, COL_CLOCKPATHMARGIN, FormaT((detail->clock_margin*1e-12/TTV_UNIT)*DISPLAY_time_unit, buf, DISPLAY_time_format));
1668 Board_SetValue(b, COL_INTRINSIC_MARGIN, FormaT((detail->margin*1e-12/TTV_UNIT)*DISPLAY_time_unit, buf, DISPLAY_time_format));
1669 }
1670
1671 count++;
1672 }
1673
1674 avt_fprintf(f, " *** %s Slack report (unit:[%s]) ***\n\n",setuphold?"Setup":"Hold", DISPLAY_time_string);
1675
1676 Board_Display(f, b, "");
1677 Board_FreeBoard(b);
1678
1679 avt_fprintf(f, "\n\n");
1680
1681 if (!sumaonly)
1682 {
1683 char *olddetmode;
1684 olddetmode=ttv_AutomaticDetailBuild("on");
1685 countfree=0;
1686 allpaths=NULL;
1687 if (!sotab)
1688 speedinput = ttv_getsigbytype_and_netname(stbfig->FIG,NULL,TTV_SIG_C|TTV_SIG_L|TTV_SIG_R|TTV_SIG_B,NULL) ;
1689 else
1690 stb_GetAllSlackPath(given_objects);
1691
1692 for (i=0; i<tot && i<maxnb; i++)
1693 {
1694
1695 if (!sotab)
1696 allpaths=__stb_getslackpaths(stbfig->FIG, tab, start, dirin, direction, setuphold, i, tot, allpaths, &chain, speedinput);
1697 else
1698 {
1699 if (sotab[i]->SI.path==NULL)
1700 stb_GetSlackPath(sotab[i], 'v');
1701 tab[i].path=sotab[i]->SI.path;
1702 chain=NULL;
1703 }
1704
1705 if (tab[i].path)
1706 {
1707 int oldmode=detail_forced_mode;
1708
1709 if (ttv_GetPathEndDirection(tab[i].path)=='u') dir=1; else dir=0;
1710 if (setuphold) detail=&tab[i].debugl.detail[dir].setup;
1711 else detail=&tab[i].debugl.detail[dir].hold;
1712
1713 detail_forced_mode=NOSUPINFO_DETAIL;
1714 // if (getptype(tab[i].path->NODE->ROOT->USER, STB_IDEAL_CLOCK)!=NULL)
1715 {
1716 if (!sotab || sotab[i]->custom==0)
1717 ttv_CheckTransformToIdeal(tab[i].path);
1718 // detail_forced_mode|=IDEAL_CLOCK;
1719 }
1720
1721 avt_fprintf(f, "Path (%d) : Slack of %s\n", i+1, FormaT(tab[i].slack*DISPLAY_time_unit, buf, DISPLAY_time_format));
1722 avt_fprintf(f, " DATA VALID:\n");
1723
1724 tab[i].path->CMD=tab[i].debugl.CMD_EVENT;
1725 /* if (!sotab)
1726 tab[i].path->USER=addptype(tab[i].path->USER, DEBUG_PTYPE, &tab[i].debugl);*/
1727 max=0;
1728
1729 if (detail->data_margin!=0)
1730 {
1731 PATH_MORE_INFO.add[max].label="[PATH MARGIN]";
1732 PATH_MORE_INFO.add[max].val=(detail->data_margin*1e-12/TTV_UNIT);
1733 PATH_MORE_INFO.add[max].noacc=0;
1734 max++;
1735 }
1736
1737 PATH_MORE_INFO.add[max].label=NULL;
1738 PATH_MORE_INFO.enabled=1;
1739 ttv_DisplayPathDetail(f, -1, tab[i].path);
1740 PATH_MORE_INFO.enabled=0;
1741 // tab[i].path->USER=testanddelptype(tab[i].path->USER, DEBUG_PTYPE);
1742 tab[i].path->USER=testanddelptype(tab[i].path->USER, MORE_PTYPE);
1743
1744 // detail_forced_mode&=~IDEAL_CLOCK;
1745
1746 if (chain!=NULL || (sotab && (detail->flags & STB_DEBUG_SPECOUTMODE)==0 && (tab[i].flags & STB_DEBUG_DIRECTIVE_DELAYMODE)==0))
1747 {
1748 if (!sotab)
1749 pth=(ttvpath_list *)chain->DATA;
1750 else
1751 pth=stb_GetSlackPath(sotab[i], 'r');
1752
1753 max=0;
1754
1755 sh_m=(detail->margin*1e-12/TTV_UNIT);
1756 if (detail->clock_margin!=0)
1757 {
1758 PATH_MORE_INFO.add[max].label="[PATH MARGIN]";
1759 PATH_MORE_INFO.add[max].val=(detail->clock_margin*1e-12/TTV_UNIT);
1760 PATH_MORE_INFO.add[max].noacc=0;
1761 max++;
1762 }
1763 if (detail->margin!=0)
1764 {
1765 char *labelsetup, *labelhold;
1766 if ((tab[i].flags & STB_DEBUG_DIRECTIVE)==0)
1767 labelsetup="[INTRINSIC SETUP]", labelhold="[INTRINSIC HOLD]";
1768 else
1769 labelsetup="[SETUP MARGIN]", labelhold="[HOLD MARGIN]";
1770
1771 if (setuphold)
1772 PATH_MORE_INFO.add[max].label=labelsetup, PATH_MORE_INFO.add[max].val=-(detail->margin*1e-12/TTV_UNIT);
1773 else
1774 PATH_MORE_INFO.add[max].label=labelhold, PATH_MORE_INFO.add[max].val=(detail->margin*1e-12/TTV_UNIT);
1775 PATH_MORE_INFO.add[max].noacc=0;
1776 max++;
1777 }
1778 if (detail->skew!=0)
1779 {
1780 PATH_MORE_INFO.add[max].label="[SKEW COMPENSATION]";
1781 if (setuphold)
1782 PATH_MORE_INFO.add[max].val=detail->skew/TTV_UNIT*1e-12;
1783 else
1784 PATH_MORE_INFO.add[max].val=-detail->skew/TTV_UNIT*1e-12;
1785 PATH_MORE_INFO.add[max].noacc=0;
1786 max++;
1787 }
1788 if (detail->uncertainty!=0)
1789 {
1790 PATH_MORE_INFO.add[max].label="[CLOCK UNCERTAINTY]";
1791 if (setuphold)
1792 PATH_MORE_INFO.add[max].val=-detail->uncertainty/TTV_UNIT*1e-12;
1793 else
1794 PATH_MORE_INFO.add[max].val=detail->uncertainty/TTV_UNIT*1e-12;
1795 PATH_MORE_INFO.add[max].noacc=0;
1796 max++;
1797 }
1798 if (!simple)
1799 {
1800 if (detail->mc_setup_period!=0)
1801 {
1802 sprintf(buf, "[SETUP MULTICYCLE %d]", detail->nb_setup_cycle);
1803 PATH_MORE_INFO.add[max].label=sensitive_namealloc(buf);
1804 PATH_MORE_INFO.add[max].val=(detail->mc_setup_period*1e-12/TTV_UNIT);
1805 PATH_MORE_INFO.add[max].noacc=1;
1806 max++;
1807 }
1808 if (!setuphold && detail->mc_hold_period!=0)
1809 {
1810 sprintf(buf, "[HOLD MULTICYCLE %d]", detail->nb_hold_cycle);
1811 PATH_MORE_INFO.add[max].label=sensitive_namealloc(buf);
1812 PATH_MORE_INFO.add[max].val=-(detail->mc_hold_period*1e-12/TTV_UNIT);
1813 PATH_MORE_INFO.add[max].noacc=1;
1814 max++;
1815 }
1816
1817 pm=-(detail->datamoved+detail->mc_setup_period)+detail->moved_clock_period;
1818 if (setuphold==0) pm-=detail->period;
1819 if (pm!=0)
1820 {
1821 if (pm>0)
1822 PATH_MORE_INFO.add[max].label="[NEXT PERIOD]";
1823 else
1824 PATH_MORE_INFO.add[max].label="[PREVIOUS PERIOD]";
1825 PATH_MORE_INFO.add[max].val=pm/TTV_UNIT*1e-12;
1826 PATH_MORE_INFO.add[max].noacc=1;
1827 max++;
1828 }
1829 }
1830
1831 PATH_MORE_INFO.add[max].label=NULL;
1832 if (max!=0) PATH_MORE_INFO.enabled=1;
1833 avt_fprintf(f, " DATA REQUIRED:\n");
1834 // if (getptype(pth->NODE->ROOT->USER, STB_IDEAL_CLOCK)!=NULL)
1835 {
1836 if (!sotab || sotab[i]->custom==0)
1837 ttv_CheckTransformToIdeal(pth);
1838 // detail_forced_mode|=IDEAL_CLOCK;
1839 }
1840
1841 save_req=pth->DELAYSTART;
1842 if (sotab && !simple)
1843 {
1844 pth->DELAYSTART-=detail->moved_clock_period-detail->datamoved+detail->misc;
1845 if (setuphold==0) pth->DELAYSTART+=detail->period;
1846 }
1847 else if (!sotab && simple)
1848 {
1849 pth->DELAYSTART+=-detail->datamoved-detail->misc+detail->moved_clock_period;
1850 if (!setuphold) pth->DELAYSTART-=detail->period;
1851 }
1852
1853
1854 ttv_DisplayPathDetail(f, -1, pth);
1855
1856 pth->DELAYSTART=save_req;
1857
1858 PATH_MORE_INFO.enabled=0;
1859 }
1860 else if (tab[i].flags & STB_DEBUG_DIRECTIVE_DELAYMODE)
1861 {
1862 avt_fprintf(f, " -> Specification: Must be stable %s %s\n\n", setuphold?"after":"before", FormaT(tab[i].datareq*DISPLAY_time_unit, buf, DISPLAY_time_format));
1863 }
1864 else
1865 {
1866 ttv_GetNodeSpecout(tab[i].path->ROOT, DISPLAY_time_unit, DISPLAY_time_format, buf, &tab[i].debugl, tab[i].path, setuphold, -detail->datamoved-detail->misc+detail->moved_clock_period);
1867 if (strlen(buf)!=0)
1868 {
1869 avt_fprintf(f, " -> Specification: %s\n\n", buf);
1870 }
1871 }
1872 ttv_FreePathList(chain);
1873 freechain(chain);
1874 detail_forced_mode=oldmode;
1875
1876 if (!sotab)
1877 {
1878 tab[i].path->MD--;
1879 if (tab[i].path->MD==NULL)
1880 {
1881 countfree++;
1882 if (countfree>50)
1883 {
1884 chain_list *temp=allpaths;
1885 allpaths=NULL;
1886 for (chain=temp; chain!=NULL; chain=chain->NEXT)
1887 {
1888 pth=(ttvpath_list *)chain->DATA;
1889 if (pth->MD==NULL)
1890 {
1891 pth->NEXT=NULL;
1892 ttv_freepathlist(pth);
1893 }
1894 else allpaths=addchain(allpaths, pth);
1895 }
1896 countfree=0;
1897 freechain(temp);
1898 }
1899 }
1900 }
1901 }
1902 else
1903 {
1904 avt_fprintf(f, "Path (%d) : Slack of %s\n", i+1, FormaT(tab[i].slack*DISPLAY_time_unit, buf, DISPLAY_time_format));
1905 avt_fprintf(f, " DATA VALID: *** FAILED TO RETRIEVE PATH ***\n\n");
1906 }
1907 }
1908
1909 if (!sotab)
1910 {
1911 freechain(speedinput);
1912 for (chain=allpaths; chain!=NULL; chain=chain->NEXT)
1913 {
1914 pth=(ttvpath_list *)chain->DATA;
1915 if (pth!=NULL) pth->MD=NULL;
1916 }
1917 ttv_FreePathList(allpaths);
1918 freechain(allpaths);
1919 }
1920 ttv_AutomaticDetailBuild(olddetmode);
1921 }
1922
1923
1924 /* for (i=0; i<tot; i++)
1925 {
1926 if (tab[i].debugl.CHRONO!=NULL)
1927 {
1928
1929 stb_freestbpair(tab[i].debugl.CHRONO->SPECS);
1930 stb_freestbpair(tab[i].debugl.CHRONO->SPECS_U);
1931 stb_freestbpair(tab[i].debugl.CHRONO->SPECS_D);
1932 mbkfree(tab[i].debugl.CHRONO);
1933 tab[i].debugl.CHRONO = NULL;
1934 }
1935 }
1936 */
1937
1938 mbkfree(tab);
1939 if (sotab) mbkfree(sotab);
1940
1941 ttv_setsearchexclude(old0, old1, &old0, &old1);
1942 stbsetdebugflag(lastmode);
1943 fflush(f);
1944 }
1945
1946 void stb_DisplaySlackReport_sub(FILE *f, stbfig_list *stbfig, char *start, char *end, char *dir, int number, char *mode, double margin)
1947 {
1948 int setup=0, hold=0, sum=0;
1949 char *tok, *c;
1950 char buf[256];
1951 int oldttvmode=TTV_QUIET_MODE;
1952 int oldprecisionlevel, addit=0, simple=0;
1953 long stbmode=stb_SUPMODE;
1954 char *thru=NULL;
1955
1956 strcpy(buf, mode);
1957 tok=strtok_r(buf, " ", &c);
1958
1959 while (tok!=NULL)
1960 {
1961 if (strcasecmp(tok,"setup")==0) setup=1;
1962 else if (strcasecmp(tok,"hold")==0) hold=1;
1963 else if (strcasecmp(tok,"all")==0) {setup=hold=1;}
1964 else if (strcasecmp(tok,"summary")==0) sum=1;
1965 else if (strcasecmp(tok,"margins")==0) addit|=1;
1966 else if (strcasecmp(tok,"thru")==0) addit|=2;
1967 else if (strcasecmp(tok,"simple")==0) simple=1;
1968 else if (strcasecmp(tok,"noprechlag")==0) stb_SUPMODE|=STB_REMOVE_LAGGING_PRECHARGES;
1969 else if (strncasecmp(tok,"thru=",5)==0) thru=&tok[5];
1970 else //avt_error("stbapi", 2, AVT_ERR, "stb_DisplaySlackReport: unknown mode '%s'\n", tok);
1971 avt_errmsg(STB_API_ERRMSG, "002", AVT_ERROR, tok);
1972 tok=strtok_r(NULL, " ", &c);
1973 }
1974
1975 if (f==NULL) return;
1976
1977 if (ftello(f)==0)
1978 ttv_DumpHeader(f, stbfig->FIG);
1979
1980 if (!stbfig) {
1981 avt_errmsg(STB_API_ERRMSG, "003", AVT_ERROR);
1982 // avt_error("stbapi", 2, AVT_ERR, "stb_DisplaySlackReport: NULL stbfig\n");
1983 return;
1984 }
1985
1986 TTV_QUIET_MODE=1;
1987
1988 oldprecisionlevel=ttv_SetPrecisionLevel(0);
1989
1990 if (number<=0) number=INT_MAX;
1991
1992 if (setup)
1993 {
1994 __stb_DisplaySlackReport_grab(f, stbfig, start, end, dir, 1, margin, sum, number, addit,thru, NULL, simple);
1995 }
1996 if (hold)
1997 {
1998 __stb_DisplaySlackReport_grab(f, stbfig, start, end, dir, 0, margin, sum, number, addit,thru, NULL, simple);
1999 }
2000
2001 ttv_SetPrecisionLevel(oldprecisionlevel);
2002
2003 TTV_QUIET_MODE=oldttvmode;
2004 stb_SUPMODE=stbmode;
2005 if (setup==0 && hold==0)
2006 avt_errmsg(STB_API_ERRMSG, "004", AVT_ERROR, mode);
2007 // avt_error("stbapi", 1, AVT_ERR, "stb_DisplaySlackReport: unknown or incomplete mode '%s'. Required: 'setup', 'hold' or 'all'\n", mode);
2008 }
2009
2010 void stb_FreeSlackList(chain_list *cl)
2011 {
2012 slackobject *so;
2013 while (cl!=NULL)
2014 {
2015 so=(slackobject *)cl->DATA;
2016 if (so->data_valid!=NULL) { so->data_valid->NEXT=NULL; so->data_valid->MD=NULL; ttv_freepathlist(so->data_valid); }
2017 if (so->data_required!=NULL) { so->data_required->NEXT=NULL; so->data_required->MD=NULL; ttv_freepathlist(so->data_required); }
2018 mbkfree(so);
2019 cl=cl->NEXT;
2020 }
2021 }
2022
2023 chain_list *stb_GetSlacks_sub(stbfig_list *stbfig, char *start, char *end, char *dir, int number, char *mode, double margin, char *thru, int nolagprech)
2024 {
2025 int setuphold;
2026 int oldprecisionlevel;
2027 int oldttvmode=TTV_QUIET_MODE;
2028 int tot, i, dirin, dirout;
2029 slackinfo *tab;
2030 slackobject *so;
2031 chain_list *cl, *ch;
2032 int forced;
2033 long stbmode=stb_SUPMODE;
2034
2035 ttv_DirectionStringToIndices(dir, &dirin, &dirout);
2036 forced=ttv_DirectionStringToIndicesHZ(dir);
2037
2038 if (strcasecmp(mode,"setup")==0) setuphold=1;
2039 else if (strcasecmp(mode,"hold")==0) setuphold=0;
2040 else
2041 {
2042 avt_errmsg(STB_API_ERRMSG, "002", AVT_ERROR, mode);
2043 return NULL;
2044 }
2045
2046 if (nolagprech) stb_SUPMODE|=STB_REMOVE_LAGGING_PRECHARGES;
2047 if (number<=0) number=INT_MAX;
2048 if (thru==NULL || strcmp(thru,"*")==0) thru=NULL;
2049
2050 TTV_QUIET_MODE=1;
2051 oldprecisionlevel=ttv_SetPrecisionLevel(0);
2052 tab=__stb_getslacklist(stbfig, setuphold, start, end, dirin, dirout, margin, number, &tot, forced, thru);
2053
2054 cl=NULL; ch=NULL;
2055 for (i=0; i<tot; i++)
2056 {
2057 so=(slackobject *)mbkalloc(sizeof(slackobject));
2058 memcpy(&so->SI, &tab[i], sizeof(slackinfo));
2059 so->setuphold=setuphold;
2060 so->custom=0;
2061 so->data_valid=so->data_required=NULL;
2062 if (i<number)
2063 cl=addchain(cl, so);
2064 else
2065 ch=addchain(ch, so);
2066 }
2067 mbkfree(tab);
2068 stb_FreeSlackList(ch);
2069 freechain(ch);
2070 ttv_SetPrecisionLevel(oldprecisionlevel);
2071 TTV_QUIET_MODE=oldttvmode;
2072 stb_SUPMODE=stbmode;
2073 return reverse(cl);
2074 }
2075
2076
2077 static ptype_list *fitdouble(double val)
2078 {
2079 ptype_list *pt;
2080 pt=addptype(NULL, TYPE_DOUBLE, NULL);
2081 *(float *)&pt->DATA=(float)val;
2082 return pt;
2083 }
2084 Property *stb_GetSlackProperty (slackobject *so, char *property)
2085 {
2086 char buf[256];
2087 Setup_Hold_Computation_Detail_INFO *detail;
2088
2089 if (!so) {
2090 sprintf (buf, "error_null_stabilityslack");
2091 return addptype (NULL, TYPE_CHAR, strdup (buf));
2092 }
2093
2094 if (!strcasecmp (property, "TYPE"))
2095 return addptype (NULL, TYPE_CHAR, strdup(so->setuphold?"setup":"hold"));
2096
2097 if (!strcasecmp (property, "DATA_REQUIRED_PATH"))
2098 return addptype (NULL, TYPE_TIMING_PATH, stb_GetSlackPath(so, 'r'));
2099
2100 if (!strcasecmp (property, "DATA_VALID_PATH"))
2101 return addptype (NULL, TYPE_TIMING_PATH, stb_GetSlackPath(so, 'v'));
2102
2103 if (!strcasecmp (property, "DATA_REQUIRED"))
2104 return fitdouble(so->SI.datareq);
2105
2106 if (!strcasecmp (property, "DATA_VALID"))
2107 return fitdouble(so->SI.datavalid);
2108
2109 if (!strcasecmp (property, "START_EVENT"))
2110 {
2111 ttvevent_list *path_start_ev;
2112 int access;
2113 path_start_ev=stb_getpathstart(ttv_GetSignalTopTimingFigure(so->SI.debugl.SIG2), so->SI.debugl.SIG1_EVENT, "*", (int)so->SI.dirin, &access, so->SI.phase, so->SI.debugl.START_CMD_EVENT, !so->SI.access, so->SI.debugl.START_CLOCK);
2114 return addptype (NULL, TYPE_TIMING_EVENT, path_start_ev);
2115 }
2116
2117 if (!strcasecmp (property, "THRU_EVENT"))
2118 {
2119 ttvevent_list *thru=NULL;
2120 if (so->SI.access) thru=so->SI.debugl.SIG1_EVENT;
2121 return addptype (NULL, TYPE_TIMING_EVENT, thru);
2122 }
2123
2124 if (!strcasecmp (property, "THRU_COMMAND_EVENT"))
2125 {
2126 ttvevent_list *thrucmd=NULL;
2127 if (so->SI.access) thrucmd=so->SI.debugl.START_CMD_EVENT;
2128 return addptype (NULL, TYPE_TIMING_EVENT, thrucmd);
2129 }
2130
2131 if (!strcasecmp (property, "END_EVENT"))
2132 return addptype (NULL, TYPE_TIMING_EVENT, &so->SI.debugl.SIG2->NODE[(int)so->SI.dirout]);
2133
2134 if (!strcasecmp (property, "IS_HZ"))
2135 {
2136 return addptype (NULL, TYPE_CHAR, strdup(so->SI.hzpath?"yes":"no"));
2137 }
2138
2139 if (!strcasecmp (property, "VALUE"))
2140 return fitdouble(so->SI.slack);
2141
2142 if (so->setuphold) detail=&so->SI.debugl.detail[(int)so->SI.dirout].setup;
2143 else detail=&so->SI.debugl.detail[(int)so->SI.dirout].hold;
2144
2145 if (!strcasecmp (property, "DATA_REQUIRED_PATH_MARGIN"))
2146 return fitdouble(detail->clock_margin*1e-12/TTV_UNIT);
2147
2148 if (!strcasecmp (property, "DATA_VALID_PATH_MARGIN"))
2149 return fitdouble(detail->data_margin*1e-12/TTV_UNIT);
2150
2151 if (!strcasecmp (property, "INTRINSIC_MARGIN"))
2152 {
2153 if (so->setuphold)
2154 return fitdouble(-detail->margin*1e-12/TTV_UNIT);
2155 else
2156 return fitdouble(detail->margin*1e-12/TTV_UNIT);
2157 }
2158
2159 if (!strcasecmp (property, "UNCERTAINTY"))
2160 {
2161 if (so->setuphold)
2162 return fitdouble(-detail->uncertainty*1e-12/TTV_UNIT);
2163 else
2164 return fitdouble(detail->uncertainty*1e-12/TTV_UNIT);
2165 }
2166
2167 if (!strcasecmp (property, "SKEW_COMPENSATION"))
2168 {
2169 if (so->setuphold)
2170 return fitdouble(detail->skew/TTV_UNIT*1e-12);
2171 else
2172 return fitdouble(-detail->skew/TTV_UNIT*1e-12);
2173 }
2174
2175 avt_errmsg(STB_API_ERRMSG, "006", AVT_FATAL, property);
2176 // fprintf (stderr, "error: unknown property %s\n", property);
2177 return NULL;
2178 }
2179
2180 static int stb_path_is_clockpath(ttvpath_list *pth)
2181 {
2182 stbnode *n;
2183 ttvevent_list *ev;
2184 stbpair_list *pair;
2185
2186 if ((pth->TTV_MORE_SEARCH_OPTIONS & TTV_MORE_OPTIONS_MUST_BE_CLOCK)!=0
2187 || (pth->TTV_MORE_SEARCH_OPTIONS & TTV_MORE_OPTIONS_USE_CLOCK_START)!=0
2188 ) return 1;
2189 if ((pth->TTV_MORE_SEARCH_OPTIONS & TTV_MORE_OPTIONS_USE_DATA_START)!=0) return 1;
2190 if (pth->LATCH==NULL) ev=pth->NODE;
2191 else ev=pth->LATCH;
2192
2193 if (ttv_IsClock(ev->ROOT)) return 1;
2194 n=stb_getstbnode(ev);
2195 pair=stb_globalstbtab(n->STBTAB, n->NBINDEX);
2196 stb_freestbpair(pair) ;
2197 if (pair) return 0;
2198 if (n->CK!=NULL) return 1;
2199 return 0;
2200 }
2201
2202 slackobject *stb_ComputeOneSlack(int setup, ttvpath_list *data, ttvpath_list *clock, double margin, int nextcycle, int nosync)
2203 {
2204 char phase_data, phase_clock;
2205 int clockisdata=0, dataisclock=0,dirout;
2206 long oc,od, cs, ds, val, lmargin, d_valid, d_req, css, dss, movedck,pper;
2207 inffig_list *ifl;
2208 ttvfig_list *tf;
2209 slackobject *so;
2210 stbfig_list *sf;
2211 Setup_Hold_Computation_Detail_INFO *detail;
2212 Extended_Setup_Hold_Computation_Data_Item eshdi;
2213 int flags=STB_DEBUG_DIRECTIVE;
2214 slackinfo *si;
2215
2216 tf=ttv_GetSignalTopTimingFigure(data->NODE->ROOT);
2217
2218 sf=stb_getstbfig(tf);
2219
2220 if (sf==NULL) return NULL;
2221
2222 ifl=getloadedinffig(tf->INFO->FIGNAME);
2223
2224 phase_data=data->PHASE;
2225 phase_clock=clock->PHASE;
2226 if (stb_path_is_clockpath(data)) dataisclock=1, flags|=STB_DEBUG_DIRECTIVE_DATA_IS_CLOCK;
2227 if (!stb_path_is_clockpath(clock)) clockisdata=1, flags|=STB_DEBUG_DIRECTIVE_CLOCK_IS_DATA;
2228
2229 if (ifl!=NULL && ifl->LOADED.INF_FALSESLACK!=NULL)
2230 {
2231 int res;
2232 res=stb_isfalseslack(sf, data->LATCH?data->NODE:NULL, data->LATCH?data->LATCH:data->NODE, data->ROOT, clock->NODE, setup?INF_FALSESLACK_SETUP:INF_FALSESLACK_HOLD);
2233 if ((ttv_PathIsHZ(data) && (res & INF_FALSESLACK_HZ)!=0) || (!ttv_PathIsHZ(data) && (res & INF_FALSESLACK_NOTHZ)!=0)) return NULL;
2234 }
2235
2236 so=mbkalloc(sizeof(slackobject));
2237 so->setuphold=setup;
2238 so->custom=1;
2239 so->data_valid=ttv_duppath(data);
2240 so->data_required=ttv_duppath(clock);
2241 ttv_CheckTransformToIdeal(so->data_valid);
2242 ttv_CheckTransformToIdeal(so->data_required);
2243 if (so->data_valid->ROOT->TYPE & TTV_NODE_UP) dirout=1; else dirout=0;
2244 si=&so->SI;
2245 if (setup) detail=&si->debugl.detail[dirout].setup;
2246 else detail=&si->debugl.detail[dirout].hold;
2247
2248 // path margins
2249 ttv_get_path_margins(tf, so->data_valid, so->data_required, &eshdi.data_margin, &eshdi.clock_margin, &oc, &od, clockisdata, dataisclock);
2250 eshdi.common=NULL; eshdi.same_origin=0;
2251 eshdi.value=abs(oc-od);
2252 movedck=0;
2253
2254 // to do
2255 eshdi.clock_uncertainty=0;
2256
2257 // multicycle
2258 if (phase_data!=STB_NO_INDEX) od=stb_getperiod(sf, phase_data); else od=0;
2259 if (phase_clock!=STB_NO_INDEX) oc=stb_getperiod(sf, phase_clock); else oc=0;
2260
2261 stb_getmulticycleperiod(so->data_valid->LATCH?so->data_valid->LATCH:so->data_valid->NODE, so->data_valid->ROOT, od, oc, &detail->mc_setup_period, &detail->mc_hold_period, &detail->nb_setup_cycle, &detail->nb_hold_cycle);
2262 if (setup) detail->mc_hold_period=0;
2263
2264 detail->datamoved=-detail->mc_setup_period;
2265 pper=0;
2266 if (!nosync)
2267 {
2268 pper=oc;
2269 if (phase_data!=STB_NO_INDEX && phase_clock!=STB_NO_INDEX)
2270 {
2271 if (stb_cmpphase(sf, phase_clock, phase_data)<=0/*phase_clock<=phase_data*/)
2272 {
2273 detail->datamoved-=stb_synchronize_slopes(sf, phase_data, phase_clock, oc, 0);
2274 // detail->datamoved-=oc;
2275 }
2276 else if (phase_clock==phase_data && nextcycle)
2277 movedck=oc;
2278 }
2279 }
2280
2281 if (setup && -detail->datamoved+movedck!=0) eshdi.value=0;
2282 else if (!setup && -detail->datamoved+detail->mc_hold_period+movedck!=0) eshdi.value=0;
2283
2284 if (margin<0)
2285 {
2286 if (((so->data_valid->ROOT->ROOT->TYPE & (TTV_SIG_L|TTV_SIG_B))!=0) && ((so->data_required->ROOT->ROOT->TYPE & (TTV_SIG_Q|TTV_SIG_B))!=0)
2287 && ((so->data_valid->TYPE & (TTV_FIND_MAX|TTV_FIND_MIN))|(so->data_required->TYPE & (TTV_FIND_MAX|TTV_FIND_MIN)))==(TTV_FIND_MAX|TTV_FIND_MIN))
2288 {
2289 margin=ttv_GetLatchIntrinsicQuick(tf, so->data_valid->ROOT, so->data_required->ROOT, setup,NULL);
2290 }
2291 else
2292 margin=0;
2293 }
2294
2295 lmargin=_DOUBLE_TO_LONG(margin);
2296
2297 if (so->data_required->CROSSMINDELAY!=TTV_NOTIME) cs=so->data_required->CROSSMINDELAY; else cs=so->data_required->DELAYSTART;
2298 css=cs;
2299 cs+=so->data_required->DELAY+so->data_required->DATADELAY+movedck;
2300 if (so->data_valid->CROSSMINDELAY!=TTV_NOTIME) ds=so->data_valid->CROSSMINDELAY; else ds=so->data_valid->DELAYSTART;
2301 dss=ds;
2302 ds+=so->data_valid->DELAY+so->data_valid->DATADELAY+detail->datamoved;
2303 if (setup)
2304 val=(cs+eshdi.clock_margin-eshdi.clock_uncertainty)-(ds+eshdi.data_margin)-lmargin+eshdi.value;
2305 else
2306 val=(ds+eshdi.data_margin)+detail->mc_hold_period-(cs+eshdi.clock_margin+lmargin-pper+eshdi.clock_uncertainty)+eshdi.value;
2307
2308 stb_setdetail(detail, val, ds, cs, lmargin, setup?0:pper, setup?0:detail->mc_hold_period, &eshdi, flags, phase_data, movedck);
2309
2310 si->debugl.SIG1_EVENT=so->data_valid->LATCH?so->data_valid->LATCH:so->data_valid->NODE;
2311 si->debugl.SIG1=si->debugl.SIG1_EVENT->ROOT;
2312 si->debugl.SIG2=so->data_valid->ROOT->ROOT;
2313 si->debugl.PERIODE=oc;
2314 si->debugl.CKNAME=si->debugl.CMDNAME=NULL;
2315 si->debugl.CMD_EVENT=so->data_valid->CMD;
2316 si->debugl.MARGESETUP=si->debugl.MARGEHOLD=lmargin;
2317 si->debugl.SETUP=setup?val:STB_NO_TIME;
2318 si->debugl.HOLD=!setup?val:STB_NO_TIME;
2319 si->debugl.START_CMD_EVENT=so->data_valid->CMDLATCH?so->data_valid->CMDLATCH:NULL;
2320 si->debugl.HOLDPERIOD=detail->mc_hold_period+oc;
2321
2322 d_valid=detail->instab+detail->data_margin;
2323 if (setup)
2324 d_req=detail->clock+detail->clock_margin-detail->margin+detail->skew;
2325 else
2326 {
2327 d_req=detail->clock+detail->clock_margin+detail->margin-detail->period-detail->skew;
2328 d_valid+=detail->misc;
2329 }
2330
2331 // correction pour multicycle sur le required
2332 d_valid+=-detail->datamoved-detail->mc_hold_period;
2333 d_req+=-detail->datamoved-detail->mc_hold_period;
2334
2335 si->slack=_LONG_TO_DOUBLE(detail->VALUE);
2336
2337 si->datavalid=_LONG_TO_DOUBLE(d_valid);
2338 si->lag=_LONG_TO_DOUBLE(data->DATADELAY);
2339 /* if (ttv_IsClock(so->data_valid->NODE->ROOT)) si->datavalidclock=dss; else si->datavalidclock=-1;
2340 si->datavalidclockdir=(so->data_valid->NODE->TYPE==TTV_NODE_UP)?1:0;*/
2341
2342 if (si->debugl.PERIODE==STB_NO_TIME) si->period=-1; else si->period=_LONG_TO_DOUBLE(si->debugl.PERIODE);
2343 si->datareq=_LONG_TO_DOUBLE(d_req);
2344 si->path=so->data_valid;
2345 si->dirout=dirout;
2346 si->dirin=(so->data_valid->NODE->TYPE & TTV_NODE_UP)?1:0;
2347 si->access=so->data_valid->LATCH?1:0;
2348 si->hzpath=ttv_PathIsHZ(so->data_valid)?1:0;
2349 si->phase=phase_data;
2350 si->flags=detail->flags;
2351
2352 so->data_required->DELAYSTART+=-detail->datamoved-detail->misc+detail->moved_clock_period;
2353 if (!setup) so->data_required->DELAYSTART-=detail->period;
2354 return so;
2355 }
2356
2357 void stb_DisplaySlackReport_sub2(FILE *f, chain_list *solist, int number, char *mode)
2358 {
2359 int setup=1, hold=1, sum=0, simple=0;
2360 char *tok, *c;
2361 char buf[256];
2362 int addit=0;
2363 chain_list *cl, *ch;
2364
2365 if (f==NULL) return;
2366
2367 if (number<=0) number=INT_MAX;
2368
2369 if (ftello(f)==0 && solist!=NULL)
2370 {
2371 ttvfig_list *tvf;
2372 tvf=ttv_GetSignalTopTimingFigure(((slackobject *)solist->DATA)->SI.debugl.SIG2);
2373 ttv_DumpHeader(f, tvf);
2374 }
2375
2376 strcpy(buf, mode);
2377 tok=strtok_r(buf, " ", &c);
2378
2379 while (tok!=NULL)
2380 {
2381 if (strcasecmp(tok,"setup")==0) hold=0;
2382 else if (strcasecmp(tok,"hold")==0) setup=0;
2383 else if (strcasecmp(tok,"all")==0) setup=hold=1;
2384 else if (strcasecmp(tok,"summary")==0) sum=1;
2385 else if (strcasecmp(tok,"margins")==0) addit|=1;
2386 else if (strcasecmp(tok,"thru")==0) addit|=2;
2387 else if (strcasecmp(tok,"simple")==0) simple=1;
2388 else //avt_error("stbapi", 2, AVT_ERR, "stb_DisplaySlackReport: unknown mode '%s'\n", tok);
2389 avt_errmsg(STB_API_ERRMSG, "002", AVT_ERROR, tok);
2390 tok=strtok_r(NULL, " ", &c);
2391 }
2392
2393 if (setup)
2394 {
2395 ch=NULL;
2396 for (cl=solist; cl!=NULL; cl=cl->NEXT)
2397 if (((slackobject *)cl->DATA)->setuphold) ch=addchain(ch, cl->DATA);
2398 ch=reverse(ch);
2399 if (ch!=NULL)
2400 __stb_DisplaySlackReport_grab(f, NULL, NULL, NULL, "??", 1, 0, sum, number, addit,0, ch, simple);
2401 freechain(ch);
2402 }
2403
2404 if (hold)
2405 {
2406 ch=NULL;
2407 for (cl=solist; cl!=NULL; cl=cl->NEXT)
2408 if (!((slackobject *)cl->DATA)->setuphold) ch=addchain(ch, cl->DATA);
2409 ch=reverse(ch);
2410 if (ch!=NULL)
2411 __stb_DisplaySlackReport_grab(f, NULL, NULL, NULL, "??", 0, 0, sum, number, addit,0, ch, simple);
2412 freechain(ch);
2413 }
2414 }
2415
2416 void stb_DisplayCoverage_sub(FILE *f, stbfig_list *sf, int detail)
2417 {
2418 enum
2419 {
2420 ___LATCH,
2421 ___PRECH,
2422 ___DIRECT,
2423 ___BREAK,
2424 ___OUTPUT,
2425 ___LAST
2426 };
2427
2428 int a, i, k;
2429 char *name, dir;
2430 Board *b;
2431 struct
2432 {
2433 int totsig, totsetup, tothold, totevent;
2434 int totrise, totfall, minus, realtot;
2435 } res[___LAST];
2436
2437 char *label[___LAST]={"Latchs","Precharges","Directives","Breakpoints","Outputs"};
2438
2439 chain_list *cl;
2440 ttvevent_list *tve;
2441 stbnode *sn;
2442 ttv_directive *sd;
2443
2444 #define DC_COL_DIR 0
2445 #define DC_COL_NAME 1
2446 #define DC_COL_SETUP 2
2447 #define DC_COL_HOLD 3
2448 #define DC_COL_DATA 4
2449 #define DC_COL_CLOCK 5
2450 #define DC_COL_SPECOUT 6
2451
2452 if (f==NULL) return;
2453
2454 if (ftello(f)==0)
2455 ttv_DumpHeader(f, sf->FIG);
2456
2457 fprintf(f," *** Coverage Report ***\n\n");
2458
2459 for (a=0; a<___LAST; a++)
2460 res[a].totsig=res[a].totsetup=res[a].tothold=res[a].totevent=res[a].totrise=res[a].totfall=res[a].minus=res[a].realtot=0;
2461
2462 for (cl=sf->NODE; cl!=NULL; cl=cl->NEXT)
2463 {
2464 tve=(ttvevent_list *)cl->DATA;
2465 sn=stb_getstbnode(tve);
2466 a=-1;
2467 if (tve->ROOT->TYPE & TTV_SIG_R)
2468 a=___PRECH;
2469 else if (tve->ROOT->TYPE & TTV_SIG_L)
2470 a=___LATCH;
2471 else if ((tve->ROOT->TYPE & TTV_SIG_C)!=0
2472 && (tve->ROOT->TYPE & TTV_SIG_CI)!=TTV_SIG_CI
2473 && (tve->ROOT->TYPE & TTV_SIG_CX)!=TTV_SIG_CX
2474 )
2475 a=___OUTPUT;
2476 else if ((tve->ROOT->TYPE & TTV_SIG_B)!=0)
2477 a=___BREAK;
2478
2479 if (a!=-1 && (tve->TYPE & TTV_NODE_UP)!=0)
2480 res[a].realtot++;
2481
2482 if (a==___OUTPUT)
2483 {
2484 if (sn->SPECOUT==NULL) k=sn->NBINDEX;
2485 else
2486 for (k=0; k<sn->NBINDEX && sn->SPECOUT[k]==NULL; k++) ;
2487 if (k>=sn->NBINDEX)
2488 a=-1;
2489 }
2490 else if (a==___BREAK)
2491 {
2492 if (getptype(tve->ROOT->NODE[0].USER, STB_BREAK_TEST_EVENT)==NULL
2493 && getptype(tve->ROOT->NODE[1].USER, STB_BREAK_TEST_EVENT)==NULL)
2494 a=-1;
2495 }
2496
2497
2498 if (a!=-1)
2499 {
2500 if (tve->TYPE & TTV_NODE_UP) res[a].totsig++;
2501
2502 if (sn->SETUP!=STB_NO_TIME && sn->HOLD!=STB_NO_TIME)
2503 {
2504 if (tve->TYPE & TTV_NODE_UP) res[a].totrise++;
2505 else res[a].totfall++;
2506 }
2507
2508 if (sn->SETUP!=STB_NO_TIME || sn->HOLD!=STB_NO_TIME)
2509 {
2510 if (sn->SETUP!=STB_NO_TIME) res[a].totsetup++;
2511 if (sn->HOLD!=STB_NO_TIME) res[a].tothold++;
2512 res[a].totevent++;
2513 }
2514 }
2515
2516 a=-1;
2517 if ((sd=ttv_get_directive(tve->ROOT))!=NULL)
2518 {
2519 while (sd!=NULL && sd->filter) sd=sd->next;
2520 if (sd!=NULL) a=___DIRECT;
2521 }
2522
2523 if (a!=-1)
2524 {
2525 if (tve->TYPE & TTV_NODE_UP) res[a].totsig++;
2526
2527 if (sn->SETUP!=STB_NO_TIME && sn->HOLD!=STB_NO_TIME)
2528 {
2529 if (tve->TYPE & TTV_NODE_UP) res[a].totrise++;
2530 else res[a].totfall++;
2531 }
2532
2533 if (sn->SETUP!=STB_NO_TIME || sn->HOLD!=STB_NO_TIME)
2534 {
2535 if (sn->SETUP!=STB_NO_TIME) res[a].totsetup++;
2536 if (sn->HOLD!=STB_NO_TIME) res[a].tothold++;
2537 res[a].totevent++;
2538 }
2539 }
2540 }
2541
2542 for (i=0; i<___LAST; i++)
2543 {
2544 int nbev;
2545 fprintf(f,"\n_________ %s coverage\n", label[i]);
2546 if (i==___PRECH) nbev=res[i].totsig;
2547 else nbev=res[i].totsig*2;
2548 fprintf(f," total = %d signals\n", res[i].realtot);
2549 fprintf(f," total to check = %d signals (%d events)\n", res[i].totsig, nbev);
2550 if (res[i].totsig>0)
2551 {
2552 fprintf(f," event setups = %d (%.1f%%)\n", res[i].totsetup, res[i].totsetup*100.0/nbev);
2553 fprintf(f," event holds = %d (%.1f%%)\n", res[i].tothold, res[i].tothold*100.0/nbev);
2554 if (i!=___PRECH)
2555 fprintf(f," event rising = %d (%.1f%%)\n", res[i].totrise, res[i].totrise*100.0/res[i].totsig);
2556
2557 fprintf(f," event falling = %d (%.1f%%)\n", res[i].totfall, res[i].totfall*100.0/res[i].totsig);
2558
2559 if (detail)
2560 {
2561 fprintf(f,"\n ** DETAIL **\n");
2562 b=Board_CreateBoard();
2563 Board_SetSize(b, DC_COL_DIR, 4, 'l');
2564 Board_SetSize(b, DC_COL_NAME, 5, 'l');
2565 Board_SetSize(b, DC_COL_SETUP, 8, 'r');
2566 Board_SetSize(b, DC_COL_HOLD, 8, 'r');
2567 Board_SetSize(b, DC_COL_DATA, 8, 'r');
2568 Board_SetSize(b, DC_COL_CLOCK, 8, 'r');
2569 if (i==___OUTPUT || i==___BREAK) Board_SetSize(b, DC_COL_SPECOUT, 8, 'r');
2570 // Board_SetValue(b, DC_COL_DIR, 4, 'l');
2571 Board_NewLine(b);
2572 Board_SetValue(b, DC_COL_NAME, "Node Name");
2573 Board_SetValue(b, DC_COL_SETUP, "Setup");
2574 Board_SetValue(b, DC_COL_HOLD, "Hold");
2575 Board_SetValue(b, DC_COL_DATA, "Data");
2576 Board_SetValue(b, DC_COL_CLOCK, "Clock");
2577 Board_SetValue(b, DC_COL_SPECOUT, i==___OUTPUT?"OutSpec":"Constraint");
2578
2579 Board_NewSeparation(b);
2580 for (cl=sf->NODE; cl!=NULL; cl=cl->NEXT)
2581 {
2582 tve=(ttvevent_list *)cl->DATA;
2583 if (i==___PRECH && (tve->TYPE & TTV_NODE_UP)!=0) continue;
2584 sn=stb_getstbnode(tve);
2585 a=-1;
2586 if (tve->ROOT->TYPE & TTV_SIG_R)
2587 a=___PRECH;
2588 else if (tve->ROOT->TYPE & TTV_SIG_L)
2589 a=___LATCH;
2590 else if ((tve->ROOT->TYPE & TTV_SIG_C)!=0
2591 && (tve->ROOT->TYPE & TTV_SIG_CI)!=TTV_SIG_CI
2592 && (tve->ROOT->TYPE & TTV_SIG_CX)!=TTV_SIG_CX
2593 )
2594 a=___OUTPUT;
2595 else if (tve->ROOT->TYPE & TTV_SIG_B &&
2596 (getptype(tve->ROOT->NODE[0].USER, STB_BREAK_TEST_EVENT)!=NULL
2597 || getptype(tve->ROOT->NODE[1].USER, STB_BREAK_TEST_EVENT)!=NULL))
2598 a=___BREAK;
2599
2600 if (i==___DIRECT && ttv_get_directive(tve->ROOT)!=NULL)
2601 a=___DIRECT;
2602
2603 if (a==i && (sn->SETUP==STB_NO_TIME || sn->HOLD==STB_NO_TIME))
2604 {
2605 char buf[5];
2606 dir=dirconv(tve->TYPE & TTV_NODE_UP?'u':'d');
2607 sprintf(buf,"(%c)",dir);
2608 Board_NewLine(b);
2609 Board_SetValue(b, DC_COL_DIR, buf);
2610 Board_SetValue(b, DC_COL_NAME, ttv_GetFullSignalName_COND (sf->FIG, tve->ROOT));
2611 Board_SetValue(b, DC_COL_SETUP, sn->SETUP!=STB_NO_TIME?"yes":"no");
2612 Board_SetValue(b, DC_COL_HOLD, sn->HOLD!=STB_NO_TIME?"yes":"no");
2613 Board_SetValue(b, DC_COL_CLOCK, sn->CK!=NULL?"yes":"no");
2614 if (sn->STBTAB==NULL) k=sn->NBINDEX;
2615 else
2616 for (k=0; k<sn->NBINDEX && sn->STBTAB[k]==NULL; k++) ;
2617 Board_SetValue(b, DC_COL_DATA, k>=sn->NBINDEX?"no":"yes");
2618
2619 if (a==___OUTPUT)
2620 {
2621 if (sn->SPECOUT==NULL) k=sn->NBINDEX;
2622 else
2623 for (k=0; k<sn->NBINDEX && sn->SPECOUT[k]==NULL; k++) ;
2624 Board_SetValue(b, DC_COL_SPECOUT, k>=sn->NBINDEX?"no":"yes");
2625 }
2626 else
2627 {
2628 Board_SetValue(b, DC_COL_SPECOUT, getptype(tve->USER, STB_BREAK_TEST_EVENT)==NULL?"no":"yes");
2629 }
2630 }
2631 }
2632 Board_NewSeparation(b);
2633 Board_Display(f, b, " ");
2634 Board_FreeBoard(b);
2635 }
2636 }
2637 fprintf(f,"\n");
2638 }
2639
2640 }