1 /****************************************************************************/
3 /* Chaine de CAO & VLSI AVERTEC */
5 /* Produit : STB Version 1.00 */
6 /* Fichier : stb_drive.c */
8 /* (c) copyright 2000 AVERTEC */
9 /* Tous droits reserves */
11 /* Auteur(s) : Karim DIOURY */
14 /****************************************************************************/
20 #include "stb_error.h"
21 #include "stb_transfer.h"
22 #include "stb_drive.h"
23 #include "stb_directives.h"
25 /*****************************************************************************
26 * static function declarations *
27 *****************************************************************************/
29 static void stb_writesig
__P((FILE *ptfile
, stbfig_list
*ptstbfig
, ttvsig_list
*ptttvsig
, int format
));
30 static void stb_writeintervals
__P((FILE *ptfile
, stbpair_list
*ptheadstbpair
, int format
));
31 static void stb_writeintervals_split(FILE *ptfile
, stbfig_list
*sb
, stbnode
*node
, int hz
, char phase
);
33 /*****************************************************************************
34 * fonction stb_savestbfig() *
35 *****************************************************************************/
39 static void stb_driveconfig(FILE *ptfile
, inffig_list
*ifl
)
43 fprintf(ptfile
, "Conditions\nBegin\n");
44 for (i
=0; i
<(signed)sto_cfg_size
; i
++)
46 if (sto_cfg
[i
].type
=='b' && V_BOOL_TAB
[sto_cfg
[i
].idx
].SET
)
47 fprintf(ptfile
, " %s = \"%s\";\n", V_BOOL_TAB
[sto_cfg
[i
].idx
].VAR
, V_BOOL_TAB
[sto_cfg
[i
].idx
].VALUE
?"yes":"no");
48 else if (sto_cfg
[i
].type
=='s' && V_STR_TAB
[sto_cfg
[i
].idx
].SET
&& V_STR_TAB
[sto_cfg
[i
].idx
].VALUE
!=NULL
)
49 fprintf(ptfile
, " %s = \"%s\";\n", V_STR_TAB
[sto_cfg
[i
].idx
].VAR
, V_STR_TAB
[sto_cfg
[i
].idx
].VALUE
);
50 else if (sto_cfg
[i
].type
=='i' && V_INT_TAB
[sto_cfg
[i
].idx
].SET
)
51 fprintf(ptfile
, " %s = \"%d\";\n", V_INT_TAB
[sto_cfg
[i
].idx
].VAR
, V_INT_TAB
[sto_cfg
[i
].idx
].VALUE
);
53 fprintf(ptfile
, " key_fp_bp = \"%x\";\n", stb_getfalsepathkey(ifl
));
54 fprintf(ptfile
, " key_mc = \"%x\";\n", stb_getmulticyclekey(ifl
));
55 fprintf(ptfile
, " key_d = \"%x\";\n", stb_getdirectivekey(ifl
));
56 fprintf(ptfile
, " key_dm = \"%x\";\n", stb_getdelaymarginkey(ifl
));
57 fprintf(ptfile
, " key_nc = \"%x\";\n", stb_getnocheckkey(ifl
));
58 fprintf(ptfile
, " key_nf_nr = \"%x\";\n", stb_getlistsectionkey(ifl
, INF_NORISING
)*3+stb_getlistsectionkey(ifl
, INF_NOFALLING
));
59 fprintf(ptfile
, " key_fs = \"%x\";\n", stb_getfalseslackkey(ifl
));
60 fprintf(ptfile
, " key_proba = \"%x\";\n",stb_getswitchingprobakey(ifl
));
61 fprintf(ptfile
, " key_uncertainty = \"%x\";\n", stb_getclockuncertaintykey(ifl
));
63 fprintf(ptfile
, "End;\n\n");
67 stb_writesetuphold(FILE *ptfile
, ttvsig_list
*ptttvsig
, char *signame
)
69 stbnode
*nodeu
, *noded
;
70 noded
=stb_getstbnode(ptttvsig
->NODE
);
71 nodeu
=stb_getstbnode(ptttvsig
->NODE
+1);
72 if (nodeu
->SETUP
!=STB_NO_TIME
|| nodeu
->HOLD
!=STB_NO_TIME
73 || noded
->SETUP
!=STB_NO_TIME
|| noded
->HOLD
!=STB_NO_TIME
)
75 fprintf(ptfile
, " \"%s\" :", signame
);
76 fprintf(ptfile
, " ( %s %s ) ", noded
->SETUP
==STB_NO_TIME
?"-":stb_drvtime(noded
->SETUP
), noded
->HOLD
==STB_NO_TIME
?"-":stb_drvtime(noded
->HOLD
));
77 fprintf(ptfile
, " ( %s %s );\n", nodeu
->SETUP
==STB_NO_TIME
?"-":stb_drvtime(nodeu
->SETUP
), nodeu
->HOLD
==STB_NO_TIME
?"-":stb_drvtime(nodeu
->HOLD
));
82 stb_writeflags(FILE *ptfile
, ttvsig_list
*ptttvsig
, char *signame
)
84 stbnode
*nodeu
, *noded
;
85 noded
=stb_getstbnode(ptttvsig
->NODE
);
86 nodeu
=stb_getstbnode(ptttvsig
->NODE
+1);
87 if ((nodeu
->FLAG
& STB_NODE_STABCORRECT
)!=0
88 || (noded
->FLAG
& STB_NODE_STABCORRECT
)!=0)
90 fprintf(ptfile
, " \"%s\" :", signame
);
91 fprintf(ptfile
, " \"%s\"", (noded
->FLAG
& STB_NODE_STABCORRECT
)!=0?"S":"");
92 fprintf(ptfile
, " \"%s\";\n", (nodeu
->FLAG
& STB_NODE_STABCORRECT
)!=0?"S":"");
97 stb_savestbfig(ptstbfig
, mode
, format
, suffix
)
98 stbfig_list
*ptstbfig
;
99 int mode
, format
, suffix
;
102 ttvsig_list
*ptttvsig
;
103 ttvevent_list
*ptevent
;
111 int conditioned
= FALSE
;
112 int internals
= FALSE
;
113 int memories
= FALSE
, invert
, ideal
, virt
;
114 stb_propagated_clock_to_clock
*spctc
;
118 if (suffix
== STB_SUFFIX_STO
) {
119 strcpy(suffixbuf
, "sto");
121 else if (suffix
== STB_SUFFIX_STB
) {
122 strcpy(suffixbuf
, "stb");
125 stb_error(ERR_UNKNOWN_SUFFIX
, NULL
, 0, STB_FATAL
);
128 if ((stbout
= mbkfopen(ptstbfig
->FIG
->INFO
->FIGNAME
, suffixbuf
, WRITE_TEXT
)) == NULL
) {
129 stb_error(ERR_CANNOT_OPEN
, NULL
, 0, STB_FATAL
);
134 avt_printExecInfo(stbout
, "#","","");
136 fprintf(stbout
, "NAME \"%s\";\n", ptstbfig
->FIG
->INFO
->FIGNAME
);
137 fprintf(stbout
, "SETUPTIME %s;\n", stb_drvtime(ptstbfig
->SETUP
));
138 fprintf(stbout
, "HOLDTIME %s;\n", stb_drvtime(ptstbfig
->HOLD
));
139 fprintf(stbout
, "\n");
142 stb_driveconfig(stbout
, getloadedinffig(ptstbfig
->FIG
->INFO
->FIGNAME
));
144 /* Clock Connectors */
146 if (ptstbfig
->CLOCK
!= NULL
) {
147 fprintf(stbout
, "CLOCK CONNECTORS\n");
148 fprintf(stbout
, "BEGIN\n");
150 for (ptchain
= ptstbfig
->CLOCK
; ptchain
; ptchain
= ptchain
->NEXT
) {
151 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
152 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
153 ptstbnode
= stb_getstbnode(ptttvsig
->NODE
);
154 if ((pt
=getptype(ptttvsig
->USER
, STB_IS_CLOCK
))!=NULL
)
155 spctc
=(stb_propagated_clock_to_clock
*)pt
->DATA
;
159 if (spctc
!=NULL
) ptstbck
=&spctc
->original_waveform
;
160 else ptstbck
= ptstbnode
->CK
;
162 if (getptype(ptttvsig
->USER
, STB_INVERTED_CLOCK
)) invert
=1;
164 if (getptype(ptttvsig
->USER
, STB_IDEAL_CLOCK
)) ideal
=1;
166 if (getptype(ptttvsig
->USER
, STB_VIRTUAL_CLOCK
)) virt
=1;
169 fprintf(stbout
, " %s%s%s \"%s\":\n", virt
?"VIRTUAL ":"",ideal
?"IDEAL ":"", invert
?"! ":"", namebuf
);
170 fprintf(stbout
, " %s (%s:%s);\n", !invert
?"UP":"DOWN", stb_drvtime(ptstbck
->SUPMIN
), stb_drvtime(ptstbck
->SUPMAX
));
171 fprintf(stbout
, " %s (%s:%s);\n", !invert
?"DOWN":"UP", stb_drvtime(ptstbck
->SDNMIN
), stb_drvtime(ptstbck
->SDNMAX
));
172 fprintf(stbout
, " PERIOD %s;\n", stb_drvtime(ptstbck
->PERIOD
));
174 if (spctc
!=NULL
&& spctc
->master
!=NULL
)
176 fprintf(stbout
, " CLOCK \"%s\" %s %s;\n", spctc
->master
, (spctc
->edges
& 2)!=0?"UP":"DOWN", (spctc
->edges
& 1)!=0?"UP":"DOWN");
180 fprintf(stbout
, "END;\n");
181 fprintf(stbout
, "\n");
184 fprintf(stbout
, "ClockLatencies\nBegin\n");
185 for (ptchain
= ptstbfig
->CLOCK
; ptchain
; ptchain
= ptchain
->NEXT
) {
187 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
188 if ((pt
=getptype(ptttvsig
->USER
, STB_IS_CLOCK
))!=NULL
)
190 spctc
=(stb_propagated_clock_to_clock
*)pt
->DATA
;
191 if (getptype(ptttvsig
->USER
, STB_INVERTED_CLOCK
))
193 a
=spctc
->latencies
.SDNMIN
; b
=spctc
->latencies
.SDNMAX
; c
=spctc
->latencies
.SUPMIN
; d
=spctc
->latencies
.SUPMAX
;
197 a
=spctc
->latencies
.SUPMIN
; b
=spctc
->latencies
.SUPMAX
; c
=spctc
->latencies
.SDNMIN
; d
=spctc
->latencies
.SDNMAX
;
199 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
200 fprintf(stbout
, " \"%s\" : %s %s", namebuf
, stb_drvtime(a
), stb_drvtime(b
));
201 fprintf(stbout
, " %s %s;\n", stb_drvtime(c
), stb_drvtime(d
));
204 fprintf(stbout
, "End;\n\n");
208 /* equivalent clock group */
209 if ((pt
=getptype(ptstbfig
->USER
, STB_EQUIVALENT
))!=NULL
)
213 fprintf(stbout
, "Equivalent Clock Groups\n");
214 fprintf(stbout
, "Begin\n");
215 for (ptchain
=(chain_list
*)pt
->DATA
, num
=1; ptchain
!=NULL
; ptchain
=ptchain
->NEXT
, num
++)
217 fprintf(stbout
, " Group%d:", num
);
218 for (cl
=ptchain
->DATA
; cl
!=NULL
; cl
=cl
->NEXT
)
220 ptttvsig
=(ttvsig_list
*)cl
->DATA
;
221 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
222 fprintf(stbout
, " \"%s\"%s", namebuf
, cl
->NEXT
!=NULL
?",":";");
224 fprintf(stbout
, "\n");
226 fprintf(stbout
, "End;\n\n");
229 /* asynchronous clock group */
230 if ((pt
=getptype(ptstbfig
->USER
, STB_DOMAIN
))!=NULL
)
234 fprintf(stbout
, "Asynchronous Clock Groups\n");
235 fprintf(stbout
, "Begin\n");
236 for (ptchain
=(chain_list
*)pt
->DATA
, num
=1; ptchain
!=NULL
; ptchain
=ptchain
->NEXT
, num
++)
238 fprintf(stbout
, " Group%d:", num
);
239 for (cl
=ptchain
->DATA
; cl
!=NULL
; cl
=cl
->NEXT
)
241 ptttvsig
=(ttvsig_list
*)cl
->DATA
;
242 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
243 fprintf(stbout
, " \"%s\"%s", namebuf
, cl
->NEXT
!=NULL
?",":";");
245 fprintf(stbout
, "\n");
247 fprintf(stbout
, "End;\n\n");
250 if ((ifl
=getloadedinffig(ptstbfig
->FIG
->INFO
->FIGNAME
))!=NULL
)
252 infDriveStbSpecSection (stbout
, ifl
, INF_SPECIN
, "Specify Input Connectors");
253 infDriveStbSpecSection (stbout
, ifl
, INF_SPECOUT
, "Verify Output Connectors");
256 /* Conditioned Command States */
258 if (ptstbfig
->COMMAND
!= NULL
) {
260 for (ptchain
= ptstbfig
->COMMAND
; ptchain
; ptchain
= ptchain
->NEXT
) {
261 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
262 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
263 ptstbnode
= stb_getstbnode(ptttvsig
->NODE
);
264 ptstbck
= ptstbnode
->CK
;
265 state
= ptstbck
->VERIF
& (STB_UP
|STB_DN
);
267 if (conditioned
== FALSE
) {
269 fprintf(stbout
, "CONDITIONED COMMAND STATES\n");
270 fprintf(stbout
, "BEGIN\n");
272 if (state
== STB_UP
) fprintf(stbout
, " \"%s\": UP;\n", namebuf
);
273 else fprintf(stbout
, " \"%s\": DOWN;\n", namebuf
);
277 if (conditioned
== TRUE
) {
278 fprintf(stbout
, "END;\n");
279 fprintf(stbout
, "\n");
283 /* Stability of Input Connectors */
285 fprintf(stbout
, "INPUT CONNECTORS STABILITY\n");
286 fprintf(stbout
, "BEGIN\n");
288 for (ptchain
= ptstbfig
->CONNECTOR
; ptchain
; ptchain
= ptchain
->NEXT
) {
289 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
290 if ((ptttvsig
->TYPE
& TTV_SIG_CI
) != TTV_SIG_CI
|| (ptttvsig
->TYPE
& TTV_SIG_CB
) == TTV_SIG_CB
) continue;
291 if (stb_getstbnode(ptttvsig
->NODE
)->CK
!= NULL
) {
292 if (stb_getstbnode(ptttvsig
->NODE
)->CK
->TYPE
== STB_TYPE_CLOCK
)
295 stb_writesig(stbout
, ptstbfig
, ptttvsig
, format
);
298 fprintf(stbout
, "END;\n");
299 fprintf(stbout
, "\n");
301 /* Stability of Output Connectors */
303 fprintf(stbout
, "OUTPUT CONNECTORS STABILITY\n");
304 fprintf(stbout
, "BEGIN\n");
306 for (ptchain
= ptstbfig
->CONNECTOR
; ptchain
; ptchain
= ptchain
->NEXT
) {
307 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
308 if ((ptttvsig
->TYPE
& TTV_SIG_CO
) != TTV_SIG_CO
) continue;
309 stb_writesig(stbout
, ptstbfig
, ptttvsig
, format
);
312 fprintf(stbout
, "END;\n");
313 fprintf(stbout
, "\n");
315 /* Stability of Memory nodes */
317 if (mode
== STB_DRIVE_INTERNALS
) {
319 for (ptchain
= ptstbfig
->NODE
; ptchain
; ptchain
= ptchain
->NEXT
) {
320 ptevent
= (ttvevent_list
*)ptchain
->DATA
;
321 ptttvsig
= ptevent
->ROOT
;
322 if ((ptttvsig
->TYPE
& TTV_SIG_MARQUE
) == TTV_SIG_MARQUE
) continue;
323 if ((ptttvsig
->TYPE
& TTV_SIG_L
) != TTV_SIG_L
) continue;
324 if (memories
== FALSE
) {
326 fprintf(stbout
, "MEMORY NODES STABILITY\n");
327 fprintf(stbout
, "BEGIN\n");
329 ptttvsig
->TYPE
|= TTV_SIG_MARQUE
;
330 stb_writesig(stbout
, ptstbfig
, ptttvsig
, format
);
333 for (ptchain
= ptstbfig
->NODE
; ptchain
; ptchain
= ptchain
->NEXT
) {
334 ptevent
= (ttvevent_list
*)ptchain
->DATA
;
335 ptttvsig
= ptevent
->ROOT
;
336 ptttvsig
->TYPE
&= ~(TTV_SIG_MARQUE
);
339 if (memories
== TRUE
) {
340 fprintf(stbout
, "END;\n");
341 fprintf(stbout
, "\n");
345 /* Stability of Internal nodes */
347 if (mode
== STB_DRIVE_INTERNALS
) {
349 for (ptchain
= ptstbfig
->NODE
; ptchain
; ptchain
= ptchain
->NEXT
) {
350 ptevent
= (ttvevent_list
*)ptchain
->DATA
;
351 ptttvsig
= ptevent
->ROOT
;
352 if ((ptttvsig
->TYPE
& TTV_SIG_MARQUE
) == TTV_SIG_MARQUE
) continue;
353 if ((ptttvsig
->TYPE
& TTV_SIG_C
) == TTV_SIG_C
) continue;
354 if ((ptttvsig
->TYPE
& TTV_SIG_L
) == TTV_SIG_L
) continue;
355 if (internals
== FALSE
) {
357 fprintf(stbout
, "INTERNAL NODES STABILITY\n");
358 fprintf(stbout
, "BEGIN\n");
360 ptttvsig
->TYPE
|= TTV_SIG_MARQUE
;
361 stb_writesig(stbout
, ptstbfig
, ptttvsig
, format
);
364 for (ptchain
= ptstbfig
->NODE
; ptchain
; ptchain
= ptchain
->NEXT
) {
365 ptevent
= (ttvevent_list
*)ptchain
->DATA
;
366 ptttvsig
= ptevent
->ROOT
;
367 ptttvsig
->TYPE
&= ~(TTV_SIG_MARQUE
);
370 if (internals
== TRUE
) {
371 fprintf(stbout
, "END;\n");
372 fprintf(stbout
, "\n");
376 fprintf(stbout
, "SetupHold\n");
377 fprintf(stbout
, "Begin\n");
379 fprintf(stbout
, "# <signal name> : ( <fallsetup> <fallhold> ) ( <risesetup> <risehold> ) ;\n");
380 for (ptchain
= ptstbfig
->NODE
; ptchain
; ptchain
= ptchain
->NEXT
) {
381 ptevent
= (ttvevent_list
*)ptchain
->DATA
;
382 ptttvsig
= ptevent
->ROOT
;
383 if ((ptttvsig
->TYPE
& TTV_SIG_MARQUE
) == TTV_SIG_MARQUE
) continue;
384 ptttvsig
->TYPE
|= TTV_SIG_MARQUE
;
385 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
386 stb_writesetuphold(stbout
, ptttvsig
, namebuf
);
388 fprintf(stbout
, "End;\n");
389 fprintf(stbout
, "\n");
392 fprintf(stbout
, "StabFlags\n");
393 fprintf(stbout
, "Begin\n");
394 for (ptchain
= ptstbfig
->NODE
; ptchain
; ptchain
= ptchain
->NEXT
) {
395 ptevent
= (ttvevent_list
*)ptchain
->DATA
;
396 ptttvsig
= ptevent
->ROOT
;
397 if ((ptttvsig
->TYPE
& TTV_SIG_MARQUE
) != TTV_SIG_MARQUE
) continue;
398 ptttvsig
->TYPE
&= ~TTV_SIG_MARQUE
;
399 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
400 stb_writeflags(stbout
, ptttvsig
, namebuf
);
402 fprintf(stbout
, "End;\n");
403 fprintf(stbout
, "\n");
405 for (ptchain
= ptstbfig
->NODE
; ptchain
; ptchain
= ptchain
->NEXT
) {
406 ptevent
= (ttvevent_list
*)ptchain
->DATA
;
407 ptttvsig
= ptevent
->ROOT
;
408 ptttvsig
->TYPE
&= ~TTV_SIG_MARQUE
;
411 /* fprintf (stbout, "Directives\nBegin\n");
412 for (ptchain = ptstbfig->NODE; ptchain; ptchain = ptchain->NEXT)
414 ptevent = (ttvevent_list *)ptchain->DATA;
415 ptttvsig = ptevent->ROOT;
416 if ((ptttvsig->TYPE & TTV_SIG_MARQUE) == TTV_SIG_MARQUE) continue;
417 ptttvsig->TYPE |= TTV_SIG_MARQUE;
418 ttv_getsigname(ptstbfig->FIG, namebuf, ptttvsig);
419 if ((sd=stb_get_directive(ptttvsig))!=NULL)
423 if (sd->filter) fprintf (stbout, " FILTER: "); else fprintf (stbout, " CHECK: ");
425 if (sd->target1_dir & INF_DIRECTIVE_CLOCK) fprintf (stbout, "CLOCK ");
426 fprintf (stbout, "\"%s\" ", namebuf);
428 if (sd->target1_dir & INF_DIRECTIVE_UP) fprintf(stbout, "Up ");
429 else if (sd->target1_dir & INF_DIRECTIVE_DOWN) fprintf(stbout, "Down ");
430 else if (sd->target1_dir & INF_DIRECTIVE_RISING) fprintf(stbout, "Rising ");
431 else if (sd->target1_dir & INF_DIRECTIVE_FALLING) fprintf(stbout, "Falling ");
433 if (sd->operation & INF_DIRECTIVE_BEFORE) fprintf(stbout, "Before ");
434 else if (sd->operation & INF_DIRECTIVE_AFTER) fprintf(stbout, "After ");
435 else fprintf(stbout, "With ");
437 if (sd->target2!=NULL)
440 ttv_getsigname(ptstbfig->FIG, namebuf2, sd->target2);
441 if (sd->target2_dir & INF_DIRECTIVE_CLOCK) fprintf(stbout, "Clock ");
442 fprintf(stbout, "\"%s\" ", namebuf2);
443 if (sd->target2_dir & INF_DIRECTIVE_UP) fprintf(stbout, "Up ");
444 else if (sd->target2_dir & INF_DIRECTIVE_DOWN) fprintf(stbout, "Down ");
445 else if (sd->target2_dir & INF_DIRECTIVE_RISING) fprintf(stbout, "Rising ");
446 else if (sd->target2_dir & INF_DIRECTIVE_FALLING) fprintf(stbout, "Falling ");
448 if (sd->margin!=0) fprintf(stbout, "Margin %.1f", sd->margin/TTV_UNIT);
450 fprintf(stbout,";\n");
456 for (ptchain = ptstbfig->NODE; ptchain; ptchain = ptchain->NEXT)
458 ptevent = (ttvevent_list *)ptchain->DATA;
459 ptttvsig = ptevent->ROOT;
460 ptttvsig->TYPE &= ~TTV_SIG_MARQUE;
462 fprintf(stbout, "End;\n");
463 fprintf(stbout, "\n");
466 if (fclose(stbout
)) {
467 stb_error(ERR_CANNOT_CLOSE
, NULL
, 0, STB_FATAL
);
473 /*****************************************************************************
474 * fonction stb_writesig() *
475 *****************************************************************************/
477 stb_writesig(ptfile
, ptstbfig
, ptttvsig
, format
)
479 stbfig_list
*ptstbfig
;
480 ttvsig_list
*ptttvsig
;
483 stbnode
*ptstbnode_up
;
484 stbnode
*ptstbnode_dn
;
490 ptstbnode_dn
= stb_getstbnode(ptttvsig
->NODE
);
491 ptstbnode_up
= stb_getstbnode(ptttvsig
->NODE
+1);
492 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
493 for (i
= 0; i
< ptstbfig
->PHASENUMBER
; i
++) {
494 /* add source phase */
495 strcpy(phasebuf
, " FROM \"");
496 if (stb_getclock(ptstbfig
, i
, phasebuf
+7, &active_edge
, NULL
) == NULL
) {
497 if (i
== 0) {/* combinatorial */
502 stb_error(ERR_UNKNOWN_CLOCK
, namebuf
, i
, STB_NONFATAL
/*STB_FATAL*/);
507 strcat(phasebuf
, "\"");
508 if (active_edge
== STB_SLOPE_DN
) {
509 strcat(phasebuf
, " FALLING");
511 else strcat(phasebuf
, " RISING");
514 /* write intervals for hz precharge/evaluate */
515 if (ptstbnode_dn
!= NULL
) {
516 if (ptstbnode_dn
->STBHZ
!= NULL
) {
517 if (ptstbnode_dn
->STBHZ
[i
] != NULL
) {
518 if (ptstbnode_dn
->CK
->TYPE
== STB_TYPE_PRECHARGE
) {
519 fprintf(ptfile
, " \"%s\" FALLING%s WITHOUT PRECHARGE:\n", namebuf
, phasebuf
);
520 stb_writeintervals(ptfile
, ptstbnode_dn
->STBHZ
[i
], format
);
521 stb_writeintervals_split(ptfile
, ptstbfig
, ptstbnode_dn
, 1, i
);
523 else if (ptstbnode_dn
->CK
->TYPE
== STB_TYPE_EVAL
) {
524 fprintf(ptfile
, " \"%s\" FALLING%s WITHOUT EVALUATE:\n", namebuf
, phasebuf
);
525 stb_writeintervals(ptfile
, ptstbnode_dn
->STBHZ
[i
], format
);
526 stb_writeintervals_split(ptfile
, ptstbfig
, ptstbnode_dn
, 1, i
);
531 if (ptstbnode_up
!= NULL
) {
532 if (ptstbnode_up
->STBHZ
!= NULL
) {
533 if (ptstbnode_up
->STBHZ
[i
] != NULL
) {
534 if (ptstbnode_up
->CK
->TYPE
== STB_TYPE_PRECHARGE
) {
535 fprintf(ptfile
, " \"%s\" RISING%s WITHOUT PRECHARGE:\n", namebuf
, phasebuf
);
536 stb_writeintervals(ptfile
, ptstbnode_up
->STBHZ
[i
], format
);
537 stb_writeintervals_split(ptfile
, ptstbfig
, ptstbnode_up
, 1, i
);
539 else if (ptstbnode_up
->CK
->TYPE
== STB_TYPE_EVAL
) {
540 fprintf(ptfile
, " \"%s\" RISING%s WITHOUT EVALUATE:\n", namebuf
, phasebuf
);
541 stb_writeintervals(ptfile
, ptstbnode_up
->STBHZ
[i
], format
);
542 stb_writeintervals_split(ptfile
, ptstbfig
, ptstbnode_up
, 1, i
);
548 /* write intervals for the current phase */
549 if (ptstbnode_up
!= NULL
&& ptstbnode_dn
!= NULL
) {
550 if (stb_compstbpairlist(ptstbnode_dn
->STBTAB
[i
], ptstbnode_up
->STBTAB
[i
]) == TRUE
) {
551 if (ptstbnode_dn
->STBTAB
[i
] != NULL
) {
552 fprintf(ptfile
, " \"%s\"%s:\n", namebuf
, phasebuf
);
553 stb_writeintervals(ptfile
, ptstbnode_dn
->STBTAB
[i
], format
);
554 stb_writeintervals_split(ptfile
, ptstbfig
, ptstbnode_dn
, 0, i
);
558 if (ptstbnode_dn
->STBTAB
[i
] != NULL
) {
559 fprintf(ptfile
, " \"%s\" FALLING%s:\n", namebuf
, phasebuf
);
560 stb_writeintervals(ptfile
, ptstbnode_dn
->STBTAB
[i
], format
);
561 stb_writeintervals_split(ptfile
, ptstbfig
, ptstbnode_dn
, 0, i
);
563 if (ptstbnode_up
->STBTAB
[i
] != NULL
) {
564 fprintf(ptfile
, " \"%s\" RISING%s:\n", namebuf
, phasebuf
);
565 stb_writeintervals(ptfile
, ptstbnode_up
->STBTAB
[i
], format
);
566 stb_writeintervals_split(ptfile
, ptstbfig
, ptstbnode_up
, 0, i
);
570 else if (ptstbnode_up
!= NULL
) {
571 if (ptstbnode_up
->STBTAB
[i
] != NULL
) {
572 fprintf(ptfile
, " \"%s\" RISING%s:\n", namebuf
, phasebuf
);
573 stb_writeintervals(ptfile
, ptstbnode_up
->STBTAB
[i
], format
);
574 stb_writeintervals_split(ptfile
, ptstbfig
, ptstbnode_up
, 0, i
);
577 else if (ptstbnode_dn
!= NULL
) {
578 if (ptstbnode_dn
->STBTAB
[i
] != NULL
) {
579 fprintf(ptfile
, " \"%s\" FALLING%s:\n", namebuf
, phasebuf
);
580 stb_writeintervals(ptfile
, ptstbnode_dn
->STBTAB
[i
], format
);
581 stb_writeintervals_split(ptfile
, ptstbfig
, ptstbnode_dn
, 0, i
);
587 /*****************************************************************************
588 * fonction stb_writeintervals() *
589 *****************************************************************************/
592 stb_writeintervals_split(FILE *ptfile
, stbfig_list
*sb
, stbnode
*node
, int hz
, char phase
)
594 stbpair_list
*ptstbpair
, *pair
;
595 stbpair_list
*STBTAB
[256];
596 stbpair_list
*STBHZ
[256];
601 if (node
->CK
==NULL
|| node
->CK
->NEXT
==NULL
) return;
603 for (ck
=node
->CK
; ck
!=NULL
; ck
=ck
->NEXT
)
605 if (ck
->CKINDEX
==phase
)
607 for (i
=0; i
<node
->NBINDEX
; i
++)
609 STBHZ
[i
]=NULL
, STBTAB
[i
]=NULL
;
611 stb_transferstbline (sb
, node
->EVENT
, node
, STBTAB
, STBHZ
, 0, 1, NULL
, ck
, 1, (node
->FLAG
& STB_NODE_STABCORRECT
)!=0?STB_TRANSFERT_CORRECTION
:0) ;
612 pair
= stb_globalstbtab (!hz
?STBTAB
:STBHZ
, node
->NBINDEX
);
613 stb_freestbtabpair(STBHZ
, node
->NBINDEX
);
614 stb_freestbtabpair(STBTAB
, node
->NBINDEX
);
618 if (ck
->CMD
==NULL
) fprintf(ptfile
, "#no cmd:");
619 else fprintf(ptfile
, "#cmd %s (%c):", ttv_getsigname(sb
->FIG
,buf
,ck
->CMD
->ROOT
), (ck
->CMD
->TYPE
& TTV_NODE_UP
)?'R':'F');
620 for (ptstbpair
= pair
; ptstbpair
; ptstbpair
= ptstbpair
->NEXT
)
621 fprintf(ptfile
, " %s-%s", stb_drvtime(ptstbpair
->D
), stb_drvtime(ptstbpair
->U
));
622 fprintf(ptfile
, "\n");
624 stb_freestbpair(pair
);
629 stb_writeintervals(ptfile
, ptheadstbpair
, format
)
631 stbpair_list
*ptheadstbpair
;
634 stbpair_list
*ptstbpair
;
636 if (format
== STB_SEPARATE_INTERVALS
) {
637 for (ptstbpair
= ptheadstbpair
; ptstbpair
; ptstbpair
= ptstbpair
->NEXT
) {
638 fprintf(ptfile
, " UNSTABLE %s;\n", stb_drvtime(ptstbpair
->D
));
639 fprintf(ptfile
, " STABLE %s;\n", stb_drvtime(ptstbpair
->U
));
643 fprintf(ptfile
, " UNSTABLE");
644 for (ptstbpair
= ptheadstbpair
; ptstbpair
; ptstbpair
= ptstbpair
->NEXT
) {
645 fprintf(ptfile
, " %s%s", stb_drvtime(ptstbpair
->D
), ptstbpair
->NEXT
?" ":"");
647 fprintf(ptfile
, ";\n");
648 fprintf(ptfile
, " STABLE ");
649 for (ptstbpair
= ptheadstbpair
; ptstbpair
; ptstbpair
= ptstbpair
->NEXT
) {
650 fprintf(ptfile
, " %s%s", stb_drvtime(ptstbpair
->U
), ptstbpair
->NEXT
?" ":"");
652 fprintf(ptfile
, ";\n");
656 /*****************************************************************************
657 * fonction stb_drvsigerr() *
658 *****************************************************************************/
659 void stb_drvsigerr(file
,ptstbfig
,ptsig
)
661 stbfig_list
*ptstbfig
;
664 stbdebug_list
*debug
;
666 char namebuf
[1024], buf
[1024];
668 debug
= stb_debugstberror(ptstbfig
,ptsig
,(long)0, 0);
670 for(deb
= debug
; deb
; deb
= deb
->NEXT
) {
671 if (deb
->START_CMD_EVENT
!=NULL
)
672 sprintf(buf
, " CMD '%s' (%c)", ttv_getsigname(ptstbfig
->FIG
,namebuf
,deb
->START_CMD_EVENT
->ROOT
), (deb
->START_CMD_EVENT
->TYPE
& TTV_NODE_UP
)?'R':'F');
675 fprintf(file
, "\tERROR FROM '%s'%s:",ttv_getsigname(ptstbfig
->FIG
,namebuf
,deb
->SIG1
), buf
);
676 if (deb
->SETUP
!= STB_NO_TIME
) {
677 fprintf(file
, " SETUP=%s", stb_drvtime(deb
->SETUP
));
679 if (deb
->HOLD
!= STB_NO_TIME
) {
680 fprintf(file
, " HOLD=%s", stb_drvtime(deb
->HOLD
));
684 stb_freestbdebuglist(debug
) ;
687 /*****************************************************************************
688 * fonction stb_drvreport() *
689 *****************************************************************************/
690 int stb_getdatalag(ttvfig_list
*ttvfig
, ttvevent_list
*latch
, double *time
)
692 stbfig_list
*stbfig
;
694 long datamax
=0, dmax
;
700 if((((latch
->ROOT
->TYPE
& TTV_SIG_LL
) != TTV_SIG_LL
) &&
701 ((latch
->ROOT
->TYPE
& TTV_SIG_R
) != TTV_SIG_R
)))
704 if (ttv_testsigflag(latch
->ROOT
, TTV_SIG_FLAGS_DONTCROSS
))
707 if((stbfig
= stb_getstbfig(ttvfig
)) == NULL
)
710 stb_geteventphase(stbfig
,latch
,&phase
,NULL
,NULL
,1,1) ;
712 if(phase
== STB_NO_INDEX
)
718 node
= stb_getstbnode (latch
);
721 for (ck
=node
->CK
; ck
!=NULL
; ck
=ck
->NEXT
)
723 if (stb_IsClockCK(node
->EVENT
, ck
)) continue;
724 stb_getstbdelta(stbfig
, latch
, &datamin
, &dmax
, ck
->CMD
);
725 if (dmax
>datamax
) datamax
=dmax
;
728 *time
=(datamax
/TTV_UNIT
)*1e-12;
738 void stb_drvreport(stbfig
,file
,type
,slope
,name
,setup
,hold
,ck
,lag
,node
)
739 stbfig_list
*stbfig
;
755 char nameclock
[1024];
761 if ((setup
!= STB_NO_TIME
) || (hold
!= STB_NO_TIME
)) {
762 fprintf(file
, "%s '%s' %s:", type
, name
, slope
);
763 if (setup
!= STB_NO_TIME
) {
764 fprintf(file
, " SETUP=%s", stb_drvtime(setup
));
766 if (hold
!= STB_NO_TIME
) {
767 fprintf(file
, " HOLD=%s", stb_drvtime(hold
));
772 fprintf(file
, " TRANSPARENT=ALWAYS");
774 fprintf(file
, " TRANSPARENT=%s", stb_drvtime(mbk_long_round(lag
*TTV_UNIT
*1e12
)));
776 fprintf(file
, " NOT-TRANSPARENT");
780 for(; ck
; ck
= ck
->NEXT
) {
781 if (stb_IsClockCK(node
, ck
)) continue;
782 if (ck
->CMD
!=NULL
&& stbfig
!=NULL
&& !stb_cmd_can_generate_event(stbfig
, node
, ck
->CMD
)) continue;
783 if(ck
->CKINDEX
!= STB_NO_INDEX
) {
784 if(stb_getclock(stbfig
,ck
->CKINDEX
,nameclock
,&edge
, ck
) == NULL
)
787 else *nameclock
='\0' ;
788 if(ck
->CMD
!= NULL
) {
789 ttv_getsigname(stbfig
->FIG
,namecmd
,ck
->CMD
->ROOT
) ;
792 if (ck
->SUPMIN
== STB_NO_TIME
) strcpy(upmin
, "NO_TIME");
793 else sprintf(upmin
, "%s", stb_drvtime(ck
->SUPMIN
));
794 if (ck
->SUPMAX
== STB_NO_TIME
) strcpy(upmax
, "NO_TIME");
795 else sprintf(upmax
, "%s", stb_drvtime(ck
->SUPMAX
));
796 if (ck
->SDNMIN
== STB_NO_TIME
) strcpy(dnmin
, "NO_TIME");
797 else sprintf(dnmin
, "%s", stb_drvtime(ck
->SDNMIN
));
798 if (ck
->SDNMAX
== STB_NO_TIME
) strcpy(dnmax
, "NO_TIME");
799 else sprintf(dnmax
, "%s", stb_drvtime(ck
->SDNMAX
));
800 fprintf(file
, "\tCLOCK: ");
801 if(*nameclock
!= '\0')
803 if (STB_OPEN_LATCH_PHASE
== 'N')
804 fprintf(file
, "%s(%s) ",nameclock
,(edge
== STB_SLOPE_DN
)?"DOWN":"UP");
806 fprintf(file
, "%s(%s) ",nameclock
,(edge
!= STB_SLOPE_DN
)?"DOWN":"UP");
811 stb_getgoodclock_and_status(stbfig
, ck
, ck
->CMD
, node
, &invert
);
817 fprintf(file
, "COMMAND : %s(%s) ",namecmd
, (ck
->CMD
->TYPE
& TTV_NODE_UP
)==TTV_NODE_UP
?"DOWN":"UP");
819 fprintf(file
, "%sMIN=%s, %sMAX=%s, %sMIN=%s, %sMAX=%s\n",up
, upmin
,up
, upmax
,down
,dnmin
,down
,dnmax
);
824 /*****************************************************************************
825 * fonction stb_report() *
826 *****************************************************************************/
829 stb_report(stbfig_list
*ptstbfig
, char *filename
)
832 ttvsig_list
*ptttvsig
;
833 stbnode
*ptstbnode_up
;
834 stbnode
*ptstbnode_dn
;
839 stbrep
= mbkfopen(filename
==NULL
?ptstbfig
->FIG
->INFO
->FIGNAME
:filename
, filename
==NULL
?"str":NULL
, WRITE_TEXT
);
841 stb_error(ERR_CANNOT_OPEN
, NULL
, 0, STB_FATAL
);
844 sprintf(namebuf
,"Stability report : %s.str\n",filename
==NULL
?ptstbfig
->FIG
->INFO
->FIGNAME
:filename
);
845 avt_printExecInfo(stbrep
, "#", namebuf
, "");
847 fprintf(stbrep
, "NUMBER OF PHASES: %d\n", (int)ptstbfig
->PHASENUMBER
);
848 for (ptchain
= ptstbfig
->CLOCK
; ptchain
; ptchain
= ptchain
->NEXT
) {
849 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
850 ptstbnode_up
= stb_getstbnode(ptttvsig
->NODE
);
851 ptstbnode_dn
= stb_getstbnode(ptttvsig
->NODE
+1);
852 fprintf(stbrep
, "CLOCK %s :", ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
));
853 if (ptstbnode_up
->CK
->CKINDEX
!= STB_NO_INDEX
)
854 fprintf(stbrep
, " FALLING(%d)", ptstbnode_up
->CK
->CKINDEX
) ;
855 if (ptstbnode_dn
->CK
->CKINDEX
!= STB_NO_INDEX
)
856 fprintf(stbrep
, " RISING(%d)", ptstbnode_dn
->CK
->CKINDEX
) ;
857 fprintf(stbrep
, "\n") ;
860 fprintf(stbrep
, "STABLE: ");
861 if (ptstbfig
->STABILITYFLAG
== STB_STABLE
) {
862 fprintf(stbrep
, "YES\n\n");
864 else fprintf(stbrep
, "NO\n\n");
867 for (ptchain
= ptstbfig
->CONNECTOR
; ptchain
; ptchain
= ptchain
->NEXT
) {
868 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
869 if ((ptttvsig
->TYPE
& TTV_SIG_CO
) != TTV_SIG_CO
) continue;
870 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
871 ptstbnode_dn
= stb_getstbnode(ptttvsig
->NODE
);
872 stb_drvreport(ptstbfig
,stbrep
, "OUTPUT", "FALLING", namebuf
, ptstbnode_dn
->SETUP
, ptstbnode_dn
->HOLD
, NULL
, lag
, ptttvsig
->NODE
);
873 ptstbnode_up
= stb_getstbnode(ptttvsig
->NODE
+1);
874 stb_drvreport(ptstbfig
,stbrep
, "OUTPUT", "RISING", namebuf
, ptstbnode_up
->SETUP
, ptstbnode_up
->HOLD
, NULL
, lag
, ptttvsig
->NODE
+1);
875 if((ptstbnode_up
->SETUP
<= (long)0) || (ptstbnode_up
->HOLD
<= (long)0)||
876 (ptstbnode_dn
->SETUP
<= (long)0) || (ptstbnode_dn
->HOLD
<= (long)0))
877 stb_drvsigerr(stbrep
,ptstbfig
,ptttvsig
) ;
881 for (ptchain
= ptstbfig
->MEMORY
; ptchain
; ptchain
= ptchain
->NEXT
) {
882 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
883 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
884 ptstbnode_dn
= stb_getstbnode(ptttvsig
->NODE
);
885 stb_getdatalag(ptstbfig
->FIG
, ptttvsig
->NODE
, &lag
);
886 stb_drvreport(ptstbfig
,stbrep
, "MEMORY", "FALLING", namebuf
, ptstbnode_dn
->SETUP
, ptstbnode_dn
->HOLD
, ptstbnode_dn
->CK
, lag
, ptttvsig
->NODE
);
887 ptstbnode_up
= stb_getstbnode(ptttvsig
->NODE
+1);
888 stb_getdatalag(ptstbfig
->FIG
, ptttvsig
->NODE
+1, &lag
);
889 stb_drvreport(ptstbfig
,stbrep
, "MEMORY", "RISING", namebuf
, ptstbnode_up
->SETUP
, ptstbnode_up
->HOLD
, ptstbnode_up
->CK
, lag
, ptttvsig
->NODE
+1);
890 if((ptstbnode_up
->SETUP
<= (long)0) || (ptstbnode_up
->HOLD
<= (long)0)||
891 (ptstbnode_dn
->SETUP
<= (long)0) || (ptstbnode_dn
->HOLD
<= (long)0))
892 stb_drvsigerr(stbrep
,ptstbfig
,ptttvsig
) ;
896 for (ptchain
= ptstbfig
->COMMAND
; ptchain
; ptchain
= ptchain
->NEXT
) {
897 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
898 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
899 ptstbnode_dn
= stb_getstbnode(ptttvsig
->NODE
);
900 stb_drvreport(ptstbfig
,stbrep
, "COMMAND", "FALLING", namebuf
, ptstbnode_dn
->SETUP
, ptstbnode_dn
->HOLD
, ptstbnode_dn
->CK
, lag
, ptttvsig
->NODE
);
901 ptstbnode_up
= stb_getstbnode(ptttvsig
->NODE
+1);
902 stb_drvreport(ptstbfig
,stbrep
, "COMMAND", "RISING", namebuf
, ptstbnode_up
->SETUP
, ptstbnode_up
->HOLD
, ptstbnode_up
->CK
, lag
, ptttvsig
->NODE
+1);
903 if((ptstbnode_up
->SETUP
<= (long)0) || (ptstbnode_up
->HOLD
<= (long)0)||
904 (ptstbnode_dn
->SETUP
<= (long)0) || (ptstbnode_dn
->HOLD
<= (long)0))
905 stb_drvsigerr(stbrep
,ptstbfig
,ptttvsig
) ;
909 for (ptchain
= ptstbfig
->PRECHARGE
; ptchain
; ptchain
= ptchain
->NEXT
) {
910 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
911 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
912 ptstbnode_dn
= stb_getstbnode(ptttvsig
->NODE
);
913 stb_getdatalag(ptstbfig
->FIG
, ptttvsig
->NODE
, &lag
);
914 stb_drvreport(ptstbfig
,stbrep
, "PRECHARGE", "FALLING", namebuf
, ptstbnode_dn
->SETUP
, ptstbnode_dn
->HOLD
, ptstbnode_dn
->CK
, lag
, ptttvsig
->NODE
);
915 ptstbnode_up
= stb_getstbnode(ptttvsig
->NODE
+1);
916 stb_getdatalag(ptstbfig
->FIG
, ptttvsig
->NODE
+1, &lag
);
917 stb_drvreport(ptstbfig
,stbrep
, "PRECHARGE", "RISING", namebuf
, ptstbnode_up
->SETUP
, ptstbnode_up
->HOLD
, ptstbnode_up
->CK
, lag
, ptttvsig
->NODE
+1);
918 if((ptstbnode_up
->SETUP
<= (long)0) || (ptstbnode_up
->HOLD
<= (long)0)||
919 (ptstbnode_dn
->SETUP
<= (long)0) || (ptstbnode_dn
->HOLD
<= (long)0))
920 stb_drvsigerr(stbrep
,ptstbfig
,ptttvsig
) ;
924 for (ptchain
= ptstbfig
->BREAK
; ptchain
; ptchain
= ptchain
->NEXT
) {
925 ptttvsig
= (ttvsig_list
*)ptchain
->DATA
;
926 ttv_getsigname(ptstbfig
->FIG
, namebuf
, ptttvsig
);
927 ptstbnode_dn
= stb_getstbnode(ptttvsig
->NODE
);
928 stb_drvreport(ptstbfig
,stbrep
, "BREAK", "FALLING", namebuf
, ptstbnode_dn
->SETUP
, ptstbnode_dn
->HOLD
, ptstbnode_dn
->CK
, lag
, ptttvsig
->NODE
);
929 ptstbnode_up
= stb_getstbnode(ptttvsig
->NODE
+1);
930 stb_drvreport(ptstbfig
,stbrep
, "BREAK", "RISING", namebuf
, ptstbnode_up
->SETUP
, ptstbnode_up
->HOLD
, ptstbnode_up
->CK
, lag
, ptttvsig
->NODE
+1);
931 if((ptstbnode_up
->SETUP
<= (long)0) || (ptstbnode_up
->HOLD
<= (long)0)||
932 (ptstbnode_dn
->SETUP
<= (long)0) || (ptstbnode_dn
->HOLD
<= (long)0))
933 stb_drvsigerr(stbrep
,ptstbfig
,ptttvsig
) ;
936 if (fclose(stbrep
)) {
937 stb_error(ERR_CANNOT_CLOSE
, NULL
, 0, STB_FATAL
);
941 char* stb_drvtime( long time
)
944 static char buffer
[4][64];
949 sprintf( buffer
[n
], "%.1f", (double)time
/ TTV_UNIT
);