Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / api / ttv / ttv_API_path_functions.c
1 #include STM_H
2 #include TTV_H
3 #include MLU_H
4 #include MUT_H
5 #include INF_H
6 #include EFG_H
7 #include TAS_H
8 #include TRC_H
9 #include YAG_H
10 #include MCC_H
11 #include STB_H
12
13 #include AVT_H
14 #define API_USE_REAL_TYPES
15 #include "ttv_API_LOCAL.h"
16 #include "ttv_API.h"
17 #include "ttv_API_display.h"
18 #include "ttv_API_util.h"
19
20
21 static void recur_run(ttvfig_list *tvf, long slopein, ttvevent_list *a, chain_list *nextnodelist, chain_list **lst, chain_list **config, char dirend, long minmax, chain_list **allsearch)
22 {
23 ttvpath_list *path_list, *pth;
24 ttvsig_list *tvsend, *tvs2;
25 long slopeout, findcmd=0, savelastslope;
26 char dir[3]=" ?";
27 int doaccess;
28 chain_list *cl, *savenodelist, *ch;
29
30 dir[0]=ttv_GetTimingEventDirection(a);
31
32 if (nextnodelist!=NULL)
33 {
34 savelastslope=TTV_PROPAGATE_FORCED_SLOPE;
35 if (slopein!=0) TTV_PROPAGATE_FORCED_SLOPE=slopein;
36
37 cl=(chain_list *)nextnodelist->DATA;
38 nextnodelist=nextnodelist->NEXT;
39 if (cl!=NULL && cl->DATA==NULL) doaccess=1, cl=cl->NEXT;
40 else doaccess=0;
41
42 while (cl!=NULL)
43 {
44 tvsend=(ttvsig_list *)cl->DATA;
45
46 // un access ?
47 if (doaccess && nextnodelist!=NULL && (tvsend->TYPE & (TTV_SIG_L|TTV_SIG_B))!=0)
48 {
49 savenodelist=nextnodelist;
50 ch=(chain_list *)nextnodelist->DATA;
51 nextnodelist=nextnodelist->NEXT;
52 if (ch!=NULL && ch->DATA==NULL) ch=ch->NEXT;
53
54 while (ch!=NULL)
55 {
56 tvs2=(ttvsig_list *)ch->DATA;
57
58 if((a->ROOT->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
59 {
60 a->ROOT->NODE->TYPE |= TTV_NODE_STOP ;
61 (a->ROOT->NODE+1)->TYPE |= TTV_NODE_STOP ;
62 if ((a->ROOT->TYPE & TTV_SIG_N) != 0)
63 TTV_MORE_SEARCH_OPTIONS|=TTV_MORE_OPTIONS_ENABLE_STOP_ON_TTV_SIG_N;
64 }
65 if ((a->ROOT->TYPE & TTV_SIG_Q) != 0)
66 findcmd=TTV_FIND_CMD;
67
68 // pour que les falsepaths s'appliquent
69 if ((tvs2->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
70 {
71 tvs2->NODE->TYPE|=TTV_NODE_STOP ;
72 (tvs2->NODE+1)->TYPE|=TTV_NODE_STOP ;
73 }
74
75 TTV_QUIET_MODE=1;
76 path_list=ttv_getsigaccesslist (tvf, tvsend, tvs2, a->ROOT, dir, 0, minmax|findcmd, 0, 0);
77 TTV_QUIET_MODE=0;
78
79 if((a->ROOT->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
80 {
81 a->ROOT->NODE->TYPE &= ~TTV_NODE_STOP ;
82 (a->ROOT->NODE+1)->TYPE &= ~TTV_NODE_STOP ;
83 if ((a->ROOT->TYPE & TTV_SIG_N) != 0)
84 TTV_MORE_SEARCH_OPTIONS&=~TTV_MORE_OPTIONS_ENABLE_STOP_ON_TTV_SIG_N;
85 }
86
87 // pour que les falsepaths s'appliquent
88 if ((tvs2->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
89 {
90 tvs2->NODE->TYPE&=~TTV_NODE_STOP ;
91 (tvs2->NODE+1)->TYPE&=~TTV_NODE_STOP ;
92 }
93
94
95 if (path_list!=NULL)
96 {
97 *allsearch=addchain(*allsearch, path_list);
98
99 for (pth=path_list; pth!=NULL; pth=pth->NEXT)
100 {
101 if (!(nextnodelist!=NULL && ttv_PathIsHZ(pth)))
102 {
103 *lst=addchain(*lst, pth);
104
105 slopeout=pth->SLOPE;
106 recur_run(tvf, slopeout, pth->ROOT, nextnodelist, lst, config, dirend, minmax, allsearch);
107
108 *lst=delchain(*lst, *lst);
109 }
110 }
111 }
112 ch=ch->NEXT;
113 }
114 nextnodelist=savenodelist;
115 }
116
117 if (!doaccess)
118 {
119 // un path?
120 if((a->ROOT->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
121 {
122 a->ROOT->NODE->TYPE |= TTV_NODE_STOP ;
123 (a->ROOT->NODE+1)->TYPE |= TTV_NODE_STOP ;
124 if ((a->ROOT->TYPE & TTV_SIG_N) != 0)
125 TTV_MORE_SEARCH_OPTIONS|=TTV_MORE_OPTIONS_ENABLE_STOP_ON_TTV_SIG_N;
126 }
127 if ((a->ROOT->TYPE & TTV_SIG_Q) != 0)
128 findcmd=TTV_FIND_CMD;
129
130 // pour que les falsepaths s'appliquent
131 if ((tvsend->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
132 {
133 tvsend->NODE->TYPE|=TTV_NODE_STOP ;
134 (tvsend->NODE+1)->TYPE|=TTV_NODE_STOP ;
135 }
136
137 path_list=ttv_getcritic_pathlist (tvf, a->ROOT, tvsend, dir, 0, minmax|findcmd, 0, 0, 0);
138
139 if((a->ROOT->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
140 {
141 a->ROOT->NODE->TYPE &= ~TTV_NODE_STOP ;
142 (a->ROOT->NODE+1)->TYPE &= ~TTV_NODE_STOP ;
143 if ((a->ROOT->TYPE & TTV_SIG_N) != 0)
144 TTV_MORE_SEARCH_OPTIONS&=~TTV_MORE_OPTIONS_ENABLE_STOP_ON_TTV_SIG_N;
145 }
146
147 // pour que les falsepaths s'appliquent
148 if ((tvsend->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
149 {
150 tvsend->NODE->TYPE&=~TTV_NODE_STOP ;
151 (tvsend->NODE+1)->TYPE&=~TTV_NODE_STOP ;
152 }
153
154 if (path_list!=NULL)
155 {
156 *allsearch=addchain(*allsearch, path_list);
157
158 for (pth=path_list; pth!=NULL; pth=pth->NEXT)
159 {
160 if (!(nextnodelist!=NULL && ttv_PathIsHZ(pth)))
161 {
162 *lst=addchain(*lst, pth);
163
164 slopeout=pth->SLOPE;
165 recur_run(tvf, slopeout, pth->ROOT, nextnodelist, lst, config, dirend, minmax, allsearch);
166
167 *lst=delchain(*lst, *lst);
168 }
169 }
170 }
171 }
172 cl=cl->NEXT;
173 }
174 TTV_PROPAGATE_FORCED_SLOPE=savelastslope;
175 }
176 else
177 {
178 if (dirend=='?' || dirend==dir[0])
179 *config=addchain(*config, reverse(dupchainlst(*lst)));
180 }
181 }
182
183 // renvoie le front d'ouverture le plus tard ou tot selon le type de recherche
184 static ttvevent_list *getgoodclockevent(stbfig_list *stbfig, ttvevent_list *latch, long type)
185 {
186 long lastopen, open, move;
187 ttvevent_list *tve=NULL, *cmd;
188 stbck *ck;
189 stbnode *node;
190 chain_list *cmds=NULL, *cl;
191
192 node=stb_getstbnode(latch);
193 if (node!=NULL)
194 {
195 // stb_getlatchslope modifie la structure donc on garde une liste a part
196 for (ck=node->CK; ck!=NULL; ck=ck->NEXT) cmds=addchain(cmds, ck->CMD);
197
198 for (cl=cmds; cl!=NULL; cl=cl->NEXT)
199 {
200 cmd=(ttvevent_list *)cl->DATA;
201 if (cmd!=NULL)
202 {
203 if ((type & TTV_FIND_MAX)==TTV_FIND_MAX)
204 {
205 stb_getlatchslope(stbfig,latch,cmd,&open,NULL,NULL,NULL,NULL,1,STB_NO_INDEX,&move);
206 if (tve==NULL || lastopen<open) lastopen=open, tve=cmd;
207 }
208 else
209 {
210 stb_getlatchslope(stbfig,latch,cmd,NULL,&open,NULL,NULL,NULL,1,STB_NO_INDEX,&move);
211 if (tve==NULL || open>lastopen) lastopen=open, tve=cmd;
212 }
213 }
214 }
215 freechain(cmds);
216 }
217 return tve;
218 }
219
220 #define CLIPCTK 0x0fab1
221 #define CLIPREF 0x0fab2
222
223 static void performstbclipping(ttvfig_list *tvf, chain_list *head, long type)
224 {
225 ttvpath_list *tph;
226 long lastopen=TTV_NOTIME, lastclose;
227 long openmax, openmin, closemax, closemin, period, deltaref, deltactk, open, close, move;
228 long timeref=0, timectk=0, err;
229 chain_list *cl;
230 ttvevent_list *tve, *newtve;
231 stbfig_list *stbfig=NULL;
232 ptype_list *pt;
233
234 if ((stbfig=stb_getstbfig(tvf))==NULL) return;
235
236 for (cl=head; cl!=NULL && cl->NEXT!=NULL; cl=cl->NEXT)
237 {
238 tph=(ttvpath_list *)cl->DATA;
239 timectk+=tph->DELAY;
240 timeref+=tph->REFDELAY;
241
242
243 if ((tve=ttv_GetPathCommand(tph))!=NULL)
244 {
245 if ((newtve=getgoodclockevent(stbfig, tph->ROOT, type))!=NULL)
246 tve=newtve;
247 stb_getlatchslope(stbfig,tph->ROOT,tve,&openmax,&openmin,&closemax,&closemin,&period,1,STB_NO_INDEX,&move);
248 if ((type & TTV_FIND_MAX)==0) openmax=openmin, closemax=closemin;
249
250 if (lastopen==TTV_NOTIME)
251 {
252 timeref=timectk=0;
253 }
254 else
255 {
256 if (openmax<lastopen)
257 {
258 open=openmax+period-lastopen, close=closemax+period-lastopen;
259 }
260 else
261 {
262 open=openmax-lastopen, close=closemax-lastopen;
263 }
264 if (timeref<open) deltaref=open-timeref; else deltaref=0;
265 if (timectk<open) deltactk=open-timectk; else deltactk=0;
266 if (timeref>close || timectk>close)
267 {
268 err=timeref-close;
269 if (timectk-close>err) err=timectk-close;
270 avt_errmsg(TTV_API_ERRMSG, "033", AVT_WARNING, ttv_GetFullSignalName_COND(tvf, tph->ROOT->ROOT), err/TTV_UNIT);
271 // avt_error("ttvapi", -1, AVT_WAR, "stability error found at node %s: data too late by %.1fps\n", ttv_GetFullSignalName_COND(tvf, tph->ROOT->ROOT), err/TTV_UNIT);
272 if (timeref>close) timeref=close;
273 if (timectk>close) timectk=close;
274 }
275 if ((pt=getptype(tph->USER, CLIPCTK))==NULL) pt=tph->USER=addptype(tph->USER, CLIPCTK, 0);
276 pt->DATA=(void *)deltactk;
277 if ((pt=getptype(tph->USER, CLIPREF))==NULL) pt=tph->USER=addptype(tph->USER, CLIPREF, 0);
278 pt->DATA=(void *)deltaref;
279
280 timeref=timeref+deltaref-open;
281 timectk=timectk+deltactk-open;
282 }
283
284 lastopen=openmax;
285 lastclose=closemax;
286 }
287 }
288 }
289
290 static long getdatadelta(ttvpath_list *pth, long type)
291 {
292 ptype_list *pt;
293 if ((pt=getptype(pth->USER, type))!=NULL)
294 return (long)pt->DATA;
295 else
296 return 0;
297 }
298 // retourne le delay total ref ou normal
299 static double getconfigdelay(chain_list *head, char type, double *slope)
300 {
301 ttvpath_list *tph;
302 double delay=0;
303 chain_list *cl;
304 for (cl=head; cl!=NULL; cl=cl->NEXT)
305 {
306 tph=(ttvpath_list *)cl->DATA;
307 switch(type)
308 {
309 case 'n': delay+=ttv_GetPathDelay(tph)+getdatadelta(tph, CLIPCTK)*1e-12/TTV_UNIT; break;
310 case 'r': delay+=ttv_GetPathRefDelay(tph)+getdatadelta(tph, CLIPREF)*1e-12/TTV_UNIT; break;
311 }
312 }
313 switch(type)
314 {
315 case 'n': *slope=ttv_GetPathSlope(tph); break;
316 case 'r': *slope=ttv_GetPathRefSlope(tph); break;
317 }
318 return delay;
319 }
320
321 // recupere le min ou max des paths pour une config de l'e/s
322 static void removebadconfig(chain_list *headconfig, char dirstart, char dirend, long search)
323 {
324 chain_list *lastconfig=NULL, *cl, *ch;
325 double lastdelay, thisdelay, slope;
326 ttvpath_list *tph, *lastfirstpath=NULL, *fpt;
327 int max;
328
329 if ((search & TTV_FIND_MAX)!=0) max=1; else max=0;
330
331 for (cl=headconfig; cl!=NULL; cl=cl->NEXT)
332 {
333 if (cl->DATA!=NULL)
334 {
335 ch=(chain_list *)cl->DATA;
336 fpt=tph=(ttvpath_list *)ch->DATA;
337 if (ttv_GetPathStartDirection(tph)==dirstart)
338 {
339 while (ch->NEXT!=NULL) ch=ch->NEXT;
340 tph=(ttvpath_list *)ch->DATA;
341 if (ttv_GetPathEndDirection(tph)==dirend)
342 {
343 thisdelay=getconfigdelay((chain_list *)cl->DATA, 'n', &slope);
344 if (lastconfig==NULL || (max && thisdelay>lastdelay) || (!max && thisdelay<lastdelay))
345 {
346 if (lastconfig!=NULL) { freechain((chain_list *)lastconfig->DATA); lastconfig->DATA=NULL; }
347 lastconfig=cl;
348 lastfirstpath=fpt;
349 }
350 }
351 }
352 }
353 }
354 }
355
356 // cree un path global pour une config
357 static ttvpath_list *buildconfigpath(chain_list *config, ttvpath_list *last)
358 {
359 chain_list *ch;
360 double delay, delayref, slope, sloperef;
361 ttvpath_list *pt, *newpth, *ptend;
362
363 ch=config;
364 pt=(ttvpath_list *)ch->DATA;
365 while (ch->NEXT!=NULL) ch=ch->NEXT;
366 ptend=(ttvpath_list *)ch->DATA;
367
368 delay=getconfigdelay(config, 'n', &slope);
369 delayref=getconfigdelay(config, 'n', &sloperef);
370
371 newpth=ttv_allocpath(last,
372 pt->FIG,
373 ptend->ROOT,
374 pt->NODE,
375 ptend->CMD,
376 pt->LATCH,
377 pt->CMDLATCH,
378 NULL, // latch list
379 pt->DATADELAY,
380 pt->ACCESS,
381 pt->REFACCESS,
382 pt->TYPE,
383 mbk_long_round(delayref*1e12*TTV_UNIT),
384 mbk_long_round(sloperef*1e12*TTV_UNIT),
385 mbk_long_round(delay*1e12*TTV_UNIT),
386 mbk_long_round(slope*1e12*TTV_UNIT),
387 pt->DELAYSTART,
388 pt->SLOPESTART,
389 NULL,
390 NULL,
391 pt->CROSSMINDELAY,
392 pt->PHASE,
393 pt->CLOCKPATHDELAY
394 ) ;
395
396 return newpth;
397 }
398
399 // cree un detail global pour une config
400 static ttvcritic_list *buildconfigdetail(chain_list *config)
401 {
402 chain_list *ch;
403 ttvpath_list *pt;
404 ttvcritic_list *tc, *newtc=NULL, *emptytc;
405
406 for (ch=config; ch!=NULL; ch=ch->NEXT)
407 {
408 pt=(ttvpath_list *)ch->DATA;
409 for (tc=pt->CRITIC; tc!=NULL; tc=tc->NEXT)
410 {
411 if (!(ch!=config && tc==pt->CRITIC))
412 {
413 emptytc=ttv_alloccritic(
414 NULL,
415 tc->FIG,
416 NULL,
417 pt->ROOT,
418 0,
419 0,
420 0,
421 0,
422 0,
423 0,
424 0,
425 NULL,
426 NULL
427 ) ;
428 if ((emptytc->NODE_FLAG & TTV_NODE_FLAG_NOALLOC)==0)
429 {
430 mbkfree(emptytc->NAME);
431 mbkfree(emptytc->NETNAME);
432 }
433 memcpy(emptytc, tc, sizeof(*tc));
434 emptytc->USER=NULL;
435 if (tc->NEXT==NULL)
436 {
437 emptytc->DELAY+=getdatadelta(pt, CLIPCTK);
438 emptytc->REFDELAY+=getdatadelta(pt, CLIPREF);
439 }
440 if ((tc->NODE_FLAG & TTV_NODE_FLAG_NOALLOC)==0)
441 {
442 emptytc->NAME=mbkstrdup(tc->NAME);
443 emptytc->NETNAME=mbkstrdup(tc->NETNAME);
444 }
445 emptytc->NEXT=newtc;
446 newtc=emptytc;
447 }
448 }
449 }
450 return (ttvcritic_list *)reverse((chain_list *)newtc);
451 }
452
453 static chain_list *filterpath(chain_list *lst, int max)
454 {
455 chain_list *cl;
456 int i;
457
458 if (max!=0)
459 {
460 for(cl=lst, i=1; i<max && cl!=NULL ; cl=cl->NEXT , i++) ;
461 if(cl!=NULL)
462 {
463 ttv_FreePathList(cl->NEXT);
464 freechain(cl->NEXT);
465 cl->NEXT=NULL;
466 }
467 }
468 return lst;
469 }
470
471 static void freedoublechain(chain_list *cl)
472 {
473 while (cl!=NULL)
474 {
475 freechain((chain_list *)cl->DATA);
476 cl=delchain(cl, cl);
477 }
478 }
479
480 chain_list *ttv_ProbeDelay_sub(ttvfig_list *tvf, double slopein, chain_list *nodenamelist, char *dir, int nbpath, char *path_or_access, char *minmax, int nosync, int noprop)
481 {
482 chain_list *cl, *mask, *nodelist, *ch, *allsearch=NULL, *ch0;
483 ttvpath_list *path_list, *pth;
484 ttvsig_list *tvs;
485 long minmax_i=1;
486 chain_list *config=NULL, *nlist;
487 char *oldmode, d0, d1;
488 int oldprop, path, cnt;
489 long lastslope=mbk_long_round(slopein*1e12*TTV_UNIT);
490 long oldexstart, oldexend, mode;
491
492 API_TEST_TOKEN_SUB(TMA_API,"tma")
493
494 if (nbpath<0) nbpath=0;
495
496 if (!strcasecmp (minmax, "max")) minmax_i = TTV_FIND_MAX;
497 else if (!strcasecmp (minmax, "min")) minmax_i = TTV_FIND_MIN;
498 else
499 {
500 avt_errmsg(TTV_API_ERRMSG, "022", AVT_ERROR);
501 // fprintf (stderr, "ttv_ProbeDelay: error: available values for 'minmax' are 'min' or 'max'\n");
502 return NULL;
503 }
504
505 if (!strcasecmp (path_or_access, "path")) path=1;
506 else if (!strcasecmp (path_or_access, "access")) path=0;
507 else if (strcasecmp (path_or_access, "-")!=0)
508 {
509 avt_errmsg(TTV_API_ERRMSG, "024", AVT_ERROR);
510 // fprintf (stderr, "ttv_ProbeDelay: error: available values for 'path_or_access' are 'path' or 'access'\n");
511 return NULL;
512 }
513 else path=-1;
514
515 if (path==1 && countchain(nodenamelist)<2)
516 {
517 avt_errmsg(TTV_API_ERRMSG, "035", AVT_ERROR, 2);
518 //fprintf (stderr, "ttv_ProbeDelay: at least 2 node names are required for the function to run\n");
519 return NULL;
520 }
521
522 if (path==0 && countchain(nodenamelist)<3)
523 {
524 avt_errmsg(TTV_API_ERRMSG, "035", AVT_ERROR, 3);
525 // fprintf (stderr, "ttv_ProbeDelay: at least 3 node names are required for the function to run\n");
526 return NULL;
527 }
528
529 if (tvf==NULL) return NULL;
530
531 // ttv_checkinfchange(tvf);
532 if ((ttv_getloadedfigtypes(tvf) & TTV_FILE_DTX)==TTV_FILE_DTX) mode=TTV_FILE_DTX;
533 else mode=TTV_FILE_TTX;
534
535 for (cl=nodenamelist, nodelist=NULL; cl!=NULL; cl=cl->NEXT)
536 {
537 char *var=(char *)cl->DATA;
538 unsigned int i, access=0;
539 const char *as="-access";
540 char *pref[]=
541 {
542 "-signal=",
543 "-latch=",
544 "-prech=",
545 "-con=",
546 "-any=",
547 "="
548 };
549 long stype=0;
550
551 if (strncasecmp(var,as,strlen(as))==0) { var=&var[strlen(as)]; access=1; }
552 if (path==0 && cl==nodenamelist->NEXT) access=1;
553 if (cl==nodenamelist || cl->NEXT==NULL) access=0;
554
555 for (i=0; i<sizeof(pref)/sizeof(*pref); i++)
556 {
557 if (strncasecmp(var,pref[i],strlen(pref[i]))==0) { var=&var[strlen(pref[i])]; break; }
558 }
559 if (i>=sizeof(pref)/sizeof(*pref) && access) var=(char *)cl->DATA;
560 if (i>=sizeof(pref)/sizeof(*pref) || i==0 || i==4) stype=(access==0)?TTV_SIG_TYPEALL:TTV_SIG_L|TTV_SIG_R|TTV_SIG_B;
561 if (i==1) stype=TTV_SIG_L;
562 if (i==2) stype=TTV_SIG_R;
563 if (i==3) stype=TTV_SIG_C;
564 if ((i==5 || i>=sizeof(pref)/sizeof(*pref)) && cl!=nodenamelist && cl->NEXT!=NULL) stype=TTV_SIG_L;
565
566 tvs=ttv_GetTimingSignal(tvf, var);
567 if (tvs!=NULL)
568 {
569 if (i>=sizeof(pref)/sizeof(*pref) || (tvs->TYPE & stype)!=0) ch=addchain(NULL, tvs);
570 else ch=NULL;
571 }
572 else
573 {
574 if (i>=sizeof(pref)/sizeof(*pref) && !mbk_isregex_name(var))
575 stype=(access==0)?TTV_SIG_TYPEALL:TTV_SIG_L|TTV_SIG_R|TTV_SIG_B;
576
577 ch=ttv_getsigbytype_and_netname(tvf,NULL,stype,mask=addchain(NULL, namealloc(var)));
578 freechain(mask);
579 nlist=NULL;
580
581 for (ch0=ch; ch0!=NULL; ch0=ch0->NEXT)
582 {
583 tvs=(ttvsig_list *)ch0->DATA;
584 if ((tvs->TYPE & (TTV_SIG_C|TTV_SIG_L|TTV_SIG_R|TTV_SIG_B))!=0 || ttv_isgateoutput(tvf, tvs, mode))
585 nlist=addchain(nlist, tvs);
586 }
587 freechain(ch);
588 ch=nlist;
589 }
590 if (access && ch!=NULL) ch=addchain(ch,NULL);
591 if (ch==NULL)
592 {
593 avt_errmsg(TTV_API_ERRMSG, "034", AVT_ERROR, (char *)cl->DATA);
594 freechain(ch);
595 freedoublechain(nodelist);
596 return NULL;
597 }
598 if ((cnt=countchain(ch))>10000)
599 avt_errmsg(TTV_API_ERRMSG, "047", AVT_ERROR, (char *)cl->DATA, cnt);
600 nodelist=addchain(nodelist, ch);
601 }
602 nodelist=reverse(nodelist);
603
604 if (lastslope<=0 || noprop)
605 lastslope=0;
606
607 ttv_setsearchexclude(0, 0, &oldexstart, &oldexend);
608 if (!noprop)
609 oldprop=ttv_SetPrecisionLevel(1);
610 oldmode=ttv_AutomaticDetailBuild("on");
611 mask=NULL;
612
613 d0=ttv_getUorD(dir[0]);
614 d1=ttv_getUorD(dir[1]);
615
616 for (cl=(chain_list *)nodelist->DATA; cl!=NULL; cl=cl->NEXT)
617 {
618 tvs=(ttvsig_list *)cl->DATA;
619 if (d0=='d' || d0=='?')
620 recur_run(tvf, lastslope, tvs->NODE, nodelist->NEXT, &mask, &config, d1, minmax_i, &allsearch);
621 if (d0=='u' || d0=='?')
622 recur_run(tvf, lastslope, tvs->NODE+1, nodelist->NEXT, &mask, &config, d1, minmax_i, &allsearch);
623 }
624
625 freedoublechain(nodelist);
626 ttv_AutomaticDetailBuild(oldmode);
627 if (!noprop)
628 ttv_SetPrecisionLevel(oldprop);
629 ttv_setsearchexclude(oldexstart, oldexend, &oldexstart, &oldexend);
630
631 // creation des details
632 if (countchain(nodenamelist)==2)
633 {
634 config=reverse(config);
635 path_list=NULL;
636 for (cl=config, ch=NULL; cl!=NULL; cl=cl->NEXT)
637 {
638 path_list=((chain_list *)(cl->DATA))->DATA;
639 path_list->USER=addptype(path_list->USER, CLIPCTK, NULL);
640
641 if (ch==NULL) path_list->NEXT=NULL;
642 else path_list->NEXT=(ttvpath_list *)ch->DATA;
643 ch=addchain(ch, path_list);
644 freechain((chain_list *)cl->DATA);
645 }
646 freechain(ch);
647
648 while (allsearch)
649 {
650 pth=(ttvpath_list *)allsearch->DATA;
651 if (getptype(pth->USER, CLIPCTK)==NULL)
652 {
653 pth->NEXT=NULL;
654 ttv_freepathlist(pth);
655 }
656 else
657 pth->USER=delptype(pth->USER, CLIPCTK);
658 allsearch=delchain(allsearch, allsearch);
659 }
660
661 path_list=ttv_classpath(path_list, minmax_i);
662
663 ch=NULL;
664 while (path_list!=NULL)
665 {
666 ch=addchain(ch, path_list);
667 path_list=path_list->NEXT;
668 }
669 ch=reverse(ch);
670
671 freechain(config);
672 }
673 else
674 {
675 /* removebadconfig(config, 'u', 'u', minmax_i);
676 removebadconfig(config, 'u', 'd', minmax_i);
677 removebadconfig(config, 'd', 'u', minmax_i);
678 removebadconfig(config, 'd', 'd', minmax_i);*/
679 ch=NULL;
680 path_list=NULL;
681 for (cl=config; cl!=NULL; cl=cl->NEXT)
682 {
683 if (cl->DATA!=NULL)
684 {
685 if (!nosync) performstbclipping(tvf, (chain_list *)cl->DATA, minmax_i);
686 path_list=buildconfigpath((chain_list *)cl->DATA, path_list);
687 path_list->CRITIC=buildconfigdetail((chain_list *)cl->DATA);
688 }
689 }
690 path_list=ttv_classpath(path_list, minmax_i);
691 while (path_list!=NULL)
692 {
693 ch=addchain(ch, path_list);
694 path_list=path_list->NEXT;
695 }
696 ch=reverse(ch);
697
698 // cleaning
699 for (cl=config; cl!=NULL; cl=cl->NEXT)
700 {
701 if (cl->DATA!=NULL)
702 freechain((chain_list *)cl->DATA);
703 }
704 freechain(config);
705 for (cl=allsearch; cl!=NULL; cl=cl->NEXT)
706 {
707 for (path_list=(ttvpath_list *)cl->DATA; path_list!=NULL; path_list=path_list->NEXT)
708 {
709 path_list->USER=testanddelptype(path_list->USER, CLIPCTK);
710 path_list->USER=testanddelptype(path_list->USER, CLIPREF);
711 }
712 ttv_freepathlist((ttvpath_list *)cl->DATA);
713 }
714 freechain(allsearch);
715 }
716
717 ch=filterpath(ch, nbpath);
718 return ch;
719 }
720
721 // ------------------------------------------ V2 -----------------------------------------------------------------
722 static int allow_signal(chain_list *lst, ttvsig_list *tvs, int depth)
723 {
724 chain_list *cl;
725 ttvpath_list *pth;
726 for (cl=lst; cl!=NULL; cl=cl->NEXT)
727 {
728 pth=(ttvpath_list *)cl->DATA;
729 if (pth->NODE->ROOT==tvs) return 0;
730 // if (pth->ROOT->ROOT==tvs) return 0;
731 }
732 return 1;
733 }
734
735 static void recur_run_v2(ttvfig_list *tvf, long slopein, ttvevent_list *a, ttvsig_list *end, chain_list **lst, chain_list **config, char dirend, long minmax, chain_list **allsearch, int depth)
736 {
737 ttvpath_list *path_list, *pth;
738 long slopeout, findcmd=0, savelastslope;
739 char dir[3]=" ?";
740
741 if (depth>0 && a->ROOT==end)
742 {
743 if (dirend=='?' || dirend==ttv_GetTimingEventDirection(pth->ROOT))
744 {
745 *config=addchain(*config, reverse(dupchainlst(*lst)));
746 return;
747 }
748 }
749
750 if (depth>10) return;
751
752 if (!allow_signal(*lst, a->ROOT, depth)) return;
753
754
755 dir[0]=ttv_GetTimingEventDirection(a);
756
757 savelastslope=TTV_PROPAGATE_FORCED_SLOPE;
758 if (slopein!=0) TTV_PROPAGATE_FORCED_SLOPE=slopein;
759
760 // access
761 if((a->ROOT->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
762 {
763 a->ROOT->NODE->TYPE |= TTV_NODE_STOP ;
764 (a->ROOT->NODE+1)->TYPE |= TTV_NODE_STOP ;
765 if ((a->ROOT->TYPE & TTV_SIG_N) != 0)
766 TTV_MORE_SEARCH_OPTIONS|=TTV_MORE_OPTIONS_ENABLE_STOP_ON_TTV_SIG_N;
767 }
768 if ((a->ROOT->TYPE & TTV_SIG_Q) != 0)
769 findcmd=TTV_FIND_CMD;
770
771 // pour que les falsepaths s'appliquent
772 if ((end->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
773 {
774 end->NODE->TYPE|=TTV_NODE_STOP ;
775 (end->NODE+1)->TYPE|=TTV_NODE_STOP ;
776 }
777
778 TTV_QUIET_MODE=1;
779 path_list=ttv_getsigaccesslist (tvf, a->ROOT, NULL, a->ROOT, dir, 0, minmax|findcmd, 0, 0);
780 TTV_QUIET_MODE=0;
781
782 if((a->ROOT->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
783 {
784 a->ROOT->NODE->TYPE &= ~TTV_NODE_STOP ;
785 (a->ROOT->NODE+1)->TYPE &= ~TTV_NODE_STOP ;
786 if ((a->ROOT->TYPE & TTV_SIG_N) != 0)
787 TTV_MORE_SEARCH_OPTIONS&=~TTV_MORE_OPTIONS_ENABLE_STOP_ON_TTV_SIG_N;
788 }
789
790 // pour que les falsepaths s'appliquent
791 if ((end->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
792 {
793 end->NODE->TYPE&=~TTV_NODE_STOP ;
794 (end->NODE+1)->TYPE&=~TTV_NODE_STOP ;
795 }
796
797
798 if (path_list!=NULL)
799 {
800 *allsearch=addchain(*allsearch, path_list);
801
802 for (pth=path_list; pth!=NULL; pth=pth->NEXT)
803 {
804 if (pth->ROOT->ROOT==end || !ttv_PathIsHZ(pth))
805 {
806 *lst=addchain(*lst, pth);
807
808 slopeout=pth->SLOPE;
809 recur_run_v2(tvf, slopeout, pth->ROOT, end, lst, config, dirend, minmax, allsearch, depth+1);
810
811 *lst=delchain(*lst, *lst);
812 }
813 }
814 }
815
816 // un path?
817 if((a->ROOT->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
818 {
819 a->ROOT->NODE->TYPE |= TTV_NODE_STOP ;
820 (a->ROOT->NODE+1)->TYPE |= TTV_NODE_STOP ;
821 if ((a->ROOT->TYPE & TTV_SIG_N) != 0)
822 TTV_MORE_SEARCH_OPTIONS|=TTV_MORE_OPTIONS_ENABLE_STOP_ON_TTV_SIG_N;
823 }
824 if ((a->ROOT->TYPE & TTV_SIG_Q) != 0)
825 findcmd=TTV_FIND_CMD;
826
827 // pour que les falsepaths s'appliquent
828 if ((end->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
829 {
830 end->NODE->TYPE|=TTV_NODE_STOP ;
831 (end->NODE+1)->TYPE|=TTV_NODE_STOP ;
832 }
833
834 path_list=ttv_getcritic_pathlist (tvf, a->ROOT, NULL, dir, 0, minmax|findcmd, 0, 0, 0);
835
836 if((a->ROOT->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
837 {
838 a->ROOT->NODE->TYPE &= ~TTV_NODE_STOP ;
839 (a->ROOT->NODE+1)->TYPE &= ~TTV_NODE_STOP ;
840 if ((a->ROOT->TYPE & TTV_SIG_N) != 0)
841 TTV_MORE_SEARCH_OPTIONS&=~TTV_MORE_OPTIONS_ENABLE_STOP_ON_TTV_SIG_N;
842 }
843
844 // pour que les falsepaths s'appliquent
845 if ((end->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B)) == 0)
846 {
847 end->NODE->TYPE&=~TTV_NODE_STOP ;
848 (end->NODE+1)->TYPE&=~TTV_NODE_STOP ;
849 }
850
851 if (path_list!=NULL)
852 {
853 *allsearch=addchain(*allsearch, path_list);
854
855 for (pth=path_list; pth!=NULL; pth=pth->NEXT)
856 {
857 if (pth->ROOT->ROOT==end || ((pth->ROOT->ROOT->TYPE & (TTV_SIG_R|TTV_SIG_Q))==0 && !ttv_PathIsHZ(pth)))
858 {
859 *lst=addchain(*lst, pth);
860
861 slopeout=pth->SLOPE;
862 recur_run_v2(tvf, slopeout, pth->ROOT, end, lst, config, dirend, minmax, allsearch, depth+1);
863
864 *lst=delchain(*lst, *lst);
865 }
866 }
867 }
868
869 TTV_PROPAGATE_FORCED_SLOPE=savelastslope;
870
871 }
872
873 chain_list *ttv_ProbeDelay_v2(ttvfig_list *tvf, double slopein, char *start, char *end, char *dir, int nbpath, char *minmax)
874 {
875 chain_list *cl, *mask, *ch, *allsearch=NULL;
876 ttvpath_list *path_list;
877 ttvsig_list *tvs_start, *tvs_end;
878 long minmax_i=1;
879 chain_list *config=NULL;
880 char *oldmode, d0, d1;
881 int oldprop;
882 long lastslope=mbk_long_round(slopein*1e12*TTV_UNIT);
883 long oldexstart, oldexend;
884
885 if (nbpath<0) nbpath=0;
886
887 if (!strcasecmp (minmax, "max")) minmax_i = TTV_FIND_MAX;
888 else if (!strcasecmp (minmax, "min")) minmax_i = TTV_FIND_MIN;
889 else
890 {
891 avt_errmsg(TTV_API_ERRMSG, "022", AVT_ERROR);
892 // fprintf (stderr, "ttv_ProbeDelay: error: available values for 'minmax' are 'min' or 'max'\n");
893 return NULL;
894 }
895
896 tvs_start=ttv_GetTimingSignal(tvf, start);
897 tvs_end=ttv_GetTimingSignal(tvf, end);
898
899 if (tvs_start==NULL)
900 {
901 avt_errmsg(TTV_API_ERRMSG, "034", AVT_ERROR, start);
902 // avt_error("ttvapi", -1, AVT_ERR, "ttv_ProbeDelay: could not find node '%s'\n", start);
903 return NULL;
904 }
905 if (tvs_end==NULL)
906 {
907 avt_errmsg(TTV_API_ERRMSG, "034", AVT_ERROR, end);
908 //avt_error("ttvapi", -1, AVT_ERR, "ttv_ProbeDelay: could not find node '%s'\n", end);
909 return NULL;
910 }
911
912 if (lastslope<=0)
913 lastslope=0;
914
915 // ttv_checkinfchange(tvf);
916
917 ttv_setsearchexclude(0, 0, &oldexstart, &oldexend);
918 oldprop=ttv_SetPrecisionLevel(1);
919 oldmode=ttv_AutomaticDetailBuild("on");
920 mask=NULL;
921
922 d0=ttv_getUorD(dir[0]);
923 d1=ttv_getUorD(dir[1]);
924
925 if (d0=='d' || d0=='?')
926 recur_run_v2(tvf, lastslope, tvs_start->NODE, tvs_end, &mask, &config, d1, minmax_i, &allsearch, 0);
927 if (d0=='u' || d0=='?')
928 recur_run_v2(tvf, lastslope, tvs_start->NODE+1, tvs_end, &mask, &config, d1, minmax_i, &allsearch, 0);
929
930 ttv_AutomaticDetailBuild(oldmode);
931 ttv_SetPrecisionLevel(oldprop);
932 ttv_setsearchexclude(oldexstart, oldexend, &oldexstart, &oldexend);
933
934
935 ch=NULL;
936 path_list=NULL;
937 for (cl=config; cl!=NULL; cl=cl->NEXT)
938 {
939 if (cl->DATA!=NULL)
940 {
941 performstbclipping(tvf, (chain_list *)cl->DATA, minmax_i);
942 path_list=buildconfigpath((chain_list *)cl->DATA, path_list);
943 path_list->CRITIC=buildconfigdetail((chain_list *)cl->DATA);
944 }
945 }
946 path_list=ttv_classpath(path_list, minmax_i);
947 while (path_list!=NULL)
948 {
949 ch=addchain(ch, path_list);
950 path_list=path_list->NEXT;
951 }
952 ch=reverse(ch);
953
954 // cleaning
955 for (cl=config; cl!=NULL; cl=cl->NEXT)
956 {
957 if (cl->DATA!=NULL)
958 freechain((chain_list *)cl->DATA);
959 }
960 freechain(config);
961 for (cl=allsearch; cl!=NULL; cl=cl->NEXT)
962 {
963 for (path_list=(ttvpath_list *)cl->DATA; path_list!=NULL; path_list=path_list->NEXT)
964 {
965 path_list->USER=testanddelptype(path_list->USER, CLIPCTK);
966 path_list->USER=testanddelptype(path_list->USER, CLIPREF);
967 }
968 ttv_freepathlist((ttvpath_list *)cl->DATA);
969 }
970 freechain(allsearch);
971
972 ch=filterpath(ch, nbpath);
973 return ch;
974 }
975
976 chain_list *ttv_CharacPaths(ttvfig_list *tf, double slopein, char *start, char *end, char *dir, long number, char *all, char *path, char *minmax, double capaout, int propagate)
977 {
978 int oldprop=ttv_SetPrecisionLevel(propagate!=0?1:0);
979 long lastslope=mbk_long_round(slopein*1e12*TTV_UNIT);
980 long savelastslope;
981 double savelastcapa;
982 chain_list *res;
983 char *oldmode;
984
985 API_TEST_TOKEN_SUB(TMA_API,"tma")
986 // ttv_checkinfchange(tf);
987
988 if (propagate==2)
989 ttv_experim_setstopaftergate1(1);
990
991 if (lastslope<=0)
992 lastslope=0;
993
994 oldmode=ttv_AutomaticDetailBuild("on");
995 savelastslope=TTV_PROPAGATE_FORCED_SLOPE;
996 savelastcapa=TTV_PROPAGATE_FORCED_CAPA;
997 if (lastslope!=0) TTV_PROPAGATE_FORCED_SLOPE=lastslope;
998 TTV_PROPAGATE_FORCED_CAPA=capaout*1e15;
999 res=ttv_GetPaths_sub(tf, start, start, end, dir, number, all, path, minmax);
1000 TTV_PROPAGATE_FORCED_CAPA=savelastcapa;
1001 TTV_PROPAGATE_FORCED_SLOPE=savelastslope;
1002 ttv_SetPrecisionLevel(oldprop);
1003
1004 ttv_AutomaticDetailBuild(oldmode);
1005
1006 ttv_experim_setstopaftergate1(0);
1007
1008 return res;
1009 }
1010
1011 static chain_list *converttodoublelist(chain_list *val, int nbx)
1012 {
1013 chain_list *cl, *ch=NULL;
1014 int i;
1015
1016 while (val!=NULL)
1017 {
1018 cl=NULL;
1019 for (i=0;i<nbx && val!=NULL;i++)
1020 {
1021 cl=addchain(cl, val->DATA);
1022 val=delchain(val,val);
1023 }
1024 ch=addchain(ch, reverse(cl));
1025 }
1026 return reverse(ch);
1027 }
1028 chain_list *ttv_CharacPathTables(ttvpath_list *pth, chain_list *slopes, chain_list *capas, int propagate)
1029 {
1030 // int oldprop=ttv_SetPrecisionLevel(propagate!=0?1:0);
1031 float val;
1032 chain_list *res, *cl;
1033 chain_list *slopes_in=NULL, *capas_in=NULL, *delays_out, *slopes_out, *energy;
1034 long type;
1035
1036 API_TEST_TOKEN_SUB(TMA_API,"tma")
1037 // ttv_checkinfchange(tf);
1038
1039 type=(pth->TYPE & (~TTV_FIND_PATH)) | TTV_FIND_LINE;
1040
1041 /* if (propagate==2)
1042 ttv_experim_setstopaftergate1(1);
1043 */
1044 if (slopes==NULL) slopes_in=addchain(NULL, (void *)TTV_NOTIME);
1045 else
1046 {
1047 for (cl=slopes; cl!=NULL; cl=cl->NEXT)
1048 {
1049 val=*(float *)&cl->DATA;
1050 if (val>0)
1051 slopes_in=addchain(slopes_in, (void *)mbk_long_round(val*1e12*TTV_UNIT));
1052 else
1053 slopes_in=addchain(slopes_in, (void *)TTV_NOTIME);
1054 }
1055 }
1056
1057 if (capas==NULL) capas_in=addchain(NULL, 0), *(float *)&capas_in->DATA=-1.0;
1058 else
1059 {
1060 for (cl=capas; cl!=NULL; cl=cl->NEXT)
1061 {
1062 val=*(float *)&cl->DATA;
1063 capas_in=addchain(capas_in, NULL);
1064 *(float *)&capas_in->DATA=val*1e15;
1065 }
1066 }
1067
1068 slopes_in=reverse(slopes_in);
1069 capas_in=reverse(capas_in);
1070
1071 ttv_activate_search_charac_mode(slopes_in, capas_in);
1072
1073 if (pth->ROOT==pth->NODE && pth->DELAY==0)
1074 {
1075 int nbx, nby, i;
1076 nbx=countchain(slopes_in);
1077 nby=countchain(capas_in);
1078 delays_out=NULL;
1079 slopes_out=NULL;
1080 energy=NULL;
1081 for (cl=slopes_in; cl!=NULL; cl=cl->NEXT)
1082 for (i=0; i<nby; i++)
1083 {
1084 delays_out=addchain(delays_out, (void *)pth->DELAY);
1085 slopes_out=addchain(slopes_out, cl->DATA);
1086 energy=addchain(energy, NULL);
1087 *(float *)&energy->DATA=0;
1088 }
1089 }
1090 else
1091 {
1092 long sTTV_MORE_SEARCH_OPTIONS=TTV_MORE_SEARCH_OPTIONS;
1093 TTV_MORE_SEARCH_OPTIONS=pth->TTV_MORE_SEARCH_OPTIONS;
1094 if ((pth->TYPE & TTV_FIND_ALL)==0)
1095 ttv_getcritic(ttv_GetTopTimingFigure(pth->FIG),pth->FIG, pth->ROOT, pth->NODE, pth->LATCH, pth->CMDLATCH, type);
1096 else
1097 ttv_getcriticpara(ttv_GetTopTimingFigure(pth->FIG), pth->FIG, pth->ROOT, pth->NODE, pth->DELAY, type, NULL, pth->TTV_MORE_SEARCH_OPTIONS);
1098 ttv_retreive_search_charac_results(&delays_out, &slopes_out, &energy);
1099 TTV_MORE_SEARCH_OPTIONS=sTTV_MORE_SEARCH_OPTIONS;
1100 }
1101
1102 for (cl=delays_out; cl!=NULL; cl=cl->NEXT)
1103 val=((long)cl->DATA)*1e-12/TTV_UNIT, *(float *)&cl->DATA=val;
1104
1105 for (cl=slopes_out; cl!=NULL; cl=cl->NEXT)
1106 val=((long)cl->DATA)*1e-12/TTV_UNIT, *(float *)&cl->DATA=val;
1107
1108 if(energy)
1109 cl=addchain(NULL, converttodoublelist(energy, countchain(capas_in)));
1110 else
1111 cl=addchain(NULL, NULL);
1112 cl=addchain(cl, converttodoublelist(slopes_out, countchain(capas_in)));
1113 cl=addchain(cl, converttodoublelist(delays_out, countchain(capas_in)));
1114
1115 ttv_activate_search_charac_mode(NULL, NULL);
1116 freechain(capas_in);
1117 freechain(slopes_in);
1118 return cl;
1119 }