Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / api / ttv / ttv_API_fig.c
1
2 #include STM_H
3 #include TTV_H
4 #include GEN_H
5 #include MLU_H
6 #include CNS_H
7 #include INF_H
8 #include EFG_H
9 #include TAS_H
10 #include TRC_H
11 #include YAG_H
12 #include MCC_H
13
14 #define API_USE_REAL_TYPES
15 #include "api_communication.h"
16 #include "gen_API.h"
17 #include "ttv_API_LOCAL.h"
18 #include "ttv_API.h"
19
20 #define TTV_DUP_LOFIG_PTYPE 0x23450001
21 #define TTV_DONE_PTYPE 0x23450002
22 #define TTV_TEMP_PTYPE 0x0fab007
23 #define TTV_mark_IN 1
24 #define TTV_mark_OUT 2
25 #define TTV_mark_HZ 4
26
27 #define IFGNS(a) if (GENIUS_GLOBAL_LOFIG!=NULL) { a }
28
29 static int CALLED_TTV_FUNCTION;
30 static lofig_list *current_dup_lofig;
31 static ht *nodeht;
32 static ttvfig_list *current_ttvfig;
33 static lofig_list *TTV_BASE_LOFIG, editmodelofig;
34 static chain_list *ALL_ADDED_NODES;
35 static loins_list *loins_removed;
36 static losig_list *losig_removed;
37 static chain_list *ALL_MY_TTV=NULL;
38 static char *TTV_FUNCTIONS_FILE;
39 static double TTVSLOPE=200e-12, TTVCAPA=0;
40 static chain_list *ALL_LINES=NULL;
41 static int TTVFLAGS=0;
42 static char *TTV_FORCED_NAME=NULL;
43 static float ttv_low=-1, ttv_high=-1;
44
45 #define TTV_INSTANCE_MODE 1
46 #define TTV_DRIVE_DTX 2
47
48 static mbk_options_pack_struct ttv_opack[]=
49 {
50 {"ttvUseInstanceMode", TTV_INSTANCE_MODE},
51 {"ttvDriveDTX", TTV_DRIVE_DTX}
52 };
53
54
55 void ttv_SetOutputSwing(double vss, double vdd)
56 {
57 ttv_low=vss;
58 ttv_high=vdd;
59 }
60
61 void ttv_API_AtLoad_Initialize() // commentaire pour desactiver l'ajout de token
62 {
63 TTVFLAGS=mbk_ReadFlags(__API_FLAGS, ttv_opack, sizeof(ttv_opack)/sizeof(*ttv_opack), 0, 0);
64 }
65
66 void ttv_API_Action_Initialize() // commentaire pour desactiver l'ajout de token
67 {
68 /* TTVSLOPE=200e-12;
69 TTVCAPA=0;*/
70 CALLED_TTV_FUNCTION=0;
71 current_dup_lofig=NULL;
72 TTV_BASE_LOFIG=NULL;
73 TTV_FUNCTIONS_FILE=NULL;
74 }
75
76 void ttv_SetBaseNetlist(lofig_list *lf)
77 {
78 char buf[1024];
79
80 TTV_BASE_LOFIG=lf;
81
82 if (!TTV_FUNCTIONS_FILE && lf!=NULL)
83 {
84 sprintf (buf, "%s_functions.c", lf->NAME);
85 TTV_FUNCTIONS_FILE = namealloc (buf);
86 }
87 }
88
89 void ttv_UseInstanceMode()
90 {
91 TTV_FORCED_NAME=gen_getinstancename();
92 }
93
94 void ttv_SetFunctionsFile (char *functions_file)
95 {
96 TTV_FUNCTIONS_FILE = namealloc (functions_file);
97 }
98
99 static void checkformoretags(ttvsig_list *ptsig)
100 {
101 if((ptsig->TYPE & (TTV_SIG_C | TTV_SIG_L | TTV_SIG_Q | TTV_SIG_R | TTV_SIG_B |
102 TTV_SIG_N)) != 0)
103 {
104 ptsig->NODE[0].TYPE |= TTV_NODE_STOP;
105 ptsig->NODE[1].TYPE |= TTV_NODE_STOP;
106 }
107 }
108
109
110 static ttvsig_list *ttvapi_GetNode(char *node, char *root, float capa)
111 {
112 long res;
113 char temp[1024], *code;
114
115 node=ttv_revect(gen_makesignalname(node));
116 root=ttv_revect(gen_makesignalname(root));
117
118 sprintf(temp,"*:%s",node);
119 code=namealloc(temp);
120 if ((res=gethtitem(nodeht, code))!=EMPTYHT)
121 {
122 if (capa!=0.0 && ((ttvsig_list *)res)->CAPA==0.0)
123 ((ttvsig_list *)res)->CAPA=capa;
124 return (ttvsig_list *)res;
125 }
126
127 sprintf(temp,"%s:%s",root,node);
128 code=namealloc(temp);
129 if ((res=gethtitem(nodeht, code))!=EMPTYHT)
130 {
131 if (capa!=0.0 && ((ttvsig_list *)res)->CAPA==0.0)
132 ((ttvsig_list *)res)->CAPA=capa;
133 return (ttvsig_list *)res;
134 }
135
136 ALL_ADDED_NODES=ttv_addrefsig(current_ttvfig, node, root, capa, 0, ALL_ADDED_NODES) ;
137 addhtitem(nodeht, code, (long)ALL_ADDED_NODES->DATA);
138 sprintf(temp,"*:%s",node);
139 code=namealloc(temp);
140 addhtitem(nodeht, code, (long)ALL_ADDED_NODES->DATA);
141 return (ttvsig_list *)ALL_ADDED_NODES->DATA;
142 }
143
144 static void GrabCreatedNodes(chain_list *cl)
145 {
146 char temp[1024], *code;
147 ttvsig_list *tvs;
148
149 while (cl!=NULL)
150 {
151 tvs=(ttvsig_list *)cl->DATA;
152 sprintf(temp,"%s:%s",tvs->NETNAME,tvs->NAME);
153 code=namealloc(temp);
154 if (gethtitem(nodeht, code)==EMPTYHT)
155 {
156 addhtitem(nodeht, code, (long)tvs);
157 sprintf(temp,"*:%s",tvs->NAME);
158 code=namealloc(temp);
159 addhtitem(nodeht, code, (long)tvs);
160 ALL_ADDED_NODES=addchain(ALL_ADDED_NODES, tvs);
161 }
162 cl=cl->NEXT;
163 }
164 }
165
166 static double ttv_get_transistor_capa (locon_list *cir_ptcon)
167 {
168 double trcapa = 0.0;
169 lotrs_list *trs, *shrinked_trs;
170
171 trs = (lotrs_list*)cir_ptcon->ROOT;
172 shrinked_trs = trs;
173 // shrinked_trs = duplotrs (trs);
174 ELP_CALC_ONLY_CAPA = 1;
175 elpLoadOnceElp();
176 //elpLotrsShrink (shrinked_trs);
177 if (trs->GRID == cir_ptcon)
178 trcapa = elpGetCapaFromLocon (shrinked_trs->GRID,ELP_CAPA_TYPICAL,elpTYPICAL);
179 else
180 if (trs->DRAIN == cir_ptcon)
181 trcapa = elpGetCapaFromLocon (shrinked_trs->DRAIN,ELP_CAPA_TYPICAL,elpTYPICAL);
182 else
183 if (trs->SOURCE == cir_ptcon)
184 trcapa = elpGetCapaFromLocon (shrinked_trs->SOURCE,ELP_CAPA_TYPICAL,elpTYPICAL);
185
186 // mbkfree (shrinked_trs);
187 ELP_CALC_ONLY_CAPA = 0;
188
189 return trcapa;
190 }
191
192 //--- copied directly from tas -----
193 static float ttvapi_tas_gettotalcapa(lofig_list *lofig, losig_list *losig)
194 {
195 float capa = 0.0;
196 chain_list *chain;
197
198 if(!lofig)
199 lofig = TAS_CONTEXT->TAS_LOFIG;
200 if(elpIsCapaSig(lofig, losig, ELP_CAPA_TYPICAL)){
201 return ((elpGetCapaSig(lofig, losig, ELP_CAPA_TYPICAL) + rcn_getcapa(lofig,losig)) * 1000.0);
202 }else{
203 for(chain = (chain_list*)getptype(losig->USER,LOFIGCHAIN)->DATA; chain; chain = chain->NEXT)
204 capa += elpGetCapaFromLocon((locon_list*)chain->DATA,ELP_CAPA_TYPICAL,elpTYPICAL);
205 elpAddCapaSig(lofig, losig, capa, ELP_CAPA_TYPICAL);
206 return ((capa + rcn_getcapa(lofig,losig)) * 1000.0);
207 }
208 }
209 //---------------------------------
210
211 static void SetConCapa(lofig_list *lf, chain_list *cl)
212 {
213 float capa;
214 chain_list *ch;
215 ttvsig_list *tvs;
216 losig_list *ls;
217 locon_list *lc;
218
219 while (cl!=NULL)
220 {
221 tvs=(ttvsig_list *)cl->DATA;
222 if ((tvs->TYPE & TTV_SIG_CX)==TTV_SIG_CX)
223 tvs->USER=addptype(tvs->USER, TTV_TEMP_PTYPE, (void *)0);
224 if ((ls=mbk_quickly_getlosigbyname(lf, tvs->NETNAME))!=NULL)
225 {
226 tvs->CAPA=ttvapi_tas_gettotalcapa(lf, ls);
227 }
228 cl=cl->NEXT;
229 }
230 }
231
232 static void UpdateRCXLocon(char *con_name, char *insname, char *rcxname)
233 {
234 locon_list *lc;
235 chain_list *lst, *cl;
236 subinst_t *sins;
237 losig_list *ls;
238 sins=gen_get_hier_instance(LATEST_GNS_RUN, insname);
239 if (sins->FLAGS & LOINS_IS_BLACKBOX) return;
240 ls=gen_corresp_sig (con_name, sins->CRT);
241 cl=lst=GrabAllConnectorsThruCorresp(con_name, ls, sins->CRT, NULL);
242 while (cl!=NULL)
243 {
244 lc=(locon_list *)cl->DATA;
245 addloconrcxname(lc, rcxname);
246 cl=cl->NEXT;
247 }
248 freechain(lst);
249 }
250
251 static int CheckFirstCallForThisModel()
252 {
253 ptype_list *p;
254 loins_list *li, *prev, *next;
255 ttvfig_list *tvf;
256 timing_cell *cell;
257 losig_list *ls, *prevls, *nextls;
258 mbkContext tmpctx;
259
260 IFGNS( if (TTV_BASE_LOFIG==NULL) TTV_BASE_LOFIG=__gns_GetNetlist (); )
261 IFGNS( if ((TTVFLAGS & TTV_INSTANCE_MODE)==0 && TTV_FORCED_NAME==NULL && (p=getptype(TTV_BASE_LOFIG->USER, TTV_DONE_PTYPE))!=NULL) return 1; )
262
263 if (current_dup_lofig!=NULL) return 0;
264
265 CALLED_TTV_FUNCTION=1;
266 ALL_LINES=NULL;
267 ALL_ADDED_NODES=NULL;
268
269 elpLoadOnceElp();
270 rcx_env();
271 //avt_savecontext();
272 yagenv (tas_yaginit);
273 tas_setenv();
274
275 if (TTV_BASE_LOFIG==NULL) return 1;
276
277 current_dup_lofig=rduplofig(TTV_BASE_LOFIG);
278
279 if (TTV_FORCED_NAME!=NULL)
280 current_dup_lofig->NAME=TTV_FORCED_NAME;
281 else IFGNS( if (TTVFLAGS & TTV_INSTANCE_MODE) current_dup_lofig->NAME=gen_getinstancename(); )
282
283 loins_removed=NULL;
284 losig_removed=NULL;
285
286 for (li=current_dup_lofig->LOINS, prev=NULL; li!=NULL; li=next)
287 {
288 next=li->NEXT;
289
290 if (!(((tvf=ttv_gethtmodel(li->FIGNAME))!=NULL || (tvf=ttv_gethtmodel(li->INSNAME))!=NULL) && tvf->STATUS & TTV_STS_DTX))
291 {
292 if (prev==NULL) current_dup_lofig->LOINS=li->NEXT;
293 else prev->NEXT=li->NEXT;
294 li->NEXT=loins_removed; loins_removed=li;
295 }
296 else prev=li;
297 }
298 lofigchain(current_dup_lofig);
299
300 for (ls=current_dup_lofig->LOSIG, prevls=NULL; ls!=NULL; ls=nextls)
301 {
302 nextls=ls->NEXT;
303 if (getptype(ls->USER,LOFIGCHAIN)->DATA==NULL)
304 {
305 if (prevls==NULL) current_dup_lofig->LOSIG=ls->NEXT;
306 else prevls->NEXT=ls->NEXT;
307 ls->NEXT=losig_removed; losig_removed=ls;
308 }
309 else prevls=ls;
310 }
311
312
313
314 if ((tvf=ttv_gethtmodel(current_dup_lofig->NAME))!=NULL)
315 {
316 if((cell = stm_getcell(tvf->INFO->FIGNAME)) != NULL){
317 stm_freecell(tvf->INFO->FIGNAME) ;
318 cell = NULL;
319 }
320 ttv_unlockttvfig(tvf);
321 ttv_freeallttvfig(tvf);
322 }
323
324 IFGNS( memcpy(&tmpctx, genius_external_getcontext(), sizeof(tmpctx));
325 mbkSwitchContext(&tmpctx); // passage dans le context NORMAL pour les modeles de transistors
326 )
327
328 tas_TechnoParameters();
329 tas_capasig(current_dup_lofig);
330 elpLofigAddCapas ( current_dup_lofig, elpTYPICAL );
331
332 IFGNS( mbkSwitchContext(&tmpctx); )
333
334 nodeht=addht(1024);
335
336 current_ttvfig = tas_builtfig(current_dup_lofig);
337
338 ttv_lockttvfig(current_ttvfig);
339
340 tas_loconorient(current_dup_lofig, current_ttvfig);
341
342 tas_setsigname(current_dup_lofig);
343
344 IFGNS( memcpy(&tmpctx, genius_external_getcontext(), sizeof(tmpctx));
345 mbkSwitchContext(&tmpctx); // passage dans le context NORMAL pour les modeles de transistors
346 )
347
348 rcx_create(current_dup_lofig);
349
350 tas_builtrcxview(current_dup_lofig, current_ttvfig);
351
352 buildrcx(current_dup_lofig);
353
354 IFGNS( mbkSwitchContext(&tmpctx); )
355
356 tas_detecloconsig(current_dup_lofig, current_ttvfig);
357
358 tas_calcrcxdelay(current_dup_lofig, current_ttvfig, TTV_FILE_DTX);
359
360 tas_builtline(current_ttvfig, TTV_LINE_D);
361
362 tas_cleanfig(current_dup_lofig, current_ttvfig);
363
364 GrabCreatedNodes((chain_list *)current_ttvfig->ELCMDSIG);
365 GrabCreatedNodes((chain_list *)current_ttvfig->ELATCHSIG);
366 GrabCreatedNodes((chain_list *)current_ttvfig->EBREAKSIG);
367 GrabCreatedNodes((chain_list *)current_ttvfig->EPRESIG);
368 GrabCreatedNodes((chain_list *)current_ttvfig->EXTSIG);
369 GrabCreatedNodes((chain_list *)current_ttvfig->ESIG);
370 GrabCreatedNodes((chain_list *)current_ttvfig->CONSIG);
371 SetConCapa(current_dup_lofig, (chain_list *)current_ttvfig->CONSIG);
372 GrabCreatedNodes((chain_list *)current_ttvfig->NCSIG);
373 current_ttvfig->NBCONSIG=current_ttvfig->NBELCMDSIG=current_ttvfig->NBELATCHSIG=
374 current_ttvfig->NBEBREAKSIG=current_ttvfig->NBEPRESIG=current_ttvfig->NBEXTSIG=current_ttvfig->NBNCSIG=0;
375
376 return 0;
377 }
378
379 static chain_list *tabtochain(ttvsig_list ***tab, int nb)
380 {
381 chain_list *cl=NULL;
382 int i;
383 for (i=0;i<nb;i++) cl=addchain(cl, (*tab)[i]);
384 mbkfree(*tab);
385 //cl=reverse(cl);
386 *tab=(ttvsig_list **)cl;
387 return cl;
388 }
389 void ttv_EditTimingFigure(ttvfig_list *tvf)
390 {
391 chain_list *uncache;
392 long type, lev=0;
393 if (TTV_BASE_LOFIG!=NULL || tvf==NULL)
394 {
395 return;
396 }
397
398 ttv_API_Action_Initialize();
399
400 CALLED_TTV_FUNCTION=1;
401 ALL_LINES=NULL;
402 ALL_ADDED_NODES=NULL;
403
404 elpLoadOnceElp();
405 rcx_env();
406 //avt_savecontext();
407 yagenv (tas_yaginit);
408 tas_setenv();
409 current_dup_lofig=TTV_BASE_LOFIG=&editmodelofig;
410 current_ttvfig = tvf;
411
412 ttv_lockttvfig(current_ttvfig);
413
414 ttv_setcachesize(-1,-1);
415 //ttv_disablecache(tvf) ; // desactivation du cache
416 //ttv_setcachesize(TTV_ALLOC_MAX, TTV_ALLOC_MAX) ; // desactivation du cache
417 type=ttv_getloadedfigtypes(tvf);
418
419 /* if (type & TTV_FILE_DTX)
420 {
421 uncache=ttv_levelise(tvf,tvf->INFO->LEVEL,TTV_FIND_LINE);
422 freechain(uncache);
423 }
424 if (type & TTV_FILE_TTX)
425 {
426 uncache=ttv_levelise(tvf,tvf->INFO->LEVEL,TTV_FIND_PATH);
427 freechain(uncache);
428 }
429 */
430 nodeht=addht(1024);
431 loins_removed=NULL;
432 losig_removed=NULL;
433
434 GrabCreatedNodes(tabtochain(&current_ttvfig->CONSIG, current_ttvfig->NBCONSIG));
435 GrabCreatedNodes(tabtochain(&current_ttvfig->ELCMDSIG, current_ttvfig->NBELCMDSIG));
436 GrabCreatedNodes(tabtochain(&current_ttvfig->ELATCHSIG, current_ttvfig->NBELATCHSIG));
437 GrabCreatedNodes(tabtochain(&current_ttvfig->EBREAKSIG, current_ttvfig->NBEBREAKSIG));
438 GrabCreatedNodes(tabtochain(&current_ttvfig->EPRESIG, current_ttvfig->NBEPRESIG));
439 GrabCreatedNodes(tabtochain(&current_ttvfig->EXTSIG, current_ttvfig->NBEXTSIG));
440 GrabCreatedNodes(tabtochain(&current_ttvfig->NCSIG, current_ttvfig->NBNCSIG));
441 SetConCapa(current_dup_lofig, (chain_list *)current_ttvfig->CONSIG);
442 current_ttvfig->NBCONSIG=current_ttvfig->NBELCMDSIG=current_ttvfig->NBELATCHSIG=
443 current_ttvfig->NBEBREAKSIG=current_ttvfig->NBEPRESIG=current_ttvfig->NBEXTSIG=current_ttvfig->NBNCSIG=0;
444
445 }
446
447 void ttv_CreateTimingFigure(lofig_list *lf)
448 {
449 ttv_API_Action_Initialize();
450 ttv_SetBaseNetlist(lf);
451
452 }
453
454 void ttv_dir_to_index(char *dir, int *a, int *b)
455 {
456 if (strlen(dir)!=2) { *a=-1; return ; }
457 if (dir[0]=='u' || dir[0]=='U') *a=1;
458 else if (dir[0]=='d' || dir[0]=='D') *a=0;
459 else { *a=-1; return ; }
460 if (dir[1]=='u' || dir[1]=='U') *b=1;
461 else if (dir[1]=='d' || dir[1]=='D') *b=0;
462 else { *a=-1; return ; }
463 }
464
465 static char *getsignal(char *name, char *type, float *capa)
466 {
467 losig_list *ls=NULL, *cls;
468 loins_list *li;
469 locon_list *lc;
470 chain_list *arbo, *main_arbo;
471 ht *sight;
472 long l;
473
474 arbo=main_arbo=gen_hierarchical_split(gen_makesignalname(name));
475 if (GENIUS_GLOBAL_LOFIG!=NULL)
476 {
477 if (arbo->NEXT==NULL)
478 {
479 sight=gen_get_losig_ht(TTV_BASE_LOFIG);
480
481 if ((l=gethtitem(sight, arbo->DATA))==EMPTYHT) ls=NULL;
482 else ls=(losig_list *)l;
483
484 if (ls!=NULL)
485 {
486 if (ls->TYPE=='E') *type='c';
487 else *type='s';
488 }
489 }
490 else
491 {
492 for (li=TTV_BASE_LOFIG->LOINS; li!=NULL && li->INSNAME!=arbo->DATA; li=li->NEXT) ;
493 if (li!=NULL)
494 {
495 for (lc=li->LOCON; lc!=NULL && lc->NAME!=arbo->NEXT->DATA; lc=lc->NEXT) ;
496 if (lc!=NULL)
497 {
498 ls=lc->SIG;
499 if (ls->TYPE=='E') *type='n';
500 else *type='s';
501 }
502 }
503 else
504 {
505 sight=gen_get_losig_ht(TTV_BASE_LOFIG);
506
507 if ((l=gethtitem(sight, arbo->DATA))==EMPTYHT) ls=NULL;
508 else ls=(losig_list *)l;
509
510 if (ls!=NULL)
511 {
512 if (ls->TYPE=='E') *type='n';
513 else *type='s';
514 }
515 }
516 }
517
518 cls=gen_corresp_sig (gen_makesignalname(name), CUR_CORRESP_TABLE);
519 if (cls!=NULL)
520 {
521 // rcn_refresh_signal(GENIUS_GLOBAL_LOFIG, cls);
522 *capa=ttvapi_tas_gettotalcapa(GENIUS_GLOBAL_LOFIG, cls);
523 }
524 else
525 *capa=0.0;
526 }
527 else if (TTV_BASE_LOFIG!=&editmodelofig)
528 {
529 ls=mbk_quickly_getlosigbyname(TTV_BASE_LOFIG, (char *)arbo->DATA);
530 if (ls!=NULL)
531 {
532 *capa=rcn_getcapa(NULL, ls);
533 if (ls->TYPE=='E') *type='c';
534 else *type='s';
535 }
536 else
537 {
538 *capa=0;
539 }
540 }
541 else
542 *capa=0;
543 freechain(arbo);
544 if (ls==NULL) { *type='s'; return namealloc(name); }
545 return gen_losigname(ls);
546 }
547
548 static void SetNodeType(ttvsig_list *tvs, char type)
549 {
550 if (TTV_BASE_LOFIG==&editmodelofig && type=='s' && (tvs->TYPE & (TTV_SIG_C|TTV_SIG_Q|TTV_SIG_B|TTV_SIG_L|TTV_SIG_R))!=0) return;
551
552 switch(type)
553 {
554 case 'c':
555 if ((tvs->TYPE & TTV_SIG_N)==TTV_SIG_N
556 ||(tvs->TYPE & TTV_SIG_S)==TTV_SIG_S)
557 {
558 avt_errmsg(TTV_API_ERRMSG, "003", AVT_WARNING, (tvs->TYPE & TTV_SIG_N)==TTV_SIG_N?'n':'s',type);
559 // avt_error("ttvapi", 3, AVT_WAR, "conflicting node type old:'%c' new:'%c'\n",(tvs->TYPE & TTV_SIG_N)==TTV_SIG_N?'n':'s',type);
560 return;
561 }
562 tvs->TYPE|=TTV_SIG_C;
563 checkformoretags(tvs);
564 break;
565 case 'n':
566 if ((tvs->TYPE & TTV_SIG_N)==TTV_SIG_C
567 ||(tvs->TYPE & TTV_SIG_S)==TTV_SIG_S)
568 {
569 avt_errmsg(TTV_API_ERRMSG, "003", AVT_WARNING, (tvs->TYPE & TTV_SIG_C)==TTV_SIG_N?'c':'s',type);
570 // avt_error("ttvapi", 3, AVT_WAR, "conflicting node type old:'%c' new:'%c'\n",(tvs->TYPE & TTV_SIG_C)==TTV_SIG_N?'c':'s',type);
571 return;
572 }
573 tvs->TYPE|=TTV_SIG_N;
574 checkformoretags(tvs);
575 break;
576 case 's':
577 if ((tvs->TYPE & TTV_SIG_N)==TTV_SIG_C
578 ||(tvs->TYPE & TTV_SIG_S)==TTV_SIG_N)
579 {
580 avt_errmsg(TTV_API_ERRMSG, "003", AVT_WARNING, (tvs->TYPE & TTV_SIG_C)==TTV_SIG_N?'c':'n',type);
581 // avt_error("ttvapi", 3, AVT_WAR, "conflicting node type old:'%c' new:'%c'\n",(tvs->TYPE & TTV_SIG_C)==TTV_SIG_N?'c':'n',type);
582 return;
583 }
584 if ((tvs->TYPE & (TTV_SIG_Q | TTV_SIG_L | TTV_SIG_R | TTV_SIG_B))!=0) return;
585 tvs->TYPE|=TTV_SIG_S;
586 checkformoretags(tvs);
587 break;
588 case ' ':
589 break;
590 default:
591 avt_errmsg(TTV_API_ERRMSG, "004", AVT_ERROR, type);
592 // avt_error("ttvapi", 3, AVT_ERR, "type '%c' is unknown\n",type);
593 return;
594 }
595 }
596
597 char gettype(int type)
598 {
599 if ((type & TTV_SIG_L)==TTV_SIG_L) return 'l';
600 if ((type & TTV_SIG_R)==TTV_SIG_R) return 'r';
601 if ((type & TTV_SIG_Q)==TTV_SIG_Q) return 'q';
602 if ((type & TTV_SIG_B)==TTV_SIG_B) return 'b';
603 return '?';
604 }
605
606 static int CompareSubtype(ttvsig_list *tvs0, ttvsig_list *tvs1)
607 {
608 int t0, t1, res;
609 if (tvs0->NETNAME!=tvs1->NETNAME) return 0;
610 t0=(tvs0->TYPE & TTV_SIG_TYPE) & ~TTV_SIG_TYPECON;
611 t1=(tvs1->TYPE & TTV_SIG_TYPE) & ~TTV_SIG_TYPECON;
612 res=t0 | t1;
613 if (res!=0)
614 {
615 tvs0->TYPE &= ~TTV_SIG_S;
616 tvs1->TYPE &= ~TTV_SIG_S;
617 tvs0->TYPE |= res;
618 tvs1->TYPE |= res;
619 checkformoretags(tvs0);
620 checkformoretags(tvs1);
621 }
622 return 1;
623 }
624 static void SetNodeSubtype(ttvsig_list *tvs, char subtype)
625 {
626 switch(subtype)
627 {
628 case 'q':
629 if ((tvs->TYPE & (TTV_SIG_L | TTV_SIG_R /*| TTV_SIG_B*/))!=0)
630 {
631 avt_errmsg(TTV_API_ERRMSG, "005", AVT_WARNING, gettype(tvs->TYPE), subtype);
632 // avt_error("ttvapi", 2, AVT_WAR, "overriding type '%c' with '%c'\n",gettype(tvs->TYPE), subtype);
633 }
634 tvs->TYPE&=~(TTV_SIG_R|TTV_SIG_L|/*TTV_SIG_B|*/TTV_SIG_S);
635 tvs->TYPE|=TTV_SIG_Q;
636 checkformoretags(tvs);
637 break;
638 case 'l':
639 if ((tvs->TYPE & (TTV_SIG_Q | TTV_SIG_R | TTV_SIG_B))!=0)
640 {
641 avt_errmsg(TTV_API_ERRMSG, "005", AVT_WARNING, gettype(tvs->TYPE), subtype);
642 // avt_error("ttvapi", 2, AVT_WAR, "overriding type '%c' with '%c'\n",gettype(tvs->TYPE), subtype);
643 }
644 tvs->TYPE&=~(TTV_SIG_R|TTV_SIG_Q|TTV_SIG_B|TTV_SIG_S);
645 tvs->TYPE|=TTV_SIG_LL;
646 checkformoretags(tvs);
647 break;
648 case 'f':
649 if ((tvs->TYPE & (TTV_SIG_Q | TTV_SIG_R | TTV_SIG_B))!=0)
650 {
651 avt_errmsg(TTV_API_ERRMSG, "005", AVT_WARNING, gettype(tvs->TYPE), subtype);
652 // avt_error("ttvapi", 2, AVT_WAR, "overriding type '%c' with '%c'\n",gettype(tvs->TYPE), subtype);
653 }
654 tvs->TYPE&=~(TTV_SIG_R|TTV_SIG_Q|TTV_SIG_B|TTV_SIG_S);
655 tvs->TYPE|=TTV_SIG_LF;
656 checkformoretags(tvs);
657 break;
658 case 'b':
659 if ((tvs->TYPE & (TTV_SIG_L | TTV_SIG_R/* | TTV_SIG_Q*/))!=0)
660 {
661 avt_errmsg(TTV_API_ERRMSG, "005", AVT_WARNING, gettype(tvs->TYPE), subtype);
662 // avt_error("ttvapi", 2, AVT_WAR, "overriding type '%c' with '%c'\n",gettype(tvs->TYPE), subtype);
663 }
664 tvs->TYPE|=TTV_SIG_B;
665 tvs->TYPE&=~TTV_SIG_S;
666 checkformoretags(tvs);
667 break;
668 case 'r':
669 if ((tvs->TYPE & (TTV_SIG_L | TTV_SIG_Q | TTV_SIG_B))!=0)
670 {
671 avt_errmsg(TTV_API_ERRMSG, "005", AVT_WARNING, gettype(tvs->TYPE), subtype);
672 // avt_error("ttvapi", 2, AVT_WAR, "overriding type '%c' with '%c'\n",gettype(tvs->TYPE), subtype);
673 }
674 tvs->TYPE&=~(TTV_SIG_L|TTV_SIG_Q|TTV_SIG_B|TTV_SIG_S);
675 tvs->TYPE|=TTV_SIG_R;
676 checkformoretags(tvs);
677 break;
678 case ' ':
679 break;
680 default:
681 avt_errmsg(TTV_API_ERRMSG, "006", AVT_ERROR, subtype);
682 // avt_error("ttvapi", 3, AVT_ERR, "subtype '%c' is unknown\n",subtype);
683 return;
684 }
685 }
686
687 static void SetAsBreakpointIfNeeded(ttvsig_list *tsig)
688 {
689 if ((tsig->TYPE & TTV_SIG_L)!=TTV_SIG_L && (tsig->TYPE & TTV_SIG_Q)!=TTV_SIG_Q)
690 {
691 tsig->TYPE&=~(TTV_SIG_Q|TTV_SIG_S);
692 tsig->TYPE|=TTV_SIG_B;
693 checkformoretags(tsig);
694 }
695 }
696
697 ttvsig_list *ttv_SetNodeSubtype(char *node, char subtype)
698 {
699 char *sin;
700 ttvsig_list *tsin;
701 char it;
702 float capa;
703
704 if (CheckFirstCallForThisModel()) return NULL;
705 if ((sin=getsignal(node, &it, &capa))==NULL) return NULL;
706 tsin=ttvapi_GetNode(node, sin, capa);
707 SetNodeType(tsin, it);
708 SetNodeSubtype(tsin, subtype);
709 return tsin;
710 }
711
712 ttvsig_list *ttv_AddConnector(char *name, char dir)
713 {
714 ttvsig_list *tvs;
715 long type;
716 switch (dir)
717 {
718 case 'i': type=TTV_SIG_CI; break;
719 case 'o': type=TTV_SIG_CO; break;
720 case 'z': type=TTV_SIG_CZ; break;
721 case 'b': type=TTV_SIG_CB; break;
722 case 't': type=TTV_SIG_CT; break;
723 case 'x': type=TTV_SIG_CX; break;
724 default: type=TTV_SIG_CI;
725 avt_errmsg(TTV_API_ERRMSG, "054", AVT_ERROR, dir);
726 }
727 tvs=ttv_AddCustomNode(name, name, 'c', ' ');
728 tvs->TYPE&=~(TTV_SIG_CI|TTV_SIG_CO|TTV_SIG_CZ|TTV_SIG_CB|TTV_SIG_CT|TTV_SIG_CX);
729 tvs->TYPE|=type;
730 return tvs;
731 }
732
733 ttvsig_list *ttv_AddCommand(char *name)
734 {
735 return ttv_SetNodeSubtype(name, 'q');
736 }
737
738 ttvsig_list *ttv_AddLatch(char *name)
739 {
740 ttvsig_list *tsin;
741 if (CheckFirstCallForThisModel()) return NULL;
742 tsin=ttv_SetNodeSubtype(name, 'l');
743 tsin->TYPE|=TTV_SIG_LL;
744 checkformoretags(tsin);
745 return tsin;
746 }
747
748 ttvsig_list *ttv_AddFlipFlop(char *name)
749 {
750 ttvsig_list *tsin;
751 if (CheckFirstCallForThisModel()) return NULL;
752 tsin=ttv_SetNodeSubtype(name, 'l');
753 tsin->TYPE|=TTV_SIG_LF;
754 checkformoretags(tsin);
755 return tsin;
756 }
757
758 ttvsig_list *ttv_AddPrecharge(char *name)
759 {
760 return ttv_SetNodeSubtype(name, 'r');
761 }
762
763 ttvsig_list *ttv_AddBreakpoint(char *name)
764 {
765 return ttv_SetNodeSubtype(name, 'b');
766 }
767
768 TimingSignal *ttv_GetNode(char *node, char *signal)
769 {
770 ttvsig_list *tvs;
771 if (CheckFirstCallForThisModel()) return NULL;
772 tvs=ttvapi_GetNode(node, signal, 0.0);
773 return tvs;
774 }
775
776 TimingSignal *ttv_AddCustomNode(char *node, char *signal, char type, char subtype)
777 {
778 ttvsig_list *tvs;
779 if (CheckFirstCallForThisModel()) return NULL;
780 if (tolower(type)!='c' && tolower(type)!='n' && tolower(type)!='s')
781 {
782 IFGNS ( avt_errmsg(TTV_API_ERRMSG, "007", AVT_ERROR, gen_info(), type); )
783 //IFGNS ( avt_error("ttvapi", 2, AVT_ERR, "%s: invalid node type '%c', ttv_AddCustomSignal ignored\n", gen_info(), type); )
784 }
785 tvs=ttvapi_GetNode(node, signal, 0.0);
786 SetNodeType(tvs, type);
787 if (subtype!=' ') SetNodeSubtype(tvs, subtype);
788 return tvs;
789 }
790
791 void ttv_Config(double value, double out_capa)
792 {
793 TTVSLOPE=value;
794 TTVCAPA=out_capa;
795 }
796
797 char *ttv_getarcdef(ttvline_list *tvl)
798 {
799 char temp[1024];
800 char *type="mod";
801 ttvsig_list *tvss, *tvsd;
802 tvss=tvl->NODE->ROOT;
803 tvsd=tvl->ROOT->ROOT;
804
805 if ((tvl->TYPE & TTV_LINE_U)==TTV_LINE_U) type="setup";
806 else if ((tvl->TYPE & TTV_LINE_O)==TTV_LINE_O) type="hold";
807 else if ((tvl->TYPE & TTV_LINE_A)==TTV_LINE_A) type="access";
808
809 if ((TTVFLAGS & TTV_INSTANCE_MODE)==0)
810 sprintf(temp,"%s_%s_%s_%c%c", type, tvss->NAME, tvsd->NAME,
811 tvl->NODE==&tvss->NODE[1]?'u':'d',
812 tvl->ROOT==&tvsd->NODE[1]?'u':'d');
813 else
814 sprintf(temp,"%s-%s_%s_%s_%c%c", gen_getinstancename(), type, tvss->NAME, tvsd->NAME,
815 tvl->NODE==&tvss->NODE[1]?'u':'d',
816 tvl->ROOT==&tvsd->NODE[1]?'u':'d');
817 return namealloc(temp);
818 }
819
820 static double ttv_tas_thr2scm (double fthr, int dir)
821 {
822 return fthr ;
823 if (dir==0)
824 {
825 // DOWN
826 return elpThr2Scm (fthr, elpGeneral[elpGSLTHR],
827 elpGeneral[elpGSHTHR],
828 elpGetModelType (TRANSN)->elpModel[elpVT],
829 0.0, elpGeneral[elpGVDDMAX], elpFALL);
830 }
831 else
832 {
833 // UP
834 return elpThr2Scm (fthr, elpGeneral[elpGSLTHR],
835 elpGeneral[elpGSHTHR],
836 elpGetModelType (TRANSP)->elpModel[elpVT],
837 elpGeneral[elpGVDDMAX], elpGeneral[elpGVDDMAX], elpRISE);
838
839 }
840 }
841
842 void checkslope(char *type, char *input, char *output, char *dir, double *val)
843 {
844
845 if (*val<=0)
846 {
847 *val=(TAS_CONTEXT->FRONT_CON/TTV_UNIT)*1e-12;
848 avt_errmsg(TTV_API_ERRMSG, "008", AVT_ERROR, type, TAS_CONTEXT->FRONT_CON/TTV_UNIT, input, output, dir);
849 // avt_error("ttvapi", 1, AVT_WAR, "nul or negative %sslope set to %gps for line %s¤4->¤.%s %s\n", type, TAS_CONTEXT->FRONT_CON/TTV_UNIT, input, output, dir);
850 }
851 }
852
853 ttvline_list *ttv_AddCustomLine(TimingSignal *input, TimingSignal *output, double max_delay, double max_slope, double min_delay, double min_slope, char *dir, int type)
854 {
855 int a, b;
856 long vali, valo, LD, LE, LF, loaded;
857 ptype_list *pti, *pto;
858 ttvline_list *tvl;
859 ttvevent_list *lnode, *cmdnode;
860
861 if (CheckFirstCallForThisModel()) return NULL;
862 ttv_dir_to_index(dir, &a, &b);
863 if (a==-1)
864 {
865 char *where="somewhere";
866 IFGNS ( where=gen_info(); )
867 avt_errmsg(TTV_API_ERRMSG, "009", AVT_ERROR, where, dir);
868 // avt_error("ttvapi", 3, AVT_ERR, "%s: invalid direction '%s', timing line creation ignored\n", where, dir);
869 return NULL;
870 }
871
872 if ((pti=getptype(input->USER, TTV_TEMP_PTYPE))!=NULL) vali=(long)pti->DATA;
873 if ((pto=getptype(output->USER, TTV_TEMP_PTYPE))!=NULL) valo=(long)pto->DATA;
874
875 LD=TTV_LINE_D;
876 LE=TTV_LINE_E;
877 LF=TTV_LINE_F;
878
879 if (TTV_BASE_LOFIG==&editmodelofig)
880 {
881 loaded=ttv_getloadedfigtypes(current_ttvfig);
882 if ((loaded & TTV_FILE_TTX)==TTV_FILE_TTX)
883 {
884 LD=TTV_LINE_T;
885 LE=TTV_LINE_J;
886 LF=TTV_LINE_P;
887
888 if ((type & TTV_LINE_D)==TTV_LINE_D) { type&=~TTV_LINE_D; type|=LD; }
889 if ((type & TTV_LINE_E)==TTV_LINE_E) { type&=~TTV_LINE_E; type|=LE; }
890 if ((type & TTV_LINE_F)==TTV_LINE_F) { type&=~TTV_LINE_F; type|=LF; }
891 }
892 }
893
894 switch (type)
895 {
896 case TTV_SETUP:
897 case TTV_HOLD:
898 case TTV_ACCESS:
899 if (type==TTV_SETUP) type=TTV_LINE_U;
900 else if (type==TTV_HOLD) type=TTV_LINE_O;
901 else type=TTV_LINE_A;
902
903
904 if (((input->TYPE|output->TYPE) & (TTV_SIG_C|TTV_SIG_N))!=0)
905 type|=LD;
906 else
907 type|=LE;
908
909 break;
910 case TTV_TIMING:
911 if (((input->TYPE|output->TYPE) & (TTV_SIG_C|TTV_SIG_N))!=0)
912 type=LD;
913 else
914 type=LF;
915 }
916
917 if ((type & (TTV_LINE_O|TTV_LINE_A|TTV_LINE_U))!=0)
918 {
919 ptype_list *pt;
920 SetAsBreakpointIfNeeded(input);
921 SetAsBreakpointIfNeeded(output);
922 if ((type & TTV_LINE_A)!=TTV_LINE_A) vali|=TTV_mark_IN, valo|=TTV_mark_IN;
923 else vali|=TTV_mark_IN, valo|=TTV_mark_OUT;
924
925 if ((type & TTV_LINE_A)==TTV_LINE_A)
926 lnode=&output->NODE[b], cmdnode=&input->NODE[a];
927 else
928 lnode=&input->NODE[a], cmdnode=&output->NODE[(b+1) & 1];
929 if (lnode->ROOT->TYPE & TTV_SIG_L)
930 {
931 if ((pt=getptype(lnode->ROOT->USER, TTV_SIG_CMD))==NULL)
932 pt=lnode->ROOT->USER=addptype(lnode->ROOT->USER, TTV_SIG_CMD, NULL);
933
934 if (getchain(pt->DATA, cmdnode)==NULL)
935 pt->DATA=addchain((chain_list *)pt->DATA, cmdnode);
936 }
937 }
938 else
939 {
940 vali|=TTV_mark_IN;
941 valo|=TTV_mark_OUT;
942 if ((type & TTV_LINE_HZ)==TTV_LINE_HZ) valo|=TTV_mark_HZ;
943 }
944
945 if (pti!=NULL) pti->DATA=(void *)vali;
946 if (pto!=NULL) pto->DATA=(void *)valo;
947
948 if (CompareSubtype(input, output))
949 {
950 type|=TTV_LINE_RC;
951 }
952
953 tvl=ttv_addline(current_ttvfig,
954 &output->NODE[b], &input->NODE[a],
955 (long)(max_delay*1e12*TTV_UNIT),
956 (long)ttv_tas_thr2scm(max_slope*1e12*TTV_UNIT, b),
957 (long)(min_delay*1e12*TTV_UNIT),
958 (long)ttv_tas_thr2scm(min_slope*1e12*TTV_UNIT, b),
959 type);
960 IFGNS (
961 ALL_LINES=addchain(ALL_LINES, tvl);
962 )
963 return tvl;
964 }
965
966 void ttv_Associate_Model(ttvline_list *tvl, void *func)
967 {
968 char *nt;
969 timing_model *tmodel;
970 HierLofigInfo *hli;
971 ArcInfo *ai;
972 double capa = 0.0, slope = STM_DEF_SLEW;
973 float vt=STM_NOVALUE, vdd=STM_NOVALUE, vf=STM_NOVALUE, vth=STM_NOVALUE;
974
975 if (func==NULL || TTV_BASE_LOFIG==&editmodelofig) return ;
976 if (tvl==NULL || CheckFirstCallForThisModel()) { APIFreeCallFunc(func); return ;}
977
978 nt=ttv_getarcdef(tvl);
979
980 stm_addfctmodel (current_ttvfig->INSNAME, nt, "?", nt, func);
981
982 tmodel=stm_getmodel(current_ttvfig->INSNAME, nt);
983
984 stm_mod_setcaracslew (tmodel, 0.2 * slope);
985 stm_mod_setcaracslew (tmodel, 1.8 * slope);
986 // TODO get the real value of the capa
987 capa=tvl->ROOT->ROOT->CAPA; // en Ff
988 stm_mod_setcaracload (tmodel, 0.2 * capa);
989 stm_mod_setcaracload (tmodel, 1.8 * capa);
990
991
992 // vdd/2, vdd, vt, vfinal
993 if (nt[strlen(nt)-1]=='d') vf=0.0;
994 else if (ttv_high!=-1) vf=ttv_high-ttv_low;
995
996 if (ttv_high!=-1)
997 {
998 vdd=ttv_high-ttv_low;
999 vt=vdd*0.2;
1000 vth=vdd*V_FLOAT_TAB[__SIM_VTH].VALUE;
1001 }
1002 stm_mod_update(tmodel, vth, vdd, vt, vf);
1003
1004 if ((tvl->TYPE & (TTV_LINE_O|TTV_LINE_U))==0
1005 || (tvl->TYPE & TTV_LINE_A)==TTV_LINE_A)
1006 ttv_addcaracline(tvl, nt, nt, nt, nt);
1007 else
1008 ttv_addcaracline(tvl, nt, nt, NULL, NULL);
1009 hli=gethierlofiginfo(TTV_BASE_LOFIG);
1010 ai=getarcinfo(hli, nt);
1011 ai->MODEL=(APICallFunc *)func;
1012 }
1013
1014
1015 void ttv_Associate_Sim(ttvline_list *tvl, void *func)
1016 {
1017 char *nt;
1018 HierLofigInfo *hli;
1019 ArcInfo *ai;
1020
1021 if (func==NULL || TTV_BASE_LOFIG==&editmodelofig) return ;
1022 if (tvl==NULL || CheckFirstCallForThisModel()) {APIFreeCallFunc(func); return ;}
1023
1024 nt=ttv_getarcdef(tvl);
1025 hli=gethierlofiginfo(TTV_BASE_LOFIG);
1026 ai=getarcinfo(hli, nt);
1027 ai->SIM=(APICallFunc *)func;
1028 }
1029
1030 void ttv_Associate_Env(ttvline_list *tvl, void *func)
1031 {
1032 char *nt;
1033 HierLofigInfo *hli;
1034 ArcInfo *ai;
1035
1036 if (func==NULL || TTV_BASE_LOFIG==&editmodelofig) return ;
1037 if (tvl==NULL || CheckFirstCallForThisModel()) {APIFreeCallFunc(func); return ;}
1038
1039 nt=ttv_getarcdef(tvl);
1040
1041 hli=gethierlofiginfo(TTV_BASE_LOFIG);
1042 ai=getarcinfo(hli, nt);
1043 ai->ENV=(APICallFunc *)func;
1044 }
1045
1046 void ttv_Associate_Ctk_Env(ttvline_list *tvl, void *func)
1047 {
1048 char *nt;
1049 HierLofigInfo *hli;
1050 ArcInfo *ai;
1051
1052 if (func==NULL || TTV_BASE_LOFIG==&editmodelofig) return ;
1053 if (tvl==NULL || CheckFirstCallForThisModel()) return ;
1054
1055 nt=ttv_getarcdef(tvl);
1056
1057 hli=gethierlofiginfo(TTV_BASE_LOFIG);
1058 ai=getarcinfo(hli, nt);
1059 ai->CTK_ENV=(APICallFunc *)func;
1060 }
1061
1062 ttvline_list *ttv_AddTiming(char *input, char *output, double max_delay, double max_slope, double min_delay, double min_slope, char *dir)
1063 {
1064 char it, ot;
1065 char *sin, *sout;
1066 ttvsig_list *tsin, *tsout;
1067 long linetype=TTV_LINE_F;
1068 float capa0, capa1;
1069
1070 if (CheckFirstCallForThisModel()) return NULL;
1071
1072 if ((sin=getsignal(input, &it, &capa0))==NULL) return NULL;
1073 if ((sout=getsignal(output, &ot, &capa1))==NULL) return NULL;
1074
1075 checkslope("min", input, output, dir, &min_slope);
1076 checkslope("max", input, output, dir, &max_slope);
1077
1078 tsin=ttvapi_GetNode(input, sin, capa0);
1079 SetNodeType(tsin, it);
1080 tsout=ttvapi_GetNode(output, sout, capa1);
1081 SetNodeType(tsout, ot);
1082
1083 if (((tsin->TYPE|tsout->TYPE) & (TTV_SIG_C|TTV_SIG_N))!=0)
1084 linetype=TTV_LINE_D;
1085
1086 return ttv_AddCustomLine(tsin, tsout, max_delay, max_slope, min_delay, min_slope, dir, linetype);
1087 }
1088 ttvline_list *ttv_AddHZTiming(char *input, char *output, double max_delay, double min_delay, char *dir)
1089 {
1090 char it, ot;
1091 char *sin, *sout;
1092 ttvsig_list *tsin, *tsout;
1093 long linetype=TTV_LINE_F|TTV_LINE_HZ;
1094 float capa0, capa1;
1095
1096 if (CheckFirstCallForThisModel()) return NULL;
1097
1098 if ((sin=getsignal(input, &it, &capa0))==NULL) return NULL;
1099 if ((sout=getsignal(output, &ot, &capa1))==NULL) return NULL;
1100
1101 tsin=ttvapi_GetNode(input, sin, capa0);
1102 SetNodeType(tsin, it);
1103 tsout=ttvapi_GetNode(output, sout, capa1);
1104 SetNodeType(tsout, ot);
1105
1106 if (((tsin->TYPE|tsout->TYPE) & (TTV_SIG_C|TTV_SIG_N))!=0)
1107 linetype=TTV_LINE_D|TTV_LINE_HZ;
1108
1109 return ttv_AddCustomLine(tsin, tsout, max_delay, 0, min_delay, 0, dir, linetype);
1110 }
1111
1112 ttvline_list *ttv_AddSetup(char *input, char *output, double delay, char *dir)
1113 {
1114 char it, ot;
1115 char *sin, *sout;
1116 ttvsig_list *tsin, *tsout;
1117 long linetype=TTV_LINE_E;
1118 float capa0, capa1;
1119
1120 if (CheckFirstCallForThisModel()) return NULL;
1121
1122 if ((sin=getsignal(input, &it, &capa0))==NULL) return NULL;
1123 if ((sout=getsignal(output, &ot, &capa1))==NULL) return NULL;
1124
1125 tsin=ttvapi_GetNode(input, sin, capa0);
1126 SetNodeType(tsin, it);
1127 tsout=ttvapi_GetNode(output, sout, capa1);
1128 SetNodeType(tsout, ot);
1129
1130 if (((tsin->TYPE|tsout->TYPE) & (TTV_SIG_C|TTV_SIG_N))!=0)
1131 linetype=TTV_LINE_D;
1132
1133 return ttv_AddCustomLine(tsin, tsout, delay, 0, delay, 0, dir, linetype|TTV_LINE_U);
1134 }
1135
1136 ttvline_list *ttv_AddHold(char *input, char *output, double delay, char *dir)
1137 {
1138 char it, ot;
1139 char *sin, *sout;
1140 ttvsig_list *tsin, *tsout;
1141 long linetype=TTV_LINE_E;
1142 float capa0, capa1;
1143
1144 if (CheckFirstCallForThisModel()) return NULL;
1145
1146 if ((sin=getsignal(input, &it, &capa0))==NULL) return NULL;
1147 if ((sout=getsignal(output, &ot, &capa1))==NULL) return NULL;
1148
1149 tsin=ttvapi_GetNode(input, sin, capa0);
1150 SetNodeType(tsin, it);
1151 tsout=ttvapi_GetNode(output, sout, capa1);
1152 SetNodeType(tsout, ot);
1153
1154 if (((tsin->TYPE|tsout->TYPE) & (TTV_SIG_C|TTV_SIG_N))!=0)
1155 linetype=TTV_LINE_D;
1156
1157 return ttv_AddCustomLine(tsin, tsout, delay, 0, delay, 0, dir, linetype|TTV_LINE_O);
1158 }
1159
1160
1161 ttvline_list *ttv_AddAccess(char *input, char *output, double max_delay, double max_slope, double min_delay, double min_slope, char *dir)
1162 {
1163 char it, ot;
1164 char *sin, *sout;
1165 ttvsig_list *tsin, *tsout;
1166 ttvline_list *tl;
1167 long linetype=TTV_LINE_E;
1168 float capa0, capa1;
1169 char dir0[3]=" ";
1170
1171 if (CheckFirstCallForThisModel()) return NULL;
1172
1173 if ((sin=getsignal(input, &it, &capa0))==NULL) return NULL;
1174 if ((sout=getsignal(output, &ot, &capa1))==NULL) return NULL;
1175
1176 tsin=ttvapi_GetNode(input, sin, capa0);
1177 SetNodeType(tsin, it);
1178 tsout=ttvapi_GetNode(output, sout, capa1);
1179 SetNodeType(tsout, ot);
1180
1181 if (((tsin->TYPE|tsout->TYPE) & (TTV_SIG_C|TTV_SIG_N))!=0)
1182 linetype=TTV_LINE_D;
1183
1184 tl=ttv_AddCustomLine(tsin, tsout, max_delay, max_slope, min_delay, min_slope, dir, linetype|TTV_LINE_A);
1185 dir0[0]=*dir;
1186 dir0[1]=*dir;
1187 ttv_SetLineCommand(tl, input, input, dir0);
1188 return tl;
1189 }
1190
1191 ttvline_list *ttv_AddHZAccess(char *input, char *output, double max_delay, double min_delay, char *dir)
1192 {
1193 char it, ot;
1194 char *sin, *sout;
1195 ttvsig_list *tsin, *tsout;
1196 long linetype=TTV_LINE_E;
1197 float capa0, capa1;
1198 ttvline_list *tl;
1199 char dir0[3]=" ";
1200
1201 if (CheckFirstCallForThisModel()) return NULL;
1202
1203 if ((sin=getsignal(input, &it, &capa0))==NULL) return NULL;
1204 if ((sout=getsignal(output, &ot, &capa1))==NULL) return NULL;
1205
1206 tsin=ttvapi_GetNode(input, sin, capa0);
1207 SetNodeType(tsin, it);
1208 tsout=ttvapi_GetNode(output, sout, capa1);
1209 SetNodeType(tsout, ot);
1210
1211 if (((tsin->TYPE|tsout->TYPE) & (TTV_SIG_C|TTV_SIG_N))!=0)
1212 linetype=TTV_LINE_D|TTV_LINE_HZ;
1213
1214 tl=ttv_AddCustomLine(tsin, tsout, max_delay, 0, min_delay, 0, dir, linetype|TTV_LINE_A);
1215 dir0[0]=*dir;
1216 dir0[1]=*dir;
1217 ttv_SetLineCommand(tl, input, input, dir0);
1218 return tl;
1219 }
1220
1221 void ShareStmFCTModels()
1222 {
1223 chain_list *cl;
1224 ttvline_list *tvl;
1225 HierLofigInfo *hli;
1226 ArcInfo *ai;
1227 char *nt, *key, *nt0, *nt1, *nt2, *nt3;
1228 ht *uniquemodels;
1229 NameAllocator na;
1230 char trans, temp[4096];
1231 long l;
1232 int cnt=0, total=0;
1233 timing_model *tmodel;
1234
1235 CreateNameAllocator(1024, &na, CASE_SENSITIVE);
1236 uniquemodels=addht(1024);
1237 hli=gethierlofiginfo(TTV_BASE_LOFIG);
1238
1239 for (cl=ALL_LINES, cnt=0; cl!=NULL; cl=cl->NEXT)
1240 {
1241 tvl=(ttvline_list *)cl->DATA;
1242 nt=ttv_getarcdef(tvl);
1243 ai=getarcinfo(hli, nt);
1244
1245 strcpy(temp,"");
1246 if (ai->MODEL!=NULL)
1247 { APIPrintCallFunc(ai->MODEL, &temp[strlen(temp)]); strcat(temp,"|"); }
1248 if (ai->SIM!=NULL)
1249 { APIPrintCallFunc(ai->SIM, &temp[strlen(temp)]); strcat(temp,"|"); }
1250 if (ai->ENV!=NULL)
1251 { APIPrintCallFunc(ai->ENV, &temp[strlen(temp)]); strcat(temp,"|"); }
1252 if (ai->CTK_ENV!=NULL)
1253 { APIPrintCallFunc(ai->CTK_ENV, &temp[strlen(temp)]); strcat(temp,"|"); }
1254
1255 if (strlen(temp)!=0)
1256 {
1257 key=NameAlloc(&na, temp);
1258 l=gethtitem(uniquemodels, key);
1259 if (l!=EMPTYHT)
1260 {
1261 cnt++;
1262 if ((long)nt!=l)
1263 {
1264 stm_freemodel(current_ttvfig->INSNAME, nt);
1265 nt=(char *)l;
1266 if ((tvl->TYPE & (TTV_LINE_O|TTV_LINE_U))==0
1267 || (tvl->TYPE & TTV_LINE_A)==TTV_LINE_A)
1268 ttv_addcaracline(tvl, nt, nt, nt, nt);
1269 else
1270 ttv_addcaracline(tvl, nt, nt, NULL, NULL);
1271 }
1272 }
1273 else
1274 addhtitem(uniquemodels, key, (long)nt);
1275 }
1276 else
1277 {
1278 if (tvl->ROOT==&tvl->ROOT->ROOT->NODE[0]) trans='d'; else trans='u';
1279 sprintf(temp,"cst_%.1fps_%c", tvl->VALMAX/TTV_UNIT, trans); nt0=namealloc(temp);
1280 stm_addconstmodel(current_ttvfig->INSNAME, nt0, tvl->VALMAX/TTV_UNIT);
1281
1282 sprintf(temp,"cst_%.1fps_%c", tvl->VALMIN/TTV_UNIT, trans); nt2=namealloc(temp);
1283 stm_addconstmodel(current_ttvfig->INSNAME, nt2, tvl->VALMIN/TTV_UNIT);
1284
1285 if (trans=='d')
1286 {
1287 tmodel=stm_getmodel(current_ttvfig->INSNAME, nt0);
1288 stm_mod_update(tmodel, STM_NOVALUE, STM_NOVALUE, STM_NOVALUE, 0.0);
1289 tmodel=stm_getmodel(current_ttvfig->INSNAME, nt2);
1290 stm_mod_update(tmodel, STM_NOVALUE, STM_NOVALUE, STM_NOVALUE, 0.0);
1291 }
1292
1293 if (!((tvl->TYPE & (TTV_LINE_O|TTV_LINE_U))==0
1294 || (tvl->TYPE & TTV_LINE_A)==TTV_LINE_A))
1295 {
1296 ttv_addcaracline(tvl, nt0, nt2, NULL, NULL);
1297 }
1298 else
1299 {
1300 sprintf(temp,"cst_%.1fps_%c", tvl->FMAX/TTV_UNIT, trans); nt1=namealloc(temp);
1301 stm_addconstmodel(current_ttvfig->INSNAME, nt1, tvl->FMAX/TTV_UNIT);
1302 sprintf(temp,"cst_%.1fps_%c", tvl->FMIN/TTV_UNIT, trans); nt3=namealloc(temp);
1303 stm_addconstmodel(current_ttvfig->INSNAME, nt3, tvl->FMIN/TTV_UNIT);
1304
1305 if (trans=='d')
1306 {
1307 tmodel=stm_getmodel(current_ttvfig->INSNAME, nt1);
1308 stm_mod_update(tmodel, STM_NOVALUE, STM_NOVALUE, STM_NOVALUE, 0.0);
1309 tmodel=stm_getmodel(current_ttvfig->INSNAME, nt3);
1310 stm_mod_update(tmodel, STM_NOVALUE, STM_NOVALUE, STM_NOVALUE, 0.0);
1311 }
1312
1313 ttv_addcaracline(tvl, nt0, nt2, nt1, nt3);
1314 }
1315 }
1316 total++;
1317 }
1318
1319 if (cnt!=0)
1320 avt_fprintf(stdout,"[¤1info¤.] %d/%d timing lines share their model\n",cnt,total);
1321 DeleteNameAllocator(&na);
1322 delht(uniquemodels);
1323 freechain(ALL_LINES);
1324 }
1325
1326 static void ChangeConDir(ttvsig_list *tvs)
1327 {
1328 ptype_list *pt;
1329 long type, val;
1330
1331 if ((pt=getptype(tvs->USER, TTV_TEMP_PTYPE))!=NULL)
1332 {
1333 type=TTV_SIG_CX;
1334 val=(long)pt->DATA;
1335 if ((val & (TTV_mark_IN|TTV_mark_OUT))==(TTV_mark_IN|TTV_mark_OUT))
1336 {
1337 if (val & TTV_mark_HZ) type=TTV_SIG_CT;
1338 else type=TTV_SIG_CB;
1339 }
1340 else if ((val & TTV_mark_OUT)==TTV_mark_OUT)
1341 {
1342 if (val & TTV_mark_HZ) type=TTV_SIG_CZ;
1343 else type=TTV_SIG_CO;
1344 }
1345 else if ((val & TTV_mark_IN)==TTV_mark_IN)
1346 {
1347 type=TTV_SIG_CI;
1348 }
1349 tvs->TYPE&=~TTV_SIG_CX;
1350 tvs->TYPE|=type;
1351 tvs->USER=delptype(tvs->USER, TTV_TEMP_PTYPE);
1352 }
1353
1354 }
1355 static void DispatchNodes()
1356 {
1357 chain_list *cl;
1358 ttvsig_list *tvs;
1359
1360 freechain((chain_list *)current_ttvfig->NCSIG); current_ttvfig->NCSIG=NULL;
1361 freechain((chain_list *)current_ttvfig->ELCMDSIG); current_ttvfig->ELCMDSIG=NULL;
1362 freechain((chain_list *)current_ttvfig->ELATCHSIG); current_ttvfig->ELATCHSIG=NULL;
1363 freechain((chain_list *)current_ttvfig->EPRESIG); current_ttvfig->EPRESIG=NULL;
1364 freechain((chain_list *)current_ttvfig->EBREAKSIG); current_ttvfig->EBREAKSIG=NULL;
1365 freechain((chain_list *)current_ttvfig->ESIG); current_ttvfig->ESIG=NULL;
1366 freechain((chain_list *)current_ttvfig->CONSIG); current_ttvfig->CONSIG=NULL;
1367
1368 for (cl=ALL_ADDED_NODES; cl!=NULL; cl=cl->NEXT)
1369 {
1370 tvs=(ttvsig_list *)cl->DATA;
1371 if ((tvs->TYPE & TTV_SIG_C)==TTV_SIG_C)
1372 {
1373 ChangeConDir(tvs);
1374 current_ttvfig->CONSIG=(ttvsig_list **)addchain((chain_list *)current_ttvfig->CONSIG, tvs);
1375 }
1376 if ((tvs->TYPE & TTV_SIG_N)==TTV_SIG_N)
1377 current_ttvfig->NCSIG=(ttvsig_list **)addchain((chain_list *)current_ttvfig->NCSIG, tvs);
1378 if ((tvs->TYPE & TTV_SIG_Q)==TTV_SIG_Q)
1379 current_ttvfig->ELCMDSIG=(ttvsig_list **)addchain((chain_list *)current_ttvfig->ELCMDSIG, tvs);
1380 if ((tvs->TYPE & TTV_SIG_L)==TTV_SIG_L)
1381 current_ttvfig->ELATCHSIG=(ttvsig_list **)addchain((chain_list *)current_ttvfig->ELATCHSIG, tvs);
1382 if ((tvs->TYPE & TTV_SIG_R)==TTV_SIG_R)
1383 current_ttvfig->EPRESIG=(ttvsig_list **)addchain((chain_list *)current_ttvfig->EPRESIG, tvs);
1384 if ((tvs->TYPE & TTV_SIG_B)==TTV_SIG_B)
1385 current_ttvfig->EBREAKSIG=(ttvsig_list **)addchain((chain_list *)current_ttvfig->EBREAKSIG, tvs);
1386 if ((tvs->TYPE & TTV_SIG_S)==TTV_SIG_S)
1387 current_ttvfig->ESIG=(ttvsig_list **)addchain((chain_list *)current_ttvfig->ESIG, tvs);
1388 }
1389 freechain(ALL_ADDED_NODES);
1390 }
1391
1392 void ttv_API_Action_Terminate() // commentaire pour desactiver l'ajout de token
1393 {
1394 int delete;
1395 int editmode=0;
1396 long loaded, filetype;
1397
1398 HierLofigInfo *hli;
1399
1400 IFGNS (
1401 if (CALLED_TTV_FUNCTION==0)
1402 {
1403 hli=gethierlofiginfo(CUR_HIER_LOFIG);
1404 if (hli->BUILD_TTV==NULL) return;
1405 else
1406 if (CheckFirstCallForThisModel()) return;
1407 }
1408
1409 ShareStmFCTModels();
1410 )
1411
1412 if (TTV_BASE_LOFIG==NULL) return;
1413
1414 if (TTV_BASE_LOFIG==&editmodelofig) editmode=1;
1415
1416 DispatchNodes();
1417
1418 filetype=TTV_FILE_DTX;
1419 if (editmode)
1420 {
1421 loaded=ttv_getloadedfigtypes(current_ttvfig);
1422 if ((loaded & TTV_FILE_TTX)==TTV_FILE_TTX) filetype=TTV_FILE_TTX;
1423 }
1424
1425 current_ttvfig->STATUS |= TTV_STS_DTX ;
1426
1427 delete = tas_deleteflatemptyfig(current_ttvfig, filetype, 'Y');
1428
1429 tas_detectloop(current_ttvfig, filetype);
1430
1431 ttv_builtrefsig(current_ttvfig);
1432
1433 if(delete != 0)
1434 {
1435 ttv_setttvlevel(current_ttvfig) ;
1436 ttv_setsigttvfiglevel(current_ttvfig) ;
1437 }
1438
1439 if (!editmode)
1440 {
1441 ttv_setttvdate (current_ttvfig, TTV_DATE_LOCAL);
1442 current_ttvfig->INFO->TOOLNAME = namealloc ("ttv_API");
1443 current_ttvfig->INFO->TOOLVERSION = namealloc ("1.0");
1444 current_ttvfig->INFO->TECHNONAME = namealloc ("spice");
1445 current_ttvfig->INFO->TECHNOVERSION = namealloc ("1.0");
1446 current_ttvfig->INFO->SLOPE = (long)(TTVSLOPE*1e12*TTV_UNIT);
1447 current_ttvfig->INFO->CAPAOUT = (long)(TTVCAPA*1e12);
1448 current_ttvfig->INFO->STHHIGH = V_FLOAT_TAB[__SIM_VTH_HIGH].VALUE;
1449 current_ttvfig->INFO->STHLOW = V_FLOAT_TAB[__SIM_VTH_LOW].VALUE;
1450 current_ttvfig->INFO->DTH = V_FLOAT_TAB[__SIM_VTH].VALUE;
1451 current_ttvfig->INFO->TEMP = V_FLOAT_TAB[__SIM_TEMP].VALUE;
1452 current_ttvfig->INFO->VDD = V_FLOAT_TAB[__SIM_POWER_SUPPLY].VALUE;
1453
1454 if (TTVFLAGS & TTV_DRIVE_DTX)
1455 {
1456 ttv_drittv (current_ttvfig, filetype, (long)0, NULL);
1457 stm_drivecell(current_ttvfig->INSNAME);
1458 }
1459
1460 if ((TTVFLAGS & TTV_INSTANCE_MODE)==0 && TTV_FORCED_NAME==NULL)
1461 TTV_BASE_LOFIG->USER=addptype(TTV_BASE_LOFIG->USER, TTV_DONE_PTYPE, current_ttvfig);
1462
1463 current_dup_lofig->LOINS=(loins_list *)append((chain_list *)current_dup_lofig->LOINS, (chain_list *)loins_removed);
1464 current_dup_lofig->LOSIG=(losig_list *)append((chain_list *)current_dup_lofig->LOSIG, (chain_list *)losig_removed);
1465 }
1466
1467 CALLED_TTV_FUNCTION=0;
1468 TTV_BASE_LOFIG=NULL;
1469 TTV_FUNCTIONS_FILE = NULL;
1470 ALL_ADDED_NODES=NULL;
1471 current_dup_lofig=NULL;
1472 TTV_FORCED_NAME=NULL;
1473 delht(nodeht);
1474
1475 IFGNS( ALL_MY_TTV=addchain(ALL_MY_TTV, current_ttvfig); )
1476
1477 tas_restore();
1478 //avt_restorecontext ();
1479
1480 }
1481
1482 ttvfig_list *ttv_FinishTimingFigure()
1483 {
1484 ttvfig_list *tvf;
1485 if (CheckFirstCallForThisModel()) return NULL;
1486 tvf=current_ttvfig;
1487 ttv_API_Action_Terminate();
1488 return tvf;
1489 }
1490
1491 void ttv_DriveTimingFigure(ttvfig_list *tvf, char *filename, char *format)
1492 {
1493 if (tvf==NULL) return;
1494 ttv_disablecache(tvf);
1495 if (strcasecmp(format,"dtx")==0)
1496 ttv_drittv (tvf, TTV_FILE_DTX, (long)0, filename);
1497 else if (strcasecmp(format,"ttx")==0)
1498 ttv_drittv (tvf, TTV_FILE_TTX, (long)0, filename);
1499 else
1500 {
1501 avt_errmsg(TTV_API_ERRMSG, "010", AVT_ERROR, format, filename);
1502 // avt_error("ttvapi", 4, AVT_ERR, "unknown file format '%s' for timing file '%s'\n", format, filename);
1503 return;
1504 }
1505
1506 stm_drivecell(tvf->INFO->FIGNAME);
1507 }
1508 void ttv_BuildTiming()
1509 {
1510 if (CheckFirstCallForThisModel()) return;
1511 ttv_API_Action_Terminate();
1512 }
1513
1514 void ttv_TasBuiltTiming(lofig_list *lf)
1515 {
1516 cnsfig_list *cnsf;
1517 ttvfig_list *tvf;
1518
1519 elpLoadOnceElp();
1520
1521 //avt_savecontext();
1522 tas_setenv();
1523 yagenv(tas_yaginit);
1524
1525 YAG_CONTEXT->YAG_GENIUS=FALSE;
1526 cnsf=yagDisassemble(lf->NAME, lf, 0);
1527
1528 TAS_CONTEXT->TAS_LOFIG=lf;
1529 TAS_CONTEXT->TAS_FIND_MIN = 'Y';
1530 tas_TechnoParameters();
1531
1532
1533 tas_capasig(lf);
1534 elpLofigAddCapas ( lf, elpTYPICAL );
1535
1536 tas_detectinout (cnsf);
1537
1538 tas_initcnsfigalloc (cnsf);
1539 tvf=tas_builtfig(lf);
1540 tas_loconorient(lf,tvf);
1541 tas_setsigname(lf);
1542 tas_timing (cnsf, lf, tvf);
1543 tvf=tas_cns2ttv(cnsf, tvf, lf);
1544 ttv_setttvdate (tvf, TTV_DATE_LOCAL);
1545 tvf->INFO->TOOLNAME = namealloc ("ttv_API_subtas");
1546 tvf->INFO->TOOLVERSION = namealloc ("1.0");
1547 tvf->INFO->TECHNONAME = namealloc ("tas");
1548 tvf->INFO->TECHNOVERSION = namealloc ("1.0");
1549 tvf->INFO->SLOPE = (long)(TTVSLOPE*1e12);
1550 tvf->INFO->CAPAOUT = (long)(TTVCAPA*1e12);
1551
1552 if (TTVFLAGS & TTV_DRIVE_DTX)
1553 {
1554 ttv_drittv (tvf, TTV_FILE_DTX, (long)0, NULL);
1555 stm_drivecell(tvf->INSNAME);
1556 }
1557 CNS_HEADCNSFIG = delcnsfig(CNS_HEADCNSFIG, cnsf);
1558
1559 ALL_MY_TTV=addchain(ALL_MY_TTV, tvf);
1560 yagrestore();
1561 tas_restore();
1562 //avt_restorecontext();
1563 }
1564
1565 void ttv_API_TopLevel(long list) // commentaire pour desactiver l'ajout de token
1566 {
1567 chain_list *cl=(chain_list *)list;
1568 chain_list *ch;
1569 ttvfig_list *tvf;
1570 timing_cell *cell;
1571 locon_list *lc;
1572 loins_list *li;
1573 ht *myttvfigs;
1574 int dir;
1575
1576 if ((TTVFLAGS & TTV_INSTANCE_MODE)==0)
1577 {
1578 myttvfigs=addht(1024);
1579 for (ch=ALL_MY_TTV; ch!=NULL; ch=ch->NEXT)
1580 {
1581 tvf=(ttvfig_list *)ch->DATA;
1582 addhtitem(myttvfigs, tvf->INSNAME, (long)tvf);
1583 }
1584 }
1585
1586 for (cl=(chain_list *)list; cl!=NULL; cl=cl->NEXT)
1587 {
1588 li=(loins_list *)cl->DATA;
1589 if ((TTVFLAGS & TTV_INSTANCE_MODE)!=0 || gethtitem(myttvfigs, li->INSNAME)!=EMPTYHT)
1590 {
1591 li->FIGNAME=li->INSNAME;
1592 }
1593 }
1594
1595 if ((TTVFLAGS & TTV_INSTANCE_MODE)==0)
1596 {
1597 delht(myttvfigs);
1598 }
1599
1600 for (ch=ALL_MY_TTV; ch!=NULL; ch=ch->NEXT)
1601 {
1602 tvf=(ttvfig_list *)ch->DATA;
1603
1604 for (cl=(chain_list *)list; cl!=NULL; cl=cl->NEXT)
1605 {
1606 if (((loins_list *)cl->DATA)->FIGNAME==tvf->INSNAME) break;
1607 }
1608 if (cl==NULL)
1609 {
1610 ttv_unlockttvfig(tvf);
1611 if((cell = stm_getcell(tvf->INFO->FIGNAME)) != NULL){
1612 stm_freecell(tvf->INFO->FIGNAME) ;
1613 cell = NULL;
1614 }
1615 ttv_freeallttvfig(tvf);
1616 }
1617 else
1618 {
1619 for (cl=(chain_list *)list; cl!=NULL; cl=cl->NEXT)
1620 {
1621 li=(loins_list *)cl->DATA;
1622 for (lc=li->LOCON; lc!=NULL; lc=lc->NEXT)
1623 {
1624 dir=mbk_rc_are_internal(li, lc);
1625 if (dir==1)
1626 {
1627 if (getptype(lc->SIG->USER, TAS_SIG_NORCDELAY)==NULL)
1628 lc->SIG->USER=addptype(lc->SIG->USER, TAS_SIG_NORCDELAY, NULL);
1629 }
1630 }
1631 }
1632 }
1633 }
1634
1635 freechain(ALL_MY_TTV);
1636 ALL_MY_TTV=NULL;
1637 }
1638
1639 int ttv_MinDelay()
1640 {
1641 int state;
1642 if (TTV_COM==NULL) return 0;
1643 if (TTV_COM(TTV_getdelaytype, &state)) return 0;
1644 if (state==TTV_getdelaytype_min) return 1;
1645 return 0;
1646 }
1647
1648 int ttv_MaxDelay()
1649 {
1650 int state;
1651 if (TTV_COM==NULL) return 0;
1652 if (TTV_COM(TTV_getdelaytype, &state)) return 0;
1653 if (state==TTV_getdelaytype_max) return 1;
1654 return 0;
1655 }
1656
1657
1658 void ASSOCIATE_TIMING(void *func)
1659 {
1660 APICallFunc *cf=(APICallFunc *)func;
1661 t_arg *ret;
1662 HierLofigInfo *hli=gethierlofiginfo(CUR_HIER_LOFIG);
1663
1664 if (TTVFLAGS & TTV_INSTANCE_MODE || hli->BUILD_TTV==NULL)
1665 {
1666 // ajout a la lofig hierarchique de l'info
1667 hli->BUILD_TTV=cf;
1668 //
1669 if (APIExecAPICallFunc(APIGetExecutionContext(), cf, &ret, 0)) EXIT(1);
1670 if (ret!=NULL)
1671 {
1672 APIFreeTARG(ret);
1673 }
1674 }
1675 else
1676 {
1677 APIFreeTARGS(cf->ARGS);
1678 mbkfree(cf);
1679 }
1680 }
1681
1682 void ttv_SetLineCommand(ttvline_list *tl, char *max_command, char *min_command, char *dir)
1683 {
1684 ttvsig_list *tvs;
1685 int a, b;
1686
1687 if (tl==NULL) return;
1688
1689 ttv_dir_to_index(dir, &a, &b);
1690 if (min_command==NULL) min_command=max_command, b=a;
1691 if (a==-1 || b==-1)
1692 {
1693 avt_errmsg(TTV_API_ERRMSG, "009", AVT_ERROR, gen_info(), dir);
1694 // avt_error("ttvapi", 3, AVT_ERR, "%s: invalid direction '%s', timing line command creation ignored\n", gen_info(), dir);
1695 return;
1696 }
1697 if (tl->ROOT->ROOT->TYPE & TTV_SIG_L)
1698 {
1699 tvs=ttv_AddCommand(max_command);
1700 ttv_addcmd(tl, TTV_LINE_CMDMAX, &tvs->NODE[a]) ;
1701 tvs=ttv_AddCommand(min_command);
1702 ttv_addcmd(tl, TTV_LINE_CMDMIN, &tvs->NODE[b]) ;
1703 }
1704 }
1705
1706 void ttv_SetLineModel(ttvline_list *tl, char *modelname, char *where)
1707 {
1708 int slope, max;
1709 char *a[2][2];
1710
1711 if (tl==NULL) return;
1712
1713 if (strstr(where,"slope")!=NULL) slope=1;
1714 else slope=0;
1715 if (strstr(where,"max")!=NULL) max=1;
1716 else max=0;
1717
1718 a[0][1]=tl->MDMAX;
1719 a[0][0]=tl->MDMIN;
1720 a[1][1]=tl->MFMAX;
1721 a[1][0]=tl->MFMIN;
1722
1723 a[slope][max]=namealloc(modelname);
1724
1725 if ((tl->TYPE & (TTV_LINE_O|TTV_LINE_U))==0
1726 || (tl->TYPE & TTV_LINE_A)==TTV_LINE_A)
1727 ttv_addcaracline(tl, a[0][1], a[0][0], a[1][1], a[1][0]);
1728 else
1729 ttv_addcaracline(tl, a[0][1], a[0][0], NULL, NULL);
1730 }
1731
1732 void ttv_SetTimingFigureName( ttvfig_list *tvf, char *name )
1733 {
1734 char *aname ;
1735 if( !tvf || !name ) return ;
1736 aname = namealloc( name );
1737 ttv_delhtmodel( tvf );
1738 if( !stm_renamecell( tvf->INFO->FIGNAME, aname ) ) {
1739 printf( "can't rename stm model\n" );
1740 }
1741 tvf->INFO->FIGNAME = aname ;
1742 tvf->INSNAME = aname ;
1743 ttv_addhtmodel( tvf );
1744 }
1745
1746 void ttv_CreateTimingTableModel(ttvfig_list *tvf, char *name, chain_list *input_slope, chain_list *output_capa, chain_list *values, char *type)
1747 {
1748 int nbs, nbc, slope, i, j;
1749 timing_model *model = NULL;
1750 chain_list *cl, *ch;
1751 float u1, u2;
1752 long t1, t2;
1753
1754 IFGNS( if (tvf==NULL) tvf=current_ttvfig; )
1755
1756 if (tvf==NULL) return;
1757
1758 nbs=countchain(input_slope);
1759 nbc=countchain(output_capa);
1760 if (strcasecmp(type,"slope-slope")==0) u1=u2=1e12, t1=t2=STM_INPUT_SLEW;
1761 else if (strcasecmp(type,"slope-ckslope")==0) u1=u2=1e12, t1=STM_INPUT_SLEW, t2=STM_CLOCK_SLEW;
1762 else if (strcasecmp(type,"slope-capa")==0) u1=1e12, u2=1e15, t1=STM_INPUT_SLEW, t2=STM_LOAD;
1763 else
1764 {
1765 avt_errmsg(TTV_API_ERRMSG, "050", AVT_ERROR, type);
1766 return;
1767 }
1768
1769 if ((i=countchain(values))!=nbs)
1770 {
1771 avt_errmsg(TTV_API_ERRMSG, "049", AVT_ERROR, i, nbs);
1772 return;
1773 }
1774
1775 for (ch=values; ch!=NULL; ch=ch->NEXT)
1776 if ((i=countchain((chain_list *)ch->DATA))!=nbc)
1777 {
1778 avt_errmsg(TTV_API_ERRMSG, "049", AVT_ERROR, i, nbc);
1779 return;
1780 }
1781
1782 name=namealloc(name);
1783
1784 if (nbs==1)
1785 {
1786 if (nbc==1)
1787 {
1788 stm_addconstmodel(tvf->INFO->FIGNAME, name, (*(float *)&((chain_list *)values->DATA)->DATA*1e12));
1789 }
1790 else
1791 {
1792 model = stm_addtblmodel (tvf->INFO->FIGNAME, name, nbc, 0, t2, STM_NOTYPE);
1793 for (cl=output_capa, i=0; i<nbc; i++, cl=cl->NEXT)
1794 {
1795 stm_modtbl_setXrangeval(model->UMODEL.TABLE, i, (*(float *)&cl->DATA)*u2);
1796 }
1797 for (ch=values; ch!=NULL; ch=ch->NEXT)
1798 for (cl=(chain_list *)ch->DATA, i=0; cl!=NULL; cl=cl->NEXT, i++)
1799 stm_modtbl_set1Dval (model->UMODEL.TABLE, i, (*(float *)&cl->DATA)*1e12);
1800 }
1801 }
1802 else if (nbc==1)
1803 {
1804 model = stm_addtblmodel (tvf->INFO->FIGNAME, name, nbs, 0, t1, STM_NOTYPE);
1805 for (cl=input_slope, i=0; i<nbs; i++, cl=cl->NEXT)
1806 {
1807 stm_modtbl_setXrangeval(model->UMODEL.TABLE, i, (*(float *)&cl->DATA)*u1);
1808 }
1809 for (cl=values, i=0; cl!=NULL; cl=cl->NEXT, i++)
1810 for (ch=(chain_list *)cl->DATA; ch!=NULL; ch=ch->NEXT)
1811 stm_modtbl_set1Dval (model->UMODEL.TABLE, i, (*(float *)&ch->DATA)*1e12);
1812 }
1813 else
1814 {
1815 model = stm_addtblmodel (tvf->INFO->FIGNAME, name, nbs, nbc, t1, t2);
1816 for (cl=input_slope, i=0; i<nbs; i++, cl=cl->NEXT)
1817 {
1818 stm_modtbl_setXrangeval(model->UMODEL.TABLE, i, (*(float *)&cl->DATA)*u1);
1819 }
1820 for (cl=output_capa, i=0; i<nbc; i++, cl=cl->NEXT)
1821 {
1822 stm_modtbl_setYrangeval(model->UMODEL.TABLE, i, (*(float *)&cl->DATA)*u2);
1823 }
1824 for (ch=values, i=0; i<nbs; i++, ch=ch->NEXT)
1825 for (j=0, cl=(chain_list *)ch->DATA; j<nbc; j++, cl=cl->NEXT)
1826 {
1827 stm_modtbl_set2Dval(model->UMODEL.TABLE, i, j, (*(float *)&cl->DATA)*1e12);
1828 }
1829 }
1830 }
1831
1832 void ttv_CreateEnergyTableModel(ttvfig_list *tvf, char *name, chain_list *input_slope, chain_list *output_capa, chain_list *values, char *type)
1833 {
1834 int nbs, nbc, slope, i, j;
1835 timing_model *model = NULL;
1836 chain_list *cl, *ch;
1837 float u1, u2;
1838 long t1, t2;
1839
1840 IFGNS( if (tvf==NULL) tvf=current_ttvfig; )
1841
1842 if (tvf==NULL) return;
1843
1844 nbs=countchain(input_slope);
1845 nbc=countchain(output_capa);
1846 if (strcasecmp(type,"slope-slope")==0) u1=u2=1e12, t1=t2=STM_INPUT_SLEW;
1847 else if (strcasecmp(type,"slope-ckslope")==0) u1=u2=1e12, t1=STM_INPUT_SLEW, t2=STM_CLOCK_SLEW;
1848 else if (strcasecmp(type,"slope-capa")==0) u1=1e12, u2=1e15, t1=STM_INPUT_SLEW, t2=STM_LOAD;
1849 else
1850 {
1851 avt_errmsg(TTV_API_ERRMSG, "050", AVT_ERROR, type);
1852 return;
1853 }
1854
1855 if ((i=countchain(values))!=nbs)
1856 {
1857 avt_errmsg(TTV_API_ERRMSG, "049", AVT_ERROR, i, nbs);
1858 return;
1859 }
1860
1861 for (ch=values; ch!=NULL; ch=ch->NEXT)
1862 if ((i=countchain((chain_list *)ch->DATA))!=nbc)
1863 {
1864 avt_errmsg(TTV_API_ERRMSG, "049", AVT_ERROR, i, nbc);
1865 return;
1866 }
1867
1868 name=namealloc(name);
1869
1870 model=stm_getmodel(tvf->INFO->FIGNAME, name);
1871
1872 if (nbs==1)
1873 {
1874 if (nbc==1)
1875 {
1876 model->ENERGYTYPE = STM_ENERGY_TABLE;
1877 model->ENERGYMODEL.ETABLE = stm_modtbl_create(0, 0, STM_NOTYPE, STM_NOTYPE);
1878 stm_modtbl_setconst (model->ENERGYMODEL.ETABLE, (*(float *)&((chain_list *)values->DATA)->DATA));
1879 }
1880 else
1881 {
1882 model->ENERGYTYPE = STM_ENERGY_TABLE;
1883 model->ENERGYMODEL.ETABLE = stm_modtbl_create(nbc, 0, t2, STM_NOTYPE);
1884 for (cl=output_capa, i=0; i<nbc; i++, cl=cl->NEXT)
1885 {
1886 stm_modtbl_setXrangeval(model->ENERGYMODEL.ETABLE, i, (*(float *)&cl->DATA)*u2);
1887 }
1888 for (ch=values; ch!=NULL; ch=ch->NEXT)
1889 for (cl=(chain_list *)ch->DATA, i=0; cl!=NULL; cl=cl->NEXT, i++)
1890 stm_modtbl_set1Dval (model->ENERGYMODEL.ETABLE, i, (*(float *)&cl->DATA));
1891 }
1892 }
1893 else if (nbc==1)
1894 {
1895 model->ENERGYTYPE = STM_ENERGY_TABLE;
1896 model->ENERGYMODEL.ETABLE = stm_modtbl_create(nbs, 0, t1, STM_NOTYPE);
1897 for (cl=input_slope, i=0; i<nbs; i++, cl=cl->NEXT)
1898 {
1899 stm_modtbl_setXrangeval(model->ENERGYMODEL.ETABLE, i, (*(float *)&cl->DATA)*u1);
1900 }
1901 for (cl=values, i=0; cl!=NULL; cl=cl->NEXT, i++)
1902 for (ch=(chain_list *)cl->DATA; ch!=NULL; ch=ch->NEXT)
1903 stm_modtbl_set1Dval (model->ENERGYMODEL.ETABLE, i, (*(float *)&ch->DATA));
1904 }
1905 else
1906 {
1907 model->ENERGYTYPE = STM_ENERGY_TABLE;
1908 model->ENERGYMODEL.ETABLE = stm_modtbl_create(nbs, nbc, t1, t2);
1909 for (cl=input_slope, i=0; i<nbs; i++, cl=cl->NEXT)
1910 {
1911 stm_modtbl_setXrangeval(model->ENERGYMODEL.ETABLE, i, (*(float *)&cl->DATA)*u1);
1912 }
1913 for (cl=output_capa, i=0; i<nbc; i++, cl=cl->NEXT)
1914 {
1915 stm_modtbl_setYrangeval(model->ENERGYMODEL.ETABLE, i, (*(float *)&cl->DATA)*u2);
1916 }
1917 for (ch=values, i=0; i<nbs; i++, ch=ch->NEXT)
1918 for (j=0, cl=(chain_list *)ch->DATA; j<nbc; j++, cl=cl->NEXT)
1919 {
1920 stm_modtbl_set2Dval(model->ENERGYMODEL.ETABLE, i, j, (*(float *)&cl->DATA));
1921 }
1922 }
1923 }
1924
1925
1926 chain_list *ttv_CharacTimingLineModel(ttvfig_list *tvf, char *name, chain_list *input_slope, chain_list *output_capa, char *type)
1927 {
1928 int nbs, nbc, slope, i, j, cst=0;
1929 timing_model *model = NULL;
1930 chain_list *cl, *ch, *res, *res1;
1931 float si, sc, u1, u2, val;
1932 long t1, t2;
1933 char *cellname;
1934
1935 IFGNS( if (tvf==NULL) tvf=current_ttvfig; )
1936
1937 if (tvf==NULL) return NULL;
1938
1939 nbs=countchain(input_slope);
1940 nbc=countchain(output_capa);
1941 if (strcasecmp(type,"slope-slope")==0) u1=u2=1e12, cst=1;
1942 else if (strcasecmp(type,"slope-capa:delay")==0) u1=u2=1e12, cst=2;
1943 else if (strcasecmp(type,"slope-capa:slope")==0) u1=1e12, u2=1e15;
1944 else
1945 {
1946 avt_errmsg(TTV_API_ERRMSG, "050", AVT_ERROR, type);
1947 return NULL;
1948 }
1949
1950 name=namealloc(name);
1951 cellname=tvf->INFO->FIGNAME;
1952
1953 res=NULL;
1954 for (ch=input_slope; ch!=NULL; ch=ch->NEXT)
1955 {
1956 si=(*(float *)&ch->DATA)*u1;
1957 res1=NULL;
1958 for (cl=output_capa; cl!=NULL; cl=cl->NEXT)
1959 {
1960 sc=(*(float *)&cl->DATA)*u2;
1961 if (cst==1)
1962 val=stm_getconstraint(cellname, name, si, sc);
1963 else if (cst==2)
1964 val=stm_getdelay(cellname, name, sc, si, NULL, NULL);
1965 else
1966 val=stm_getslew(cellname, name, sc, si, NULL, NULL, NULL);
1967 res1=addchain(res1, NULL);
1968 *(float *)&res1->DATA=val*1e-12;
1969 }
1970 res=addchain(res, reverse(res1));
1971 }
1972 res=reverse(res);
1973 return res;
1974 }
1975
1976 int ttv_LoadSSTAResults(ttvfig_list *tvf, chain_list *filenames, chain_list *order)
1977 {
1978 chain_list *cl;
1979 if (tvf==NULL) return 0;
1980 for (cl=order; cl!=NULL; cl=cl->NEXT)
1981 {
1982 if (countchain((chain_list *)cl->DATA)!=2)
1983 {
1984 avt_errmsg(TTV_API_ERRMSG, "053", AVT_ERROR);
1985 return 0;
1986 }
1987 }
1988 return ttv_ssta_loadresults(tvf, filenames, order);
1989 }
1990
1991 int ttv_SetSSTARunNumber(ttvfig_list *tvf, int num)
1992 {
1993 return ttv_ssta_set_run_number(tvf, num-1);
1994 }
1995
1996 int ttv_BuildSSTALineStats(ttvfig_list *tvf)
1997 {
1998 return ttv_ssta_buildlinestat(tvf);
1999 }