1 /*
2 * Copyright (c) Tony Bybell 1999-2017.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 */
9
10
11 /*
12 * vcd.c 23jan99ajb
13 * evcd parts 29jun99ajb
14 * profiler optimizations 15jul99ajb
15 * more profiler optimizations 25jan00ajb
16 * finsim parameter fix 26jan00ajb
17 * vector rechaining code 03apr00ajb
18 * multiple var section code 06apr00ajb
19 * fix for duplicate nets 19dec00ajb
20 * support for alt hier seps 23dec00ajb
21 * fix for rcs identifiers 16jan01ajb
22 * coredump fix for bad VCD 04apr02ajb
23 * min/maxid speedup 27feb03ajb
24 * bugfix on min/maxid speedup 06jul03ajb
25 * escaped hier modification 20feb06ajb
26 * added real_parameter vartype 04aug06ajb
27 * added in/out port vartype 31jan07ajb
28 * use gperf for port vartypes 19feb07ajb
29 * MTI SV implicit-var fix 05apr07ajb
30 * MTI SV len=0 is real var 05apr07ajb
31 * Backtracking fix 16oct18ajb
32 */
33
34 /* AIX may need this for alloca to work */
35 #if defined _AIX
36 #pragma alloca
37 #endif
38
39 #include <config.h>
40 #include "globals.h"
41 #include "vcd.h"
42 #include "hierpack.h"
43
44 #undef VCD_BSEARCH_IS_PERFECT /* bsearch is imperfect under linux, but OK under AIX */
45
46 static void add_histent(TimeType time, struct Node *n, char ch, int regadd, char *vector);
47 static void add_tail_histents(void);
48 static void vcd_build_symbols(void);
49 static void vcd_cleanup(void);
50 static void evcd_strcpy(char *dst, char *src);
51
52 /******************************************************************/
53
malform_eof_fix(void)54 static void malform_eof_fix(void)
55 {
56 if(feof(GLOBALS->vcd_handle_vcd_c_1))
57 {
58 memset(GLOBALS->vcdbuf_vcd_c_1, ' ', VCD_BSIZ);
59 GLOBALS->vst_vcd_c_1=GLOBALS->vend_vcd_c_1;
60 }
61 }
62
63 /**/
64
strcpy_vcdalt(char * too,char * from,char delim)65 void strcpy_vcdalt(char *too, char *from, char delim)
66 {
67 char ch;
68
69 do
70 {
71 ch=*(from++);
72 if(ch==delim)
73 {
74 ch=GLOBALS->hier_delimeter;
75 }
76 } while((*(too++)=ch));
77 }
78
79
strcpy_delimfix(char * too,char * from)80 int strcpy_delimfix(char *too, char *from)
81 {
82 char ch;
83 int found = 0;
84
85 do
86 {
87 ch=*(from++);
88 if(ch==GLOBALS->hier_delimeter)
89 {
90 ch=VCDNAM_ESCAPE;
91 found = 1;
92 }
93 } while((*(too++)=ch));
94
95 if(found) GLOBALS->escaped_names_found_vcd_c_1 = found;
96
97 return(found);
98 }
99
100 /******************************************************************/
101
102
103 /******************************************************************/
104
105 enum Tokens { T_VAR, T_END, T_SCOPE, T_UPSCOPE,
106 T_COMMENT, T_DATE, T_DUMPALL, T_DUMPOFF, T_DUMPON,
107 T_DUMPVARS, T_ENDDEFINITIONS,
108 T_DUMPPORTS, T_DUMPPORTSOFF, T_DUMPPORTSON, T_DUMPPORTSALL,
109 T_TIMESCALE, T_VERSION, T_VCDCLOSE, T_TIMEZERO,
110 T_EOF, T_STRING, T_UNKNOWN_KEY };
111
112 static char *tokens[]={ "var", "end", "scope", "upscope",
113 "comment", "date", "dumpall", "dumpoff", "dumpon",
114 "dumpvars", "enddefinitions",
115 "dumpports", "dumpportsoff", "dumpportson", "dumpportsall",
116 "timescale", "version", "vcdclose", "timezero",
117 "", "", "" };
118
119 #define NUM_TOKENS 19
120
121
122 #define T_GET tok=get_token();if((tok==T_END)||(tok==T_EOF))break;
123
124 /******************************************************************/
125
126
127
128 /******************************************************************/
129
130 /*
131 * histent structs are NEVER freed so this is OK..
132 * (we are allocating as many entries that fit in 64k minus the size of the two
133 * bookkeeping void* pointers found in the malloc_2/free_2 routines in
134 * debug.c--unless Judy, then can dispense with pointer subtraction)
135 */
136 #ifdef _WAVE_HAVE_JUDY
137 #define VCD_HISTENT_GRANULARITY ( (64*1024) / sizeof(HistEnt) )
138 #else
139 #define VCD_HISTENT_GRANULARITY ( ( (64*1024)-(2*sizeof(void *)) ) / sizeof(HistEnt) )
140 #endif
141
histent_calloc(void)142 struct HistEnt *histent_calloc(void)
143 {
144 if(GLOBALS->he_curr_vcd_c_1==GLOBALS->he_fini_vcd_c_1)
145 {
146 GLOBALS->he_curr_vcd_c_1=(struct HistEnt *)calloc_2(VCD_HISTENT_GRANULARITY, sizeof(struct HistEnt));
147 GLOBALS->he_fini_vcd_c_1=GLOBALS->he_curr_vcd_c_1+VCD_HISTENT_GRANULARITY;
148 }
149
150 return(GLOBALS->he_curr_vcd_c_1++);
151 }
152
153 /******************************************************************/
154
155
156 /******************************************************************/
157
158
vcdid_hash(char * s,int len)159 static unsigned int vcdid_hash(char *s, int len)
160 {
161 unsigned int val=0;
162 int i;
163
164 s+=(len-1);
165
166 for(i=0;i<len;i++)
167 {
168 val *= 94;
169 val += (((unsigned char)*s) - 32);
170 s--;
171 }
172
173 return(val);
174 }
175
176 /******************************************************************/
177
178 /*
179 * bsearch compare
180 */
vcdsymbsearchcompare(const void * s1,const void * s2)181 static int vcdsymbsearchcompare(const void *s1, const void *s2)
182 {
183 char *v1;
184 struct vcdsymbol *v2;
185
186 v1=(char *)s1;
187 v2=*((struct vcdsymbol **)s2);
188
189 return(strcmp(v1, v2->id));
190 }
191
192
193 /*
194 * actual bsearch
195 */
bsearch_vcd(char * key,int len)196 static struct vcdsymbol *bsearch_vcd(char *key, int len)
197 {
198 struct vcdsymbol **v;
199 struct vcdsymbol *t;
200
201 if(GLOBALS->indexed_vcd_c_1)
202 {
203 unsigned int hsh = vcdid_hash(key, len);
204 if((hsh>=GLOBALS->vcd_minid_vcd_c_1)&&(hsh<=GLOBALS->vcd_maxid_vcd_c_1))
205 {
206 return(GLOBALS->indexed_vcd_c_1[hsh-GLOBALS->vcd_minid_vcd_c_1]);
207 }
208
209 return(NULL);
210 }
211
212 if(GLOBALS->sorted_vcd_c_1)
213 {
214 v=(struct vcdsymbol **)bsearch(key, GLOBALS->sorted_vcd_c_1, GLOBALS->numsyms_vcd_c_1,
215 sizeof(struct vcdsymbol *), vcdsymbsearchcompare);
216
217 if(v)
218 {
219 #ifndef VCD_BSEARCH_IS_PERFECT
220 for(;;)
221 {
222 t=*v;
223
224 if((v==GLOBALS->sorted_vcd_c_1)||(strcmp((*(--v))->id, key)))
225 {
226 return(t);
227 }
228 }
229 #else
230 return(*v);
231 #endif
232 }
233 else
234 {
235 return(NULL);
236 }
237 }
238 else
239 {
240 if(!GLOBALS->err_vcd_c_1)
241 {
242 fprintf(stderr, "Near byte %d, VCD search table NULL..is this a VCD file?\n", (int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)));
243 GLOBALS->err_vcd_c_1=1;
244 }
245 return(NULL);
246 }
247 }
248
249
250 /*
251 * sort on vcdsymbol pointers
252 */
vcdsymcompare(const void * s1,const void * s2)253 static int vcdsymcompare(const void *s1, const void *s2)
254 {
255 struct vcdsymbol *v1, *v2;
256
257 v1=*((struct vcdsymbol **)s1);
258 v2=*((struct vcdsymbol **)s2);
259
260 return(strcmp(v1->id, v2->id));
261 }
262
263
264 /*
265 * create sorted (by id) table
266 */
create_sorted_table(void)267 static void create_sorted_table(void)
268 {
269 struct vcdsymbol *v;
270 struct vcdsymbol **pnt;
271 unsigned int vcd_distance;
272
273 if(GLOBALS->sorted_vcd_c_1)
274 {
275 free_2(GLOBALS->sorted_vcd_c_1); /* this means we saw a 2nd enddefinition chunk! */
276 GLOBALS->sorted_vcd_c_1=NULL;
277 }
278
279 if(GLOBALS->indexed_vcd_c_1)
280 {
281 free_2(GLOBALS->indexed_vcd_c_1);
282 GLOBALS->indexed_vcd_c_1=NULL;
283 }
284
285 if(GLOBALS->numsyms_vcd_c_1)
286 {
287 vcd_distance = GLOBALS->vcd_maxid_vcd_c_1 - GLOBALS->vcd_minid_vcd_c_1 + 1;
288
289 if((vcd_distance <= VCD_INDEXSIZ)||(!GLOBALS->vcd_hash_kill))
290 {
291 GLOBALS->indexed_vcd_c_1 = (struct vcdsymbol **)calloc_2(vcd_distance, sizeof(struct vcdsymbol *));
292
293 /* printf("%d symbols span ID range of %d, using indexing...\n", GLOBALS->numsyms_vcd_c_1, vcd_distance); */
294
295 v=GLOBALS->vcdsymroot_vcd_c_1;
296 while(v)
297 {
298 if(!GLOBALS->indexed_vcd_c_1[v->nid - GLOBALS->vcd_minid_vcd_c_1]) GLOBALS->indexed_vcd_c_1[v->nid - GLOBALS->vcd_minid_vcd_c_1] = v;
299 v=v->next;
300 }
301 }
302 else
303 {
304 pnt=GLOBALS->sorted_vcd_c_1=(struct vcdsymbol **)calloc_2(GLOBALS->numsyms_vcd_c_1, sizeof(struct vcdsymbol *));
305 v=GLOBALS->vcdsymroot_vcd_c_1;
306 while(v)
307 {
308 *(pnt++)=v;
309 v=v->next;
310 }
311
312 qsort(GLOBALS->sorted_vcd_c_1, GLOBALS->numsyms_vcd_c_1, sizeof(struct vcdsymbol *), vcdsymcompare);
313 }
314 }
315 }
316
317 /******************************************************************/
318
319 /*
320 * single char get inlined/optimized
321 */
getch_alloc(void)322 static void getch_alloc(void)
323 {
324 GLOBALS->vend_vcd_c_1=GLOBALS->vst_vcd_c_1=GLOBALS->vcdbuf_vcd_c_1=(char *)calloc_2(1,VCD_BSIZ);
325 }
326
getch_free(void)327 static void getch_free(void)
328 {
329 free_2(GLOBALS->vcdbuf_vcd_c_1);
330 GLOBALS->vcdbuf_vcd_c_1=GLOBALS->vst_vcd_c_1=GLOBALS->vend_vcd_c_1=NULL;
331 }
332
333
334
getch_fetch(void)335 static int getch_fetch(void)
336 {
337 size_t rd;
338
339 errno = 0;
340 if(feof(GLOBALS->vcd_handle_vcd_c_1)) return(-1);
341
342 GLOBALS->vcdbyteno_vcd_c_1+=(GLOBALS->vend_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1);
343 rd=fread(GLOBALS->vcdbuf_vcd_c_1, sizeof(char), VCD_BSIZ, GLOBALS->vcd_handle_vcd_c_1);
344 GLOBALS->vend_vcd_c_1=(GLOBALS->vst_vcd_c_1=GLOBALS->vcdbuf_vcd_c_1)+rd;
345
346 if((!rd)||(errno)) return(-1);
347
348 if(GLOBALS->vcd_fsiz_vcd_c_1)
349 {
350 splash_sync(GLOBALS->vcdbyteno_vcd_c_1, GLOBALS->vcd_fsiz_vcd_c_1); /* gnome 2.18 seems to set errno so splash moved here... */
351 }
352
353 return((int)(*GLOBALS->vst_vcd_c_1));
354 }
355
356
getch(void)357 static inline signed char getch(void) {
358 signed char ch = ((GLOBALS->vst_vcd_c_1!=GLOBALS->vend_vcd_c_1)?((int)(*GLOBALS->vst_vcd_c_1)):(getch_fetch()));
359 GLOBALS->vst_vcd_c_1++;
360 return(ch);
361 }
362
getch_peek(void)363 static inline signed char getch_peek(void) {
364 signed char ch = ((GLOBALS->vst_vcd_c_1!=GLOBALS->vend_vcd_c_1)?((int)(*GLOBALS->vst_vcd_c_1)):(getch_fetch()));
365 /* no increment */
366 return(ch);
367 }
368
369
370
getch_patched(void)371 static int getch_patched(void)
372 {
373 char ch;
374
375 ch=*GLOBALS->vsplitcurr_vcd_c_1;
376 if(!ch)
377 {
378 return(-1);
379 }
380 else
381 {
382 GLOBALS->vsplitcurr_vcd_c_1++;
383 return((int)ch);
384 }
385 }
386
387 /*
388 * simple tokenizer
389 */
get_token(void)390 static int get_token(void)
391 {
392 int ch;
393 int i, len=0;
394 int is_string=0;
395 char *yyshadow;
396
397 for(;;)
398 {
399 ch=getch();
400 if(ch<0) return(T_EOF);
401 if(ch<=' ') continue; /* val<=' ' is a quick whitespace check */
402 break; /* (take advantage of fact that vcd is text) */
403 }
404 if(ch=='$')
405 {
406 GLOBALS->yytext_vcd_c_1[len++]=ch;
407 for(;;)
408 {
409 ch=getch();
410 if(ch<0) return(T_EOF);
411 if(ch<=' ') continue;
412 break;
413 }
414 }
415 else
416 {
417 is_string=1;
418 }
419
420 for(GLOBALS->yytext_vcd_c_1[len++]=ch;;GLOBALS->yytext_vcd_c_1[len++]=ch)
421 {
422 if(len==GLOBALS->T_MAX_STR_vcd_c_1)
423 {
424 GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1);
425 }
426 ch=getch();
427 if(ch<=' ') break;
428 }
429 GLOBALS->yytext_vcd_c_1[len]=0; /* terminator */
430
431 if(is_string)
432 {
433 GLOBALS->yylen_vcd_c_1=len;
434 return(T_STRING);
435 }
436
437 yyshadow=GLOBALS->yytext_vcd_c_1;
438 do
439 {
440 yyshadow++;
441 for(i=0;i<NUM_TOKENS;i++)
442 {
443 if(!strcmp(yyshadow,tokens[i]))
444 {
445 return(i);
446 }
447 }
448
449 } while(*yyshadow=='$'); /* fix for RCS ids in version strings */
450
451 return(T_UNKNOWN_KEY);
452 }
453
454
get_vartoken_patched(int match_kw)455 static int get_vartoken_patched(int match_kw)
456 {
457 int ch;
458 int len=0;
459
460 if(!GLOBALS->var_prevch_vcd_c_1)
461 {
462 for(;;)
463 {
464 ch=getch_patched();
465 if(ch<0) { free_2(GLOBALS->varsplit_vcd_c_1); GLOBALS->varsplit_vcd_c_1=NULL; return(V_END); }
466 if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')) continue;
467 break;
468 }
469 }
470 else
471 {
472 ch=GLOBALS->var_prevch_vcd_c_1;
473 GLOBALS->var_prevch_vcd_c_1=0;
474 }
475
476 if(ch=='[') return(V_LB);
477 if(ch==':') return(V_COLON);
478 if(ch==']') return(V_RB);
479
480 for(GLOBALS->yytext_vcd_c_1[len++]=ch;;GLOBALS->yytext_vcd_c_1[len++]=ch)
481 {
482 if(len==GLOBALS->T_MAX_STR_vcd_c_1)
483 {
484 GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1);
485 }
486 ch=getch_patched();
487 if(ch<0) { free_2(GLOBALS->varsplit_vcd_c_1); GLOBALS->varsplit_vcd_c_1=NULL; break; }
488 if((ch==':')||(ch==']'))
489 {
490 GLOBALS->var_prevch_vcd_c_1=ch;
491 break;
492 }
493 }
494 GLOBALS->yytext_vcd_c_1[len]=0; /* terminator */
495
496 if(match_kw)
497 {
498 int vt = vcd_keyword_code(GLOBALS->yytext_vcd_c_1, len);
499 if(vt != V_STRING)
500 {
501 if(ch<0) { free_2(GLOBALS->varsplit_vcd_c_1); GLOBALS->varsplit_vcd_c_1=NULL; }
502 return(vt);
503 }
504 }
505
506 GLOBALS->yylen_vcd_c_1=len;
507 if(ch<0) { free_2(GLOBALS->varsplit_vcd_c_1); GLOBALS->varsplit_vcd_c_1=NULL; }
508 return(V_STRING);
509 }
510
get_vartoken(int match_kw)511 static int get_vartoken(int match_kw)
512 {
513 int ch;
514 int len=0;
515
516 if(GLOBALS->varsplit_vcd_c_1)
517 {
518 int rc=get_vartoken_patched(match_kw);
519 if(rc!=V_END) return(rc);
520 GLOBALS->var_prevch_vcd_c_1=0;
521 }
522
523 if(!GLOBALS->var_prevch_vcd_c_1)
524 {
525 for(;;)
526 {
527 ch=getch();
528 if(ch<0) return(V_END);
529 if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')) continue;
530 break;
531 }
532 }
533 else
534 {
535 ch=GLOBALS->var_prevch_vcd_c_1;
536 GLOBALS->var_prevch_vcd_c_1=0;
537 }
538
539 if(ch=='[') return(V_LB);
540 if(ch==':') return(V_COLON);
541 if(ch==']') return(V_RB);
542
543 if(ch=='#') /* for MTI System Verilog '$var reg 64 >w #implicit-var###VarElem:ram_di[0.0] [63:0] $end' style declarations */
544 { /* debussy simply escapes until the space */
545 GLOBALS->yytext_vcd_c_1[len++]= '\\';
546 }
547
548 for(GLOBALS->yytext_vcd_c_1[len++]=ch;;GLOBALS->yytext_vcd_c_1[len++]=ch)
549 {
550 if(len==GLOBALS->T_MAX_STR_vcd_c_1)
551 {
552 GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1);
553 }
554
555 ch=getch();
556 if(ch==' ')
557 {
558 if(match_kw) break;
559 if(getch_peek() == '[')
560 {
561 ch = getch();
562 GLOBALS->varsplit_vcd_c_1=GLOBALS->yytext_vcd_c_1+len; /* keep looping so we get the *last* one */
563 continue;
564 }
565 }
566
567 if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')||(ch<0)) break;
568 if((ch=='[')&&(GLOBALS->yytext_vcd_c_1[0]!='\\'))
569 {
570 GLOBALS->varsplit_vcd_c_1=GLOBALS->yytext_vcd_c_1+len; /* keep looping so we get the *last* one */
571 }
572 else
573 if(((ch==':')||(ch==']'))&&(!GLOBALS->varsplit_vcd_c_1)&&(GLOBALS->yytext_vcd_c_1[0]!='\\'))
574 {
575 GLOBALS->var_prevch_vcd_c_1=ch;
576 break;
577 }
578 }
579 GLOBALS->yytext_vcd_c_1[len]=0; /* absolute terminator */
580 if((GLOBALS->varsplit_vcd_c_1)&&(GLOBALS->yytext_vcd_c_1[len-1]==']'))
581 {
582 char *vst;
583 vst=malloc_2(strlen(GLOBALS->varsplit_vcd_c_1)+1);
584 strcpy(vst, GLOBALS->varsplit_vcd_c_1);
585
586 *GLOBALS->varsplit_vcd_c_1=0x00; /* zero out var name at the left bracket */
587 len=GLOBALS->varsplit_vcd_c_1-GLOBALS->yytext_vcd_c_1;
588
589 GLOBALS->varsplit_vcd_c_1=GLOBALS->vsplitcurr_vcd_c_1=vst;
590 GLOBALS->var_prevch_vcd_c_1=0;
591 }
592 else
593 {
594 GLOBALS->varsplit_vcd_c_1=NULL;
595 }
596
597 if(match_kw)
598 {
599 int vt = vcd_keyword_code(GLOBALS->yytext_vcd_c_1, len);
600 if(vt != V_STRING)
601 {
602 return(vt);
603 }
604 }
605
606 GLOBALS->yylen_vcd_c_1=len;
607 return(V_STRING);
608 }
609
get_strtoken(void)610 static int get_strtoken(void)
611 {
612 int ch;
613 int len=0;
614
615 if(!GLOBALS->var_prevch_vcd_c_1)
616 {
617 for(;;)
618 {
619 ch=getch();
620 if(ch<0) return(V_END);
621 if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')) continue;
622 break;
623 }
624 }
625 else
626 {
627 ch=GLOBALS->var_prevch_vcd_c_1;
628 GLOBALS->var_prevch_vcd_c_1=0;
629 }
630
631 for(GLOBALS->yytext_vcd_c_1[len++]=ch;;GLOBALS->yytext_vcd_c_1[len++]=ch)
632 {
633 if(len==GLOBALS->T_MAX_STR_vcd_c_1)
634 {
635 GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1);
636 }
637 ch=getch();
638 if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')||(ch<0)) break;
639 }
640 GLOBALS->yytext_vcd_c_1[len]=0; /* terminator */
641
642 GLOBALS->yylen_vcd_c_1=len;
643 return(V_STRING);
644 }
645
sync_end(char * hdr)646 static void sync_end(char *hdr)
647 {
648 int tok;
649
650 if(hdr) { DEBUG(fprintf(stderr,"%s",hdr)); }
651 for(;;)
652 {
653 tok=get_token();
654 if((tok==T_END)||(tok==T_EOF)) break;
655 if(hdr) { DEBUG(fprintf(stderr," %s",GLOBALS->yytext_vcd_c_1)); }
656 }
657 if(hdr) { DEBUG(fprintf(stderr,"\n")); }
658 }
659
version_sync_end(char * hdr)660 static int version_sync_end(char *hdr)
661 {
662 int tok;
663 int rc = 0;
664
665 if(hdr) { DEBUG(fprintf(stderr,"%s",hdr)); }
666 for(;;)
667 {
668 tok=get_token();
669 if((tok==T_END)||(tok==T_EOF)) break;
670 if(hdr) { DEBUG(fprintf(stderr," %s",GLOBALS->yytext_vcd_c_1)); }
671 if(strstr(GLOBALS->yytext_vcd_c_1, "Icarus")) /* turn off autocoalesce for Icarus */
672 {
673 GLOBALS->autocoalesce = 0;
674 rc = 1;
675 }
676 }
677 if(hdr) { DEBUG(fprintf(stderr,"\n")); }
678 return(rc);
679 }
680
build_slisthier(void)681 char *build_slisthier(void)
682 {
683 struct slist *s;
684 int len=0;
685
686 if(GLOBALS->slisthier)
687 {
688 free_2(GLOBALS->slisthier);
689 }
690
691 if(!GLOBALS->slistroot)
692 {
693 GLOBALS->slisthier_len=0;
694 GLOBALS->slisthier=(char *)malloc_2(1);
695 *GLOBALS->slisthier=0;
696 return(GLOBALS->slisthier);
697 }
698
699 s=GLOBALS->slistroot; len=0;
700 while(s)
701 {
702 len+=s->len+(s->next?1:0);
703 s=s->next;
704 }
705
706 GLOBALS->slisthier=(char *)malloc_2((GLOBALS->slisthier_len=len)+1);
707 s=GLOBALS->slistroot; len=0;
708 while(s)
709 {
710 strcpy(GLOBALS->slisthier+len,s->str);
711 len+=s->len;
712 if(s->next)
713 {
714 strcpy(GLOBALS->slisthier+len,GLOBALS->vcd_hier_delimeter);
715 len++;
716 }
717 s=s->next;
718 }
719
720 return(GLOBALS->slisthier);
721 }
722
723
append_vcd_slisthier(char * str)724 void append_vcd_slisthier(char *str)
725 {
726 struct slist *s;
727 s=(struct slist *)calloc_2(1,sizeof(struct slist));
728 s->len=strlen(str);
729 s->str=(char *)malloc_2(s->len+1);
730 strcpy(s->str,str);
731
732 if(GLOBALS->slistcurr)
733 {
734 GLOBALS->slistcurr->next=s;
735 GLOBALS->slistcurr=s;
736 }
737 else
738 {
739 GLOBALS->slistcurr=GLOBALS->slistroot=s;
740 }
741
742 build_slisthier();
743 DEBUG(fprintf(stderr, "SCOPE: %s\n",GLOBALS->slisthier));
744 }
745
746
parse_valuechange(void)747 static void parse_valuechange(void)
748 {
749 struct vcdsymbol *v;
750 char *vector;
751 int vlen;
752
753 switch(GLOBALS->yytext_vcd_c_1[0])
754 {
755 case '0':
756 case '1':
757 case 'x': case 'X':
758 case 'z': case 'Z':
759 case 'h': case 'H':
760 case 'u': case 'U':
761 case 'w': case 'W':
762 case 'l': case 'L':
763 case '-':
764 if(GLOBALS->yylen_vcd_c_1>1)
765 {
766 v=bsearch_vcd(GLOBALS->yytext_vcd_c_1+1, GLOBALS->yylen_vcd_c_1-1);
767 if(!v)
768 {
769 fprintf(stderr,"Near byte %d, Unknown VCD identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)),GLOBALS->yytext_vcd_c_1+1);
770 malform_eof_fix();
771 }
772 else
773 {
774 v->value[0]=GLOBALS->yytext_vcd_c_1[0];
775 DEBUG(fprintf(stderr,"%s = '%c'\n",v->name,v->value[0]));
776 add_histent(GLOBALS->current_time_vcd_c_1,v->narray[0],v->value[0],1, NULL);
777 }
778 }
779 else
780 {
781 fprintf(stderr,"Near byte %d, Malformed VCD identifier\n", (int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)));
782 malform_eof_fix();
783 }
784 break;
785
786 case 'b':
787 case 'B':
788 {
789 /* extract binary number then.. */
790 vector=malloc_2(GLOBALS->yylen_cache_vcd_c_1=GLOBALS->yylen_vcd_c_1);
791 strcpy(vector,GLOBALS->yytext_vcd_c_1+1);
792 vlen=GLOBALS->yylen_vcd_c_1-1;
793
794 get_strtoken();
795 v=bsearch_vcd(GLOBALS->yytext_vcd_c_1, GLOBALS->yylen_vcd_c_1);
796 if(!v)
797 {
798 fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
799 free_2(vector);
800 malform_eof_fix();
801 }
802 else
803 {
804 if ((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE)||((GLOBALS->convert_to_reals)&&((v->vartype==V_INTEGER)||(v->vartype==V_PARAMETER))))
805 {
806 double *d;
807 char *pnt;
808 char ch;
809 TimeType k=0;
810
811 pnt=vector;
812 while((ch=*(pnt++))) { k=(k<<1)|((ch=='1')?1:0); }
813 free_2(vector);
814
815 d=malloc_2(sizeof(double));
816 *d=(double)k;
817
818 if(!v)
819 {
820 fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
821 free_2(d);
822 malform_eof_fix();
823 }
824 else
825 {
826 add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],'g',1,(char *)d);
827 }
828 break;
829 }
830
831 if(vlen<v->size) /* fill in left part */
832 {
833 char extend;
834 int i, fill;
835
836 extend=(vector[0]=='1')?'0':vector[0];
837
838 fill=v->size-vlen;
839 for(i=0;i<fill;i++)
840 {
841 v->value[i]=extend;
842 }
843 strcpy(v->value+fill,vector);
844 }
845 else if(vlen==v->size) /* straight copy */
846 {
847 strcpy(v->value,vector);
848 }
849 else /* too big, so copy only right half */
850 {
851 int skip;
852
853 skip=vlen-v->size;
854 strcpy(v->value,vector+skip);
855 }
856 DEBUG(fprintf(stderr,"%s = '%s'\n",v->name, v->value));
857
858 if((v->size==1)||(!GLOBALS->atomic_vectors))
859 {
860 int i;
861 for(i=0;i<v->size;i++)
862 {
863 add_histent(GLOBALS->current_time_vcd_c_1, v->narray[i],v->value[i],1, NULL);
864 }
865 free_2(vector);
866 }
867 else
868 {
869 if(GLOBALS->yylen_cache_vcd_c_1!=(v->size+1))
870 {
871 free_2(vector);
872 vector=malloc_2(v->size+1);
873 }
874 strcpy(vector,v->value);
875 add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],0,1,vector);
876 }
877
878 }
879 break;
880 }
881
882 case 'p':
883 /* extract port dump value.. */
884 vector=malloc_2(GLOBALS->yylen_cache_vcd_c_1=GLOBALS->yylen_vcd_c_1);
885 strcpy(vector,GLOBALS->yytext_vcd_c_1+1);
886 vlen=GLOBALS->yylen_vcd_c_1-1;
887
888 get_strtoken(); /* throw away 0_strength_component */
889 get_strtoken(); /* throw away 0_strength_component */
890 get_strtoken(); /* this is the id */
891 v=bsearch_vcd(GLOBALS->yytext_vcd_c_1, GLOBALS->yylen_vcd_c_1);
892 if(!v)
893 {
894 fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
895 free_2(vector);
896 malform_eof_fix();
897 }
898 else
899 {
900 if ((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE)||((GLOBALS->convert_to_reals)&&((v->vartype==V_INTEGER)||(v->vartype==V_PARAMETER))))
901 {
902 double *d;
903 char *pnt;
904 char ch;
905 TimeType k=0;
906
907 pnt=vector;
908 while((ch=*(pnt++))) { k=(k<<1)|((ch=='1')?1:0); }
909 free_2(vector);
910
911 d=malloc_2(sizeof(double));
912 *d=(double)k;
913
914 if(!v)
915 {
916 fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
917 free_2(d);
918 malform_eof_fix();
919 }
920 else
921 {
922 add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],'g',1,(char *)d);
923 }
924 break;
925 }
926
927 if(vlen<v->size) /* fill in left part */
928 {
929 char extend;
930 int i, fill;
931
932 extend='0';
933
934 fill=v->size-vlen;
935 for(i=0;i<fill;i++)
936 {
937 v->value[i]=extend;
938 }
939 evcd_strcpy(v->value+fill,vector);
940 }
941 else if(vlen==v->size) /* straight copy */
942 {
943 evcd_strcpy(v->value,vector);
944 }
945 else /* too big, so copy only right half */
946 {
947 int skip;
948
949 skip=vlen-v->size;
950 evcd_strcpy(v->value,vector+skip);
951 }
952 DEBUG(fprintf(stderr,"%s = '%s'\n",v->name, v->value));
953
954 if((v->size==1)||(!GLOBALS->atomic_vectors))
955 {
956 int i;
957 for(i=0;i<v->size;i++)
958 {
959 add_histent(GLOBALS->current_time_vcd_c_1, v->narray[i],v->value[i],1, NULL);
960 }
961 free_2(vector);
962 }
963 else
964 {
965 if(GLOBALS->yylen_cache_vcd_c_1<v->size)
966 {
967 free_2(vector);
968 vector=malloc_2(v->size+1);
969 }
970 strcpy(vector,v->value);
971 add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],0,1,vector);
972 }
973 }
974 break;
975
976
977 case 'r':
978 case 'R':
979 {
980 double *d;
981
982 d=malloc_2(sizeof(double));
983 sscanf(GLOBALS->yytext_vcd_c_1+1,"%lg",d);
984
985 get_strtoken();
986 v=bsearch_vcd(GLOBALS->yytext_vcd_c_1, GLOBALS->yylen_vcd_c_1);
987 if(!v)
988 {
989 fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
990 free_2(d);
991 malform_eof_fix();
992 }
993 else
994 {
995 add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],'g',1,(char *)d);
996 }
997
998 break;
999 }
1000
1001 #ifndef STRICT_VCD_ONLY
1002 case 's':
1003 case 'S':
1004 {
1005 char *d;
1006
1007 d=(char *)malloc_2(GLOBALS->yylen_vcd_c_1);
1008 vlen = fstUtilityEscToBin((unsigned char *)d, (unsigned char *)(GLOBALS->yytext_vcd_c_1+1), GLOBALS->yylen_vcd_c_1); /* includes 0 term */
1009 if(vlen != GLOBALS->yylen_vcd_c_1)
1010 {
1011 d = realloc_2(d, vlen);
1012 }
1013
1014 get_strtoken();
1015 v=bsearch_vcd(GLOBALS->yytext_vcd_c_1, GLOBALS->yylen_vcd_c_1);
1016 if(!v)
1017 {
1018 fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
1019 free_2(d);
1020 malform_eof_fix();
1021 }
1022 else
1023 {
1024 add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],'s',1,(char *)d);
1025 }
1026
1027 break;
1028 }
1029 #endif
1030 }
1031
1032 }
1033
1034
evcd_strcpy(char * dst,char * src)1035 static void evcd_strcpy(char *dst, char *src)
1036 {
1037 static const char *evcd="DUNZduLHXTlh01?FAaBbCcf";
1038 static const char *vcd="01xz0101xz0101xzxxxxxxz";
1039
1040 char ch;
1041 int i;
1042
1043 while((ch=*src))
1044 {
1045 for(i=0;i<23;i++)
1046 {
1047 if(evcd[i]==ch)
1048 {
1049 *dst=vcd[i];
1050 break;
1051 }
1052 }
1053 if(i==23) *dst='x';
1054
1055 src++;
1056 dst++;
1057 }
1058
1059 *dst=0; /* null terminate destination */
1060 }
1061
1062
vcd_parse(void)1063 static void vcd_parse(void)
1064 {
1065 int tok;
1066 unsigned char ttype;
1067 int disable_autocoalesce = 0;
1068
1069 for(;;)
1070 {
1071 switch(get_token())
1072 {
1073 case T_COMMENT:
1074 sync_end("COMMENT:");
1075 break;
1076 case T_DATE:
1077 sync_end("DATE:");
1078 break;
1079 case T_VERSION:
1080 disable_autocoalesce = version_sync_end("VERSION:");
1081 break;
1082 case T_TIMEZERO:
1083 {
1084 int vtok=get_token();
1085 if((vtok==T_END)||(vtok==T_EOF)) break;
1086 GLOBALS->global_time_offset=atoi_64(GLOBALS->yytext_vcd_c_1);
1087
1088 DEBUG(fprintf(stderr,"TIMEZERO: "TTFormat"\n",GLOBALS->global_time_offset));
1089 sync_end(NULL);
1090 }
1091 break;
1092 case T_TIMESCALE:
1093 {
1094 int vtok;
1095 int i;
1096 char prefix=' ';
1097
1098 vtok=get_token();
1099 if((vtok==T_END)||(vtok==T_EOF)) break;
1100 fractional_timescale_fix(GLOBALS->yytext_vcd_c_1);
1101 GLOBALS->time_scale=atoi_64(GLOBALS->yytext_vcd_c_1);
1102 if(!GLOBALS->time_scale) GLOBALS->time_scale=1;
1103 for(i=0;i<GLOBALS->yylen_vcd_c_1;i++)
1104 {
1105 if((GLOBALS->yytext_vcd_c_1[i]<'0')||(GLOBALS->yytext_vcd_c_1[i]>'9'))
1106 {
1107 prefix=GLOBALS->yytext_vcd_c_1[i];
1108 break;
1109 }
1110 }
1111 if(prefix==' ')
1112 {
1113 vtok=get_token();
1114 if((vtok==T_END)||(vtok==T_EOF)) break;
1115 prefix=GLOBALS->yytext_vcd_c_1[0];
1116 }
1117 switch(prefix)
1118 {
1119 case ' ':
1120 case 'm':
1121 case 'u':
1122 case 'n':
1123 case 'p':
1124 case 'f':
1125 case 'a':
1126 case 'z':
1127 GLOBALS->time_dimension=prefix;
1128 break;
1129 case 's':
1130 GLOBALS->time_dimension=' ';
1131 break;
1132 default: /* unknown */
1133 GLOBALS->time_dimension='n';
1134 break;
1135 }
1136
1137 DEBUG(fprintf(stderr,"TIMESCALE: "TTFormat" %cs\n",GLOBALS->time_scale, GLOBALS->time_dimension));
1138 sync_end(NULL);
1139 }
1140 break;
1141 case T_SCOPE:
1142 T_GET;
1143 {
1144 switch(GLOBALS->yytext_vcd_c_1[0])
1145 {
1146 case 'm': ttype = TREE_VCD_ST_MODULE; break;
1147 case 't': ttype = TREE_VCD_ST_TASK; break;
1148 case 'f': ttype = (GLOBALS->yytext_vcd_c_1[1] == 'u') ? TREE_VCD_ST_FUNCTION : TREE_VCD_ST_FORK; break;
1149 case 'b': ttype = TREE_VCD_ST_BEGIN; break;
1150 case 'g': ttype = TREE_VCD_ST_GENERATE; break;
1151 case 's': ttype = TREE_VCD_ST_STRUCT; break;
1152 case 'u': ttype = TREE_VCD_ST_UNION; break;
1153 case 'c': ttype = TREE_VCD_ST_CLASS; break;
1154 case 'i': ttype = TREE_VCD_ST_INTERFACE; break;
1155 case 'p': ttype = (GLOBALS->yytext_vcd_c_1[1] == 'r') ? TREE_VCD_ST_PROGRAM : TREE_VCD_ST_PACKAGE; break;
1156
1157 case 'v': {
1158 char *vht = GLOBALS->yytext_vcd_c_1;
1159 if(!strncmp(vht, "vhdl_", 5))
1160 {
1161 switch(vht[5])
1162 {
1163 case 'a': ttype = TREE_VHDL_ST_ARCHITECTURE; break;
1164 case 'r': ttype = TREE_VHDL_ST_RECORD; break;
1165 case 'b': ttype = TREE_VHDL_ST_BLOCK; break;
1166 case 'g': ttype = TREE_VHDL_ST_GENERATE; break;
1167 case 'i': ttype = TREE_VHDL_ST_GENIF; break;
1168 case 'f': ttype = (vht[6] == 'u') ? TREE_VHDL_ST_FUNCTION : TREE_VHDL_ST_GENFOR; break;
1169 case 'p': ttype = (!strncmp(vht+6, "roces", 5)) ? TREE_VHDL_ST_PROCESS: TREE_VHDL_ST_PROCEDURE; break;
1170 default: ttype = TREE_UNKNOWN; break;
1171 }
1172 }
1173 else
1174 {
1175 ttype = TREE_UNKNOWN;
1176 }
1177 }
1178 break;
1179
1180 default: ttype = TREE_UNKNOWN;
1181 break;
1182 }
1183 }
1184
1185 T_GET;
1186 if(tok==T_STRING)
1187 {
1188 struct slist *s;
1189 s=(struct slist *)calloc_2(1,sizeof(struct slist));
1190 s->len=GLOBALS->yylen_vcd_c_1;
1191 s->str=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+1);
1192 strcpy(s->str, GLOBALS->yytext_vcd_c_1);
1193 s->mod_tree_parent = GLOBALS->mod_tree_parent;
1194
1195 allocate_and_decorate_module_tree_node(ttype, GLOBALS->yytext_vcd_c_1, NULL, GLOBALS->yylen_vcd_c_1, 0, 0, 0);
1196
1197 if(GLOBALS->slistcurr)
1198 {
1199 GLOBALS->slistcurr->next=s;
1200 GLOBALS->slistcurr=s;
1201 }
1202 else
1203 {
1204 GLOBALS->slistcurr=GLOBALS->slistroot=s;
1205 }
1206
1207 build_slisthier();
1208 DEBUG(fprintf(stderr, "SCOPE: %s\n",GLOBALS->slisthier));
1209 }
1210 sync_end(NULL);
1211 break;
1212 case T_UPSCOPE:
1213 if(GLOBALS->slistroot)
1214 {
1215 struct slist *s;
1216
1217 GLOBALS->mod_tree_parent = GLOBALS->slistcurr->mod_tree_parent;
1218 s=GLOBALS->slistroot;
1219 if(!s->next)
1220 {
1221 free_2(s->str);
1222 free_2(s);
1223 GLOBALS->slistroot=GLOBALS->slistcurr=NULL;
1224 }
1225 else
1226 for(;;)
1227 {
1228 if(!s->next->next)
1229 {
1230 free_2(s->next->str);
1231 free_2(s->next);
1232 s->next=NULL;
1233 GLOBALS->slistcurr=s;
1234 break;
1235 }
1236 s=s->next;
1237 }
1238 build_slisthier();
1239 DEBUG(fprintf(stderr, "SCOPE: %s\n",GLOBALS->slisthier));
1240 }
1241 else
1242 {
1243 GLOBALS->mod_tree_parent = NULL;
1244 }
1245 sync_end(NULL);
1246 break;
1247 case T_VAR:
1248 if((GLOBALS->header_over_vcd_c_1)&&(0))
1249 {
1250 fprintf(stderr,"$VAR encountered after $ENDDEFINITIONS near byte %d. VCD is malformed, exiting.\n",
1251 (int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)));
1252 vcd_exit(255);
1253 }
1254 else
1255 {
1256 int vtok;
1257 struct vcdsymbol *v=NULL;
1258
1259 GLOBALS->var_prevch_vcd_c_1=0;
1260
1261 if(GLOBALS->varsplit_vcd_c_1)
1262 {
1263 free_2(GLOBALS->varsplit_vcd_c_1);
1264 GLOBALS->varsplit_vcd_c_1=NULL;
1265 }
1266 vtok=get_vartoken(1);
1267 if(vtok>V_STRINGTYPE) goto bail;
1268
1269 v=(struct vcdsymbol *)calloc_2(1,sizeof(struct vcdsymbol));
1270 v->vartype=vtok;
1271 v->msi=v->lsi=GLOBALS->vcd_explicit_zero_subscripts; /* indicate [un]subscripted status */
1272
1273 if(vtok==V_PORT)
1274 {
1275 vtok=get_vartoken(1);
1276 if(vtok==V_STRING)
1277 {
1278 v->size=atoi_64(GLOBALS->yytext_vcd_c_1);
1279 if(!v->size) v->size=1;
1280 }
1281 else
1282 if(vtok==V_LB)
1283 {
1284 vtok=get_vartoken(1);
1285 if(vtok==V_END) goto err;
1286 if(vtok!=V_STRING) goto err;
1287 v->msi=atoi_64(GLOBALS->yytext_vcd_c_1);
1288 vtok=get_vartoken(0);
1289 if(vtok==V_RB)
1290 {
1291 v->lsi=v->msi;
1292 v->size=1;
1293 }
1294 else
1295 {
1296 if(vtok!=V_COLON) goto err;
1297 vtok=get_vartoken(0);
1298 if(vtok!=V_STRING) goto err;
1299 v->lsi=atoi_64(GLOBALS->yytext_vcd_c_1);
1300 vtok=get_vartoken(0);
1301 if(vtok!=V_RB) goto err;
1302
1303 if(v->msi>v->lsi)
1304 {
1305 v->size=v->msi-v->lsi+1;
1306 }
1307 else
1308 {
1309 v->size=v->lsi-v->msi+1;
1310 }
1311 }
1312 }
1313 else goto err;
1314
1315 vtok=get_strtoken();
1316 if(vtok==V_END) goto err;
1317 v->id=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+1);
1318 strcpy(v->id, GLOBALS->yytext_vcd_c_1);
1319 v->nid=vcdid_hash(GLOBALS->yytext_vcd_c_1,GLOBALS->yylen_vcd_c_1);
1320
1321 if(v->nid == (GLOBALS->vcd_hash_max+1))
1322 {
1323 GLOBALS->vcd_hash_max = v->nid;
1324 }
1325 else
1326 if((v->nid>0)&&(v->nid<=GLOBALS->vcd_hash_max))
1327 {
1328 /* general case with aliases */
1329 }
1330 else
1331 {
1332 GLOBALS->vcd_hash_kill = 1;
1333 }
1334
1335 if(v->nid < GLOBALS->vcd_minid_vcd_c_1) GLOBALS->vcd_minid_vcd_c_1 = v->nid;
1336 if(v->nid > GLOBALS->vcd_maxid_vcd_c_1) GLOBALS->vcd_maxid_vcd_c_1 = v->nid;
1337
1338 vtok=get_vartoken(0);
1339 if(vtok!=V_STRING) goto err;
1340 if(GLOBALS->slisthier_len)
1341 {
1342 v->name=(char *)malloc_2(GLOBALS->slisthier_len+1+GLOBALS->yylen_vcd_c_1+1);
1343 strcpy(v->name,GLOBALS->slisthier);
1344 strcpy(v->name+GLOBALS->slisthier_len,GLOBALS->vcd_hier_delimeter);
1345 if(GLOBALS->alt_hier_delimeter)
1346 {
1347 strcpy_vcdalt(v->name+GLOBALS->slisthier_len+1,GLOBALS->yytext_vcd_c_1,GLOBALS->alt_hier_delimeter);
1348 }
1349 else
1350 {
1351 if((strcpy_delimfix(v->name+GLOBALS->slisthier_len+1,GLOBALS->yytext_vcd_c_1)) && (GLOBALS->yytext_vcd_c_1[0] != '\\'))
1352 {
1353 char *sd=(char *)malloc_2(GLOBALS->slisthier_len+1+GLOBALS->yylen_vcd_c_1+2);
1354 strcpy(sd,GLOBALS->slisthier);
1355 strcpy(sd+GLOBALS->slisthier_len,GLOBALS->vcd_hier_delimeter);
1356 sd[GLOBALS->slisthier_len+1] = '\\';
1357 strcpy(sd+GLOBALS->slisthier_len+2,v->name+GLOBALS->slisthier_len+1);
1358 free_2(v->name);
1359 v->name = sd;
1360 }
1361 }
1362 }
1363 else
1364 {
1365 v->name=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+1);
1366 if(GLOBALS->alt_hier_delimeter)
1367 {
1368 strcpy_vcdalt(v->name,GLOBALS->yytext_vcd_c_1,GLOBALS->alt_hier_delimeter);
1369 }
1370 else
1371 {
1372 if((strcpy_delimfix(v->name,GLOBALS->yytext_vcd_c_1)) && (GLOBALS->yytext_vcd_c_1[0] != '\\'))
1373 {
1374 char *sd=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+2);
1375 sd[0] = '\\';
1376 strcpy(sd+1,v->name);
1377 free_2(v->name);
1378 v->name = sd;
1379 }
1380 }
1381 }
1382
1383 if(GLOBALS->pv_vcd_c_1)
1384 {
1385 if(!strcmp(GLOBALS->pv_vcd_c_1->name,v->name) && !disable_autocoalesce && (!strchr(v->name, '\\')))
1386 {
1387 GLOBALS->pv_vcd_c_1->chain=v;
1388 v->root=GLOBALS->rootv_vcd_c_1;
1389 if(GLOBALS->pv_vcd_c_1==GLOBALS->rootv_vcd_c_1) GLOBALS->pv_vcd_c_1->root=GLOBALS->rootv_vcd_c_1;
1390 }
1391 else
1392 {
1393 GLOBALS->rootv_vcd_c_1=v;
1394 }
1395 }
1396 else
1397 {
1398 GLOBALS->rootv_vcd_c_1=v;
1399 }
1400 GLOBALS->pv_vcd_c_1=v;
1401 }
1402 else /* regular vcd var, not an evcd port var */
1403 {
1404 vtok=get_vartoken(1);
1405 if(vtok==V_END) goto err;
1406 v->size=atoi_64(GLOBALS->yytext_vcd_c_1);
1407 vtok=get_strtoken();
1408 if(vtok==V_END) goto err;
1409 v->id=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+1);
1410 strcpy(v->id, GLOBALS->yytext_vcd_c_1);
1411 v->nid=vcdid_hash(GLOBALS->yytext_vcd_c_1,GLOBALS->yylen_vcd_c_1);
1412
1413 if(v->nid == (GLOBALS->vcd_hash_max+1))
1414 {
1415 GLOBALS->vcd_hash_max = v->nid;
1416 }
1417 else
1418 if((v->nid>0)&&(v->nid<=GLOBALS->vcd_hash_max))
1419 {
1420 /* general case with aliases */
1421 }
1422 else
1423 {
1424 GLOBALS->vcd_hash_kill = 1;
1425 }
1426
1427 if(v->nid < GLOBALS->vcd_minid_vcd_c_1) GLOBALS->vcd_minid_vcd_c_1 = v->nid;
1428 if(v->nid > GLOBALS->vcd_maxid_vcd_c_1) GLOBALS->vcd_maxid_vcd_c_1 = v->nid;
1429
1430 vtok=get_vartoken(0);
1431 if(vtok!=V_STRING) goto err;
1432 if(GLOBALS->slisthier_len)
1433 {
1434 v->name=(char *)malloc_2(GLOBALS->slisthier_len+1+GLOBALS->yylen_vcd_c_1+1);
1435 strcpy(v->name,GLOBALS->slisthier);
1436 strcpy(v->name+GLOBALS->slisthier_len,GLOBALS->vcd_hier_delimeter);
1437 if(GLOBALS->alt_hier_delimeter)
1438 {
1439 strcpy_vcdalt(v->name+GLOBALS->slisthier_len+1,GLOBALS->yytext_vcd_c_1,GLOBALS->alt_hier_delimeter);
1440 }
1441 else
1442 {
1443 if((strcpy_delimfix(v->name+GLOBALS->slisthier_len+1,GLOBALS->yytext_vcd_c_1)) && (GLOBALS->yytext_vcd_c_1[0] != '\\'))
1444 {
1445 char *sd=(char *)malloc_2(GLOBALS->slisthier_len+1+GLOBALS->yylen_vcd_c_1+2);
1446 strcpy(sd,GLOBALS->slisthier);
1447 strcpy(sd+GLOBALS->slisthier_len,GLOBALS->vcd_hier_delimeter);
1448 sd[GLOBALS->slisthier_len+1] = '\\';
1449 strcpy(sd+GLOBALS->slisthier_len+2,v->name+GLOBALS->slisthier_len+1);
1450 free_2(v->name);
1451 v->name = sd;
1452 }
1453 }
1454 }
1455 else
1456 {
1457 v->name=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+1);
1458 if(GLOBALS->alt_hier_delimeter)
1459 {
1460 strcpy_vcdalt(v->name,GLOBALS->yytext_vcd_c_1,GLOBALS->alt_hier_delimeter);
1461 }
1462 else
1463 {
1464 if((strcpy_delimfix(v->name,GLOBALS->yytext_vcd_c_1)) && (GLOBALS->yytext_vcd_c_1[0] != '\\'))
1465 {
1466 char *sd=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+2);
1467 sd[0] = '\\';
1468 strcpy(sd+1,v->name);
1469 free_2(v->name);
1470 v->name = sd;
1471 }
1472 }
1473 }
1474
1475 if(GLOBALS->pv_vcd_c_1)
1476 {
1477 if(!strcmp(GLOBALS->pv_vcd_c_1->name,v->name))
1478 {
1479 GLOBALS->pv_vcd_c_1->chain=v;
1480 v->root=GLOBALS->rootv_vcd_c_1;
1481 if(GLOBALS->pv_vcd_c_1==GLOBALS->rootv_vcd_c_1) GLOBALS->pv_vcd_c_1->root=GLOBALS->rootv_vcd_c_1;
1482 }
1483 else
1484 {
1485 GLOBALS->rootv_vcd_c_1=v;
1486 }
1487 }
1488 else
1489 {
1490 GLOBALS->rootv_vcd_c_1=v;
1491 }
1492 GLOBALS->pv_vcd_c_1=v;
1493
1494 vtok=get_vartoken(1);
1495 if(vtok==V_END) goto dumpv;
1496 if(vtok!=V_LB) goto err;
1497 vtok=get_vartoken(0);
1498 if(vtok!=V_STRING) goto err;
1499 v->msi=atoi_64(GLOBALS->yytext_vcd_c_1);
1500 vtok=get_vartoken(0);
1501 if(vtok==V_RB)
1502 {
1503 v->lsi=v->msi;
1504 goto dumpv;
1505 }
1506 if(vtok!=V_COLON) goto err;
1507 vtok=get_vartoken(0);
1508 if(vtok!=V_STRING) goto err;
1509 v->lsi=atoi_64(GLOBALS->yytext_vcd_c_1);
1510 vtok=get_vartoken(0);
1511 if(vtok!=V_RB) goto err;
1512 }
1513
1514 dumpv:
1515 if(v->size == 0)
1516 {
1517 if(v->vartype != V_EVENT)
1518 {
1519 if(v->vartype != V_STRINGTYPE)
1520 {
1521 v->vartype = V_REAL;
1522 }
1523 }
1524 else
1525 {
1526 v->size = 1;
1527 }
1528
1529 } /* MTI fix */
1530
1531 if((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE)||((GLOBALS->convert_to_reals)&&((v->vartype==V_INTEGER)||(v->vartype==V_PARAMETER))))
1532 {
1533 if(v->vartype!=V_STRINGTYPE)
1534 {
1535 v->vartype=V_REAL;
1536 }
1537 v->size=1; /* override any data we parsed in */
1538 v->msi=v->lsi=0;
1539 }
1540 else
1541 if((v->size>1)&&(v->msi<=0)&&(v->lsi<=0))
1542 {
1543 if(v->vartype==V_EVENT)
1544 {
1545 v->size=1;
1546 }
1547 else
1548 {
1549 /* any criteria for the direction here? */
1550 v->msi=v->size-1;
1551 v->lsi=0;
1552 }
1553 }
1554 else
1555 if((v->msi>v->lsi)&&((v->msi-v->lsi+1)!=v->size))
1556 {
1557 if((v->vartype!=V_EVENT)&&(v->vartype!=V_PARAMETER))
1558 {
1559 if((v->msi-v->lsi+1) > v->size) /* if() is 2d add */
1560 {
1561 v->msi = v->size-1; v->lsi = 0;
1562 }
1563 /* all this formerly was goto err; */
1564 }
1565 else
1566 {
1567 v->size=v->msi-v->lsi+1;
1568 }
1569 }
1570 else
1571 if((v->lsi>=v->msi)&&((v->lsi-v->msi+1)!=v->size))
1572 {
1573 if((v->vartype!=V_EVENT)&&(v->vartype!=V_PARAMETER))
1574 {
1575 if((v->lsi-v->msi+1) > v->size) /* if() is 2d add */
1576 {
1577 v->lsi = v->size-1; v->msi = 0;
1578 }
1579 /* all this formerly was goto err; */
1580 }
1581 else
1582 {
1583 v->size=v->lsi-v->msi+1;
1584 }
1585 }
1586
1587 /* initial conditions */
1588 v->value=(char *)malloc_2(v->size+1);
1589 v->value[v->size]=0;
1590 v->narray=(struct Node **)calloc_2(v->size,sizeof(struct Node *));
1591 {
1592 int i;
1593 if(GLOBALS->atomic_vectors)
1594 {
1595 for(i=0;i<v->size;i++)
1596 {
1597 v->value[i]='x';
1598 }
1599 v->narray[0]=(struct Node *)calloc_2(1,sizeof(struct Node));
1600 v->narray[0]->head.time=-1;
1601 v->narray[0]->head.v.h_val=AN_X;
1602 set_vcd_vartype(v, v->narray[0]);
1603 }
1604 else
1605 {
1606 for(i=0;i<v->size;i++)
1607 {
1608 v->value[i]='x';
1609
1610 v->narray[i]=(struct Node *)calloc_2(1,sizeof(struct Node));
1611 v->narray[i]->head.time=-1;
1612 v->narray[i]->head.v.h_val=AN_X;
1613 if(i == 0)
1614 {
1615 set_vcd_vartype(v, v->narray[0]);
1616 }
1617 else
1618 {
1619 v->narray[i]->vartype = v->narray[0]->vartype;
1620 }
1621 }
1622 }
1623 }
1624
1625 if(!GLOBALS->vcdsymroot_vcd_c_1)
1626 {
1627 GLOBALS->vcdsymroot_vcd_c_1=GLOBALS->vcdsymcurr_vcd_c_1=v;
1628 }
1629 else
1630 {
1631 GLOBALS->vcdsymcurr_vcd_c_1->next=v;
1632 GLOBALS->vcdsymcurr_vcd_c_1=v;
1633 }
1634 GLOBALS->numsyms_vcd_c_1++;
1635
1636 if(GLOBALS->vcd_save_handle)
1637 {
1638 if(v->msi==v->lsi)
1639 {
1640 if((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE))
1641 {
1642 fprintf(GLOBALS->vcd_save_handle,"%s\n",v->name);
1643 }
1644 else
1645 {
1646 if(v->msi>=0)
1647 {
1648 if(!GLOBALS->vcd_explicit_zero_subscripts)
1649 fprintf(GLOBALS->vcd_save_handle,"%s%c%d\n",v->name,GLOBALS->hier_delimeter,v->msi);
1650 else
1651 fprintf(GLOBALS->vcd_save_handle,"%s[%d]\n",v->name,v->msi);
1652 }
1653 else
1654 {
1655 fprintf(GLOBALS->vcd_save_handle,"%s\n",v->name);
1656 }
1657 }
1658 }
1659 else
1660 {
1661 int i;
1662
1663 if(!GLOBALS->atomic_vectors)
1664 {
1665 fprintf(GLOBALS->vcd_save_handle,"#%s[%d:%d]",v->name,v->msi,v->lsi);
1666 if(v->msi>v->lsi)
1667 {
1668 for(i=v->msi;i>=v->lsi;i--)
1669 {
1670 if(!GLOBALS->vcd_explicit_zero_subscripts)
1671 fprintf(GLOBALS->vcd_save_handle," %s%c%d",v->name,GLOBALS->hier_delimeter,i);
1672 else
1673 fprintf(GLOBALS->vcd_save_handle," %s[%d]",v->name,i);
1674 }
1675 }
1676 else
1677 {
1678 for(i=v->msi;i<=v->lsi;i++)
1679 {
1680 if(!GLOBALS->vcd_explicit_zero_subscripts)
1681 fprintf(GLOBALS->vcd_save_handle," %s%c%d",v->name,GLOBALS->hier_delimeter,i);
1682 else
1683 fprintf(GLOBALS->vcd_save_handle," %s[%d]",v->name,i);
1684 }
1685 }
1686 fprintf(GLOBALS->vcd_save_handle,"\n");
1687 }
1688 else
1689 {
1690 fprintf(GLOBALS->vcd_save_handle,"%s[%d:%d]\n",v->name,v->msi,v->lsi);
1691 }
1692 }
1693 }
1694
1695 goto bail;
1696 err:
1697 if(v)
1698 {
1699 GLOBALS->error_count_vcd_c_1++;
1700 if(v->name)
1701 {
1702 fprintf(stderr, "Near byte %d, $VAR parse error encountered with '%s'\n", (int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), v->name);
1703 free_2(v->name);
1704 }
1705 else
1706 {
1707 fprintf(stderr, "Near byte %d, $VAR parse error encountered\n", (int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)));
1708 }
1709 if(v->id) free_2(v->id);
1710 if(v->value) free_2(v->value);
1711 free_2(v);
1712 GLOBALS->pv_vcd_c_1 = NULL;
1713 }
1714
1715 bail:
1716 if(vtok!=V_END) sync_end(NULL);
1717 break;
1718 }
1719 case T_ENDDEFINITIONS:
1720 GLOBALS->header_over_vcd_c_1=1; /* do symbol table management here */
1721 create_sorted_table();
1722 if((!GLOBALS->sorted_vcd_c_1)&&(!GLOBALS->indexed_vcd_c_1))
1723 {
1724 fprintf(stderr, "No symbols in VCD file..nothing to do!\n");
1725 vcd_exit(255);
1726 }
1727 if(GLOBALS->error_count_vcd_c_1)
1728 {
1729 fprintf(stderr, "\n%d VCD parse errors encountered, exiting.\n", GLOBALS->error_count_vcd_c_1);
1730 vcd_exit(255);
1731 }
1732 break;
1733 case T_STRING:
1734 if(!GLOBALS->header_over_vcd_c_1)
1735 {
1736 GLOBALS->header_over_vcd_c_1=1; /* do symbol table management here */
1737 create_sorted_table();
1738 if((!GLOBALS->sorted_vcd_c_1)&&(!GLOBALS->indexed_vcd_c_1)) break;
1739 }
1740 {
1741 /* catchall for events when header over */
1742 if(GLOBALS->yytext_vcd_c_1[0]=='#')
1743 {
1744 TimeType tim;
1745 tim=atoi_64(GLOBALS->yytext_vcd_c_1+1);
1746
1747 if(GLOBALS->start_time_vcd_c_1<0)
1748 {
1749 GLOBALS->start_time_vcd_c_1=tim;
1750 }
1751 /* backtracking fix */
1752 else
1753 {
1754 if(tim < GLOBALS->current_time_vcd_c_1) /* avoid backtracking time counts which can happen on malformed files */
1755 {
1756 if(!GLOBALS->vcd_already_backtracked)
1757 {
1758 GLOBALS->vcd_already_backtracked = 1;
1759 fprintf(stderr, "VCDLOAD | Time backtracking detected in VCD file!\n");
1760 }
1761 #if 0
1762 tim = GLOBALS->current_time_vcd_c_1;
1763 #endif
1764 }
1765 }
1766
1767 GLOBALS->current_time_vcd_c_1=tim;
1768 if(GLOBALS->end_time_vcd_c_1<tim) GLOBALS->end_time_vcd_c_1=tim; /* in case of malformed vcd files */
1769 DEBUG(fprintf(stderr,"#"TTFormat"\n",tim));
1770 }
1771 else
1772 {
1773 parse_valuechange();
1774 }
1775 }
1776 break;
1777 case T_DUMPALL: /* dump commands modify vals anyway so */
1778 case T_DUMPPORTSALL:
1779 break; /* just loop through.. */
1780 case T_DUMPOFF:
1781 case T_DUMPPORTSOFF:
1782 GLOBALS->dumping_off_vcd_c_1=1;
1783 /* if((!GLOBALS->blackout_regions)||((GLOBALS->blackout_regions)&&(GLOBALS->blackout_regions->bstart<=GLOBALS->blackout_regions->bend))) : remove redundant condition */
1784 if((!GLOBALS->blackout_regions)||(GLOBALS->blackout_regions->bstart<=GLOBALS->blackout_regions->bend))
1785 {
1786 struct blackout_region_t *bt = calloc_2(1, sizeof(struct blackout_region_t));
1787
1788 bt->bstart = GLOBALS->current_time_vcd_c_1;
1789 bt->next = GLOBALS->blackout_regions;
1790 GLOBALS->blackout_regions = bt;
1791 }
1792 break;
1793 case T_DUMPON:
1794 case T_DUMPPORTSON:
1795 GLOBALS->dumping_off_vcd_c_1=0;
1796 if((GLOBALS->blackout_regions)&&(GLOBALS->blackout_regions->bstart>GLOBALS->blackout_regions->bend))
1797 {
1798 GLOBALS->blackout_regions->bend = GLOBALS->current_time_vcd_c_1;
1799 }
1800 break;
1801 case T_DUMPVARS:
1802 case T_DUMPPORTS:
1803 if(GLOBALS->current_time_vcd_c_1<0)
1804 { GLOBALS->start_time_vcd_c_1=GLOBALS->current_time_vcd_c_1=GLOBALS->end_time_vcd_c_1=0; }
1805 break;
1806 case T_VCDCLOSE:
1807 sync_end("VCDCLOSE:");
1808 break; /* next token will be '#' time related followed by $end */
1809 case T_END: /* either closure for dump commands or */
1810 break; /* it's spurious */
1811 case T_UNKNOWN_KEY:
1812 sync_end(NULL); /* skip over unknown keywords */
1813 break;
1814 case T_EOF:
1815 if((GLOBALS->blackout_regions)&&(GLOBALS->blackout_regions->bstart>GLOBALS->blackout_regions->bend))
1816 {
1817 GLOBALS->blackout_regions->bend = GLOBALS->current_time_vcd_c_1;
1818 }
1819 return;
1820 default:
1821 DEBUG(fprintf(stderr,"UNKNOWN TOKEN\n"));
1822 }
1823 }
1824 }
1825
1826
1827 /*******************************************************************************/
1828
add_histent(TimeType tim,struct Node * n,char ch,int regadd,char * vector)1829 void add_histent(TimeType tim, struct Node *n, char ch, int regadd, char *vector)
1830 {
1831 struct HistEnt *he;
1832 char heval;
1833
1834 if(!vector)
1835 {
1836 if(!n->curr)
1837 {
1838 he=histent_calloc();
1839 he->time=-1;
1840 he->v.h_val=AN_X;
1841
1842 n->curr=he;
1843 n->head.next=he;
1844
1845 add_histent(tim,n,ch,regadd, vector);
1846 }
1847 else
1848 {
1849 if(regadd) { tim*=(GLOBALS->time_scale); }
1850
1851 if(ch=='0') heval=AN_0; else
1852 if(ch=='1') heval=AN_1; else
1853 if((ch=='x')||(ch=='X')) heval=AN_X; else
1854 if((ch=='z')||(ch=='Z')) heval=AN_Z; else
1855 if((ch=='h')||(ch=='H')) heval=AN_H; else
1856 if((ch=='u')||(ch=='U')) heval=AN_U; else
1857 if((ch=='w')||(ch=='W')) heval=AN_W; else
1858 if((ch=='l')||(ch=='L')) heval=AN_L; else
1859 /* if(ch=='-') */ heval=AN_DASH; /* default */
1860
1861 if((n->curr->v.h_val!=heval)||(tim==GLOBALS->start_time_vcd_c_1)||(n->vartype==ND_VCD_EVENT)||(GLOBALS->vcd_preserve_glitches)) /* same region == go skip */
1862 {
1863 if(n->curr->time>=tim) /* backtracking fix */
1864 {
1865 DEBUG(printf("Warning: Glitch at time ["TTFormat"] Signal [%p], Value [%c->%c].\n",
1866 tim, n, AN_STR[n->curr->v.h_val], ch));
1867 n->curr->v.h_val=heval; /* we have a glitch! */
1868
1869 GLOBALS->num_glitches_vcd_c_2++;
1870 if(!(n->curr->flags&HIST_GLITCH))
1871 {
1872 n->curr->flags|=HIST_GLITCH; /* set the glitch flag */
1873 GLOBALS->num_glitch_regions_vcd_c_2++;
1874 }
1875 }
1876 else
1877 {
1878 he=histent_calloc();
1879 he->time=tim;
1880 he->v.h_val=heval;
1881
1882 n->curr->next=he;
1883 if(n->curr->v.h_val==heval)
1884 {
1885 n->curr->flags|=HIST_GLITCH; /* set the glitch flag */
1886 GLOBALS->num_glitch_regions_vcd_recoder_c_4++;
1887 }
1888 n->curr=he;
1889 GLOBALS->regions+=regadd;
1890 }
1891 }
1892 }
1893 }
1894 else
1895 {
1896 switch(ch)
1897 {
1898 case 's': /* string */
1899 {
1900 if(!n->curr)
1901 {
1902 he=histent_calloc();
1903 he->flags=(HIST_STRING|HIST_REAL);
1904 he->time=-1;
1905 he->v.h_vector=NULL;
1906
1907 n->curr=he;
1908 n->head.next=he;
1909
1910 add_histent(tim,n,ch,regadd, vector);
1911 }
1912 else
1913 {
1914 if(regadd) { tim*=(GLOBALS->time_scale); }
1915
1916 if(n->curr->time>=tim) /* backtracking fix */
1917 {
1918 DEBUG(printf("Warning: String Glitch at time ["TTFormat"] Signal [%p].\n",
1919 tim, n));
1920 if(n->curr->v.h_vector) free_2(n->curr->v.h_vector);
1921 n->curr->v.h_vector=vector; /* we have a glitch! */
1922
1923 GLOBALS->num_glitches_vcd_c_2++;
1924 if(!(n->curr->flags&HIST_GLITCH))
1925 {
1926 n->curr->flags|=HIST_GLITCH; /* set the glitch flag */
1927 GLOBALS->num_glitch_regions_vcd_c_2++;
1928 }
1929 }
1930 else
1931 {
1932 he=histent_calloc();
1933 he->flags=(HIST_STRING|HIST_REAL);
1934 he->time=tim;
1935 he->v.h_vector=vector;
1936
1937 n->curr->next=he;
1938 n->curr=he;
1939 GLOBALS->regions+=regadd;
1940 }
1941 }
1942 break;
1943 }
1944 case 'g': /* real number */
1945 {
1946 if(!n->curr)
1947 {
1948 he=histent_calloc();
1949 he->flags=HIST_REAL;
1950 he->time=-1;
1951 #ifdef WAVE_HAS_H_DOUBLE
1952 he->v.h_double = strtod("NaN", NULL);
1953 #else
1954 he->v.h_vector=NULL;
1955 #endif
1956
1957 n->curr=he;
1958 n->head.next=he;
1959
1960 add_histent(tim,n,ch,regadd, vector);
1961 }
1962 else
1963 {
1964 if(regadd) { tim*=(GLOBALS->time_scale); }
1965
1966 if(
1967 #ifdef WAVE_HAS_H_DOUBLE
1968 (vector&&(n->curr->v.h_double!=*(double *)vector))
1969 #else
1970 (n->curr->v.h_vector&&vector&&(*(double *)n->curr->v.h_vector!=*(double *)vector))
1971 #endif
1972 ||(tim==GLOBALS->start_time_vcd_c_1)
1973 #ifndef WAVE_HAS_H_DOUBLE
1974 ||(!n->curr->v.h_vector)
1975 #endif
1976 ||(GLOBALS->vcd_preserve_glitches)||(GLOBALS->vcd_preserve_glitches_real)
1977 ) /* same region == go skip */
1978 {
1979 if(n->curr->time>=tim) /* backtracking fix */
1980 {
1981 DEBUG(printf("Warning: Real number Glitch at time ["TTFormat"] Signal [%p].\n",
1982 tim, n));
1983 #ifdef WAVE_HAS_H_DOUBLE
1984 n->curr->v.h_double = *((double *)vector);
1985 #else
1986 if(n->curr->v.h_vector) free_2(n->curr->v.h_vector);
1987 n->curr->v.h_vector=vector; /* we have a glitch! */
1988 #endif
1989 GLOBALS->num_glitches_vcd_c_2++;
1990 if(!(n->curr->flags&HIST_GLITCH))
1991 {
1992 n->curr->flags|=HIST_GLITCH; /* set the glitch flag */
1993 GLOBALS->num_glitch_regions_vcd_c_2++;
1994 }
1995 }
1996 else
1997 {
1998 he=histent_calloc();
1999 he->flags=HIST_REAL;
2000 he->time=tim;
2001 #ifdef WAVE_HAS_H_DOUBLE
2002 he->v.h_double = *((double *)vector);
2003 #else
2004 he->v.h_vector=vector;
2005 #endif
2006 n->curr->next=he;
2007 n->curr=he;
2008 GLOBALS->regions+=regadd;
2009 }
2010 }
2011 else
2012 {
2013 #ifndef WAVE_HAS_H_DOUBLE
2014 free_2(vector);
2015 #endif
2016 }
2017 #ifdef WAVE_HAS_H_DOUBLE
2018 free_2(vector);
2019 #endif
2020 }
2021 break;
2022 }
2023 default:
2024 {
2025 if(!n->curr)
2026 {
2027 he=histent_calloc();
2028 he->time=-1;
2029 he->v.h_vector=NULL;
2030
2031 n->curr=he;
2032 n->head.next=he;
2033
2034 add_histent(tim,n,ch,regadd, vector);
2035 }
2036 else
2037 {
2038 if(regadd) { tim*=(GLOBALS->time_scale); }
2039
2040 if(
2041 (n->curr->v.h_vector&&vector&&(strcmp(n->curr->v.h_vector,vector)))
2042 ||(tim==GLOBALS->start_time_vcd_c_1)
2043 ||(!n->curr->v.h_vector)
2044 ||(GLOBALS->vcd_preserve_glitches)
2045 ) /* same region == go skip */
2046 {
2047 if(n->curr->time>=tim) /* backtracking fix */
2048 {
2049 DEBUG(printf("Warning: Glitch at time ["TTFormat"] Signal [%p], Value [%c->%c].\n",
2050 tim, n, AN_STR[n->curr->v.h_val], ch));
2051 if(n->curr->v.h_vector) free_2(n->curr->v.h_vector);
2052 n->curr->v.h_vector=vector; /* we have a glitch! */
2053
2054 GLOBALS->num_glitches_vcd_c_2++;
2055 if(!(n->curr->flags&HIST_GLITCH))
2056 {
2057 n->curr->flags|=HIST_GLITCH; /* set the glitch flag */
2058 GLOBALS->num_glitch_regions_vcd_c_2++;
2059 }
2060 }
2061 else
2062 {
2063 he=histent_calloc();
2064 he->time=tim;
2065 he->v.h_vector=vector;
2066
2067 n->curr->next=he;
2068 n->curr=he;
2069 GLOBALS->regions+=regadd;
2070 }
2071 }
2072 else
2073 {
2074 free_2(vector);
2075 }
2076 }
2077 break;
2078 }
2079 }
2080 }
2081
2082 }
2083
2084
set_vcd_vartype(struct vcdsymbol * v,nptr n)2085 void set_vcd_vartype(struct vcdsymbol *v, nptr n)
2086 {
2087 unsigned char nvt;
2088
2089 switch(v->vartype)
2090 {
2091 case V_EVENT: nvt = ND_VCD_EVENT; break;
2092 case V_PARAMETER: nvt = ND_VCD_PARAMETER; break;
2093 case V_INTEGER: nvt = ND_VCD_INTEGER; break;
2094 case V_REAL: nvt = ND_VCD_REAL; break;
2095 case V_REG: nvt = ND_VCD_REG; break;
2096 case V_SUPPLY0: nvt = ND_VCD_SUPPLY0; break;
2097 case V_SUPPLY1: nvt = ND_VCD_SUPPLY1; break;
2098 case V_TIME: nvt = ND_VCD_TIME; break;
2099 case V_TRI: nvt = ND_VCD_TRI; break;
2100 case V_TRIAND: nvt = ND_VCD_TRIAND; break;
2101 case V_TRIOR: nvt = ND_VCD_TRIOR; break;
2102 case V_TRIREG: nvt = ND_VCD_TRIREG; break;
2103 case V_TRI0: nvt = ND_VCD_TRI0; break;
2104 case V_TRI1: nvt = ND_VCD_TRI1; break;
2105 case V_WAND: nvt = ND_VCD_WAND; break;
2106 case V_WIRE: nvt = ND_VCD_WIRE; break;
2107 case V_WOR: nvt = ND_VCD_WOR; break;
2108 case V_PORT: nvt = ND_VCD_PORT; break;
2109 case V_STRINGTYPE: nvt = ND_GEN_STRING; break;
2110 case V_BIT: nvt = ND_SV_BIT; break;
2111 case V_LOGIC: nvt = ND_SV_LOGIC; break;
2112 case V_INT: nvt = ND_SV_INT; break;
2113 case V_SHORTINT: nvt = ND_SV_SHORTINT; break;
2114 case V_LONGINT: nvt = ND_SV_LONGINT; break;
2115 case V_BYTE: nvt = ND_SV_BYTE; break;
2116 case V_ENUM: nvt = ND_SV_ENUM; break;
2117 /* V_SHORTREAL as a type does not exist for VCD: is cast to V_REAL */
2118 default: nvt = ND_UNSPECIFIED_DEFAULT; break;
2119 }
2120 n->vartype = nvt;
2121 }
2122
2123
add_tail_histents(void)2124 static void add_tail_histents(void)
2125 {
2126 int j;
2127 struct vcdsymbol *v;
2128
2129 /* dump out any pending events 1st (removed) */
2130 /* then do 'x' trailers */
2131
2132 v=GLOBALS->vcdsymroot_vcd_c_1;
2133 while(v)
2134 {
2135 if((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE))
2136 {
2137 double *d;
2138
2139 d=malloc_2(sizeof(double));
2140 *d=1.0;
2141 add_histent(MAX_HISTENT_TIME-1, v->narray[0], 'g', 0, (char *)d);
2142 }
2143 else
2144 if((v->size==1)||(!GLOBALS->atomic_vectors))
2145 for(j=0;j<v->size;j++)
2146 {
2147 add_histent(MAX_HISTENT_TIME-1, v->narray[j], 'x', 0, NULL);
2148 }
2149 else
2150 {
2151 add_histent(MAX_HISTENT_TIME-1, v->narray[0], 'x', 0, (char *)calloc_2(1,sizeof(char)));
2152 }
2153
2154 v=v->next;
2155 }
2156
2157 v=GLOBALS->vcdsymroot_vcd_c_1;
2158 while(v)
2159 {
2160 if((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE))
2161 {
2162 double *d;
2163
2164 d=malloc_2(sizeof(double));
2165 *d=0.0;
2166 add_histent(MAX_HISTENT_TIME, v->narray[0], 'g', 0, (char *)d);
2167 }
2168 else
2169 if((v->size==1)||(!GLOBALS->atomic_vectors))
2170 for(j=0;j<v->size;j++)
2171 {
2172 add_histent(MAX_HISTENT_TIME, v->narray[j], 'z', 0, NULL);
2173 }
2174 else
2175 {
2176 add_histent(MAX_HISTENT_TIME, v->narray[0], 'z', 0, (char *)calloc_2(1,sizeof(char)));
2177 }
2178
2179 v=v->next;
2180 }
2181 }
2182
2183 /*******************************************************************************/
2184
vcd_build_symbols(void)2185 static void vcd_build_symbols(void)
2186 {
2187 int j;
2188 int max_slen=-1;
2189 struct sym_chain *sym_chain=NULL, *sym_curr=NULL;
2190 int duphier=0;
2191 char hashdirty;
2192 struct vcdsymbol *v, *vprime;
2193 char *str = wave_alloca(1); /* quiet scan-build null pointer warning below */
2194 #ifdef _WAVE_HAVE_JUDY
2195 int ss_len, longest = 0;
2196 #endif
2197
2198 v=GLOBALS->vcdsymroot_vcd_c_1;
2199 while(v)
2200 {
2201 int msi;
2202 int delta;
2203
2204 {
2205 int slen;
2206 int substnode;
2207
2208 msi=v->msi;
2209 delta=((v->lsi-v->msi)<0)?-1:1;
2210 substnode=0;
2211
2212 slen=strlen(v->name);
2213 str=(slen>max_slen)?(wave_alloca((max_slen=slen)+32)):(str); /* more than enough */
2214 strcpy(str,v->name);
2215
2216 if((v->msi>=0)||(v->msi != v->lsi))
2217 {
2218 strcpy(str+slen,GLOBALS->vcd_hier_delimeter);
2219 slen++;
2220 }
2221
2222 if((vprime=bsearch_vcd(v->id, strlen(v->id)))!=v) /* hash mish means dup net */
2223 {
2224 if(v->size!=vprime->size)
2225 {
2226 fprintf(stderr,"ERROR: Duplicate IDs with differing width: %s %s\n", v->name, vprime->name);
2227 }
2228 else
2229 {
2230 substnode=1;
2231 }
2232 }
2233
2234 if(((v->size==1)||(!GLOBALS->atomic_vectors))&&(v->vartype!=V_REAL)&&(v->vartype!=V_STRINGTYPE))
2235 {
2236 struct symbol *s = NULL;
2237
2238 for(j=0;j<v->size;j++)
2239 {
2240 if(v->msi>=0)
2241 {
2242 if(!GLOBALS->vcd_explicit_zero_subscripts)
2243 sprintf(str+slen,"%d",msi);
2244 else
2245 sprintf(str+slen-1,"[%d]",msi);
2246 }
2247
2248 hashdirty=0;
2249 if(symfind(str, NULL))
2250 {
2251 char *dupfix=(char *)malloc_2(max_slen+32);
2252 #ifndef _WAVE_HAVE_JUDY
2253 hashdirty=1;
2254 #endif
2255 DEBUG(fprintf(stderr,"Warning: %s is a duplicate net name.\n",str));
2256
2257 do sprintf(dupfix, "$DUP%d%s%s", duphier++, GLOBALS->vcd_hier_delimeter, str);
2258 while(symfind(dupfix, NULL));
2259
2260 strcpy(str, dupfix);
2261 free_2(dupfix);
2262 duphier=0; /* reset for next duplicate resolution */
2263 }
2264 /* fallthrough */
2265 {
2266 s=symadd(str,hashdirty?hash(str):GLOBALS->hashcache);
2267 #ifdef _WAVE_HAVE_JUDY
2268 ss_len = strlen(str); if(ss_len >= longest) { longest = ss_len + 1; }
2269 #endif
2270 s->n=v->narray[j];
2271 if(substnode)
2272 {
2273 struct Node *n, *n2;
2274
2275 n=s->n;
2276 n2=vprime->narray[j];
2277 /* nname stays same */
2278 n->head=n2->head;
2279 n->curr=n2->curr;
2280 /* harray calculated later */
2281 n->numhist=n2->numhist;
2282 }
2283
2284 #ifndef _WAVE_HAVE_JUDY
2285 s->n->nname=s->name;
2286 #endif
2287 if(!GLOBALS->firstnode)
2288 {
2289 GLOBALS->firstnode=
2290 GLOBALS->curnode=calloc_2(1, sizeof(struct symchain));
2291 }
2292 else
2293 {
2294 GLOBALS->curnode->next=calloc_2(1, sizeof(struct symchain));
2295 GLOBALS->curnode=GLOBALS->curnode->next;
2296 }
2297 GLOBALS->curnode->symbol=s;
2298
2299 GLOBALS->numfacs++;
2300 DEBUG(fprintf(stderr,"Added: %s\n",str));
2301 }
2302 msi+=delta;
2303 }
2304
2305 if((j==1)&&(v->root))
2306 {
2307 s->vec_root=(struct symbol *)v->root; /* these will get patched over */
2308 s->vec_chain=(struct symbol *)v->chain; /* these will get patched over */
2309 v->sym_chain=s;
2310
2311 if(!sym_chain)
2312 {
2313 sym_curr=(struct sym_chain *)calloc_2(1,sizeof(struct sym_chain));
2314 sym_chain=sym_curr;
2315 }
2316 else
2317 {
2318 sym_curr->next=(struct sym_chain *)calloc_2(1,sizeof(struct sym_chain));
2319 sym_curr=sym_curr->next;
2320 }
2321 sym_curr->val=s;
2322 }
2323 }
2324 else /* atomic vector */
2325 {
2326 if((v->vartype!=V_REAL)&&(v->vartype!=V_STRINGTYPE)&&(v->vartype!=V_INTEGER)&&(v->vartype!=V_PARAMETER))
2327 /* if((v->vartype!=V_REAL)&&(v->vartype!=V_STRINGTYPE)) */
2328 {
2329 sprintf(str+slen-1,"[%d:%d]",v->msi,v->lsi);
2330 /* 2d add */
2331 if((v->msi>v->lsi)&&((v->msi-v->lsi+1)!=v->size))
2332 {
2333 if((v->vartype!=V_EVENT)&&(v->vartype!=V_PARAMETER))
2334 {
2335 v->msi = v->size-1; v->lsi = 0;
2336 }
2337 }
2338 else
2339 if((v->lsi>=v->msi)&&((v->lsi-v->msi+1)!=v->size))
2340 {
2341 if((v->vartype!=V_EVENT)&&(v->vartype!=V_PARAMETER))
2342 {
2343 v->lsi = v->size-1; v->msi = 0;
2344 }
2345 }
2346 }
2347 else
2348 {
2349 *(str+slen-1)=0;
2350 }
2351
2352
2353 hashdirty=0;
2354 if(symfind(str, NULL))
2355 {
2356 char *dupfix=(char *)malloc_2(max_slen+32);
2357 #ifndef _WAVE_HAVE_JUDY
2358 hashdirty=1;
2359 #endif
2360 DEBUG(fprintf(stderr,"Warning: %s is a duplicate net name.\n",str));
2361
2362 do sprintf(dupfix, "$DUP%d%s%s", duphier++, GLOBALS->vcd_hier_delimeter, str);
2363 while(symfind(dupfix, NULL));
2364
2365 strcpy(str, dupfix);
2366 free_2(dupfix);
2367 duphier=0; /* reset for next duplicate resolution */
2368 }
2369 /* fallthrough */
2370 {
2371 struct symbol *s;
2372
2373 s=symadd(str,hashdirty?hash(str):GLOBALS->hashcache); /* cut down on double lookups.. */
2374 #ifdef _WAVE_HAVE_JUDY
2375 ss_len = strlen(str); if(ss_len >= longest) { longest = ss_len + 1; }
2376 #endif
2377 s->n=v->narray[0];
2378 if(substnode)
2379 {
2380 struct Node *n, *n2;
2381
2382 n=s->n;
2383 n2=vprime->narray[0];
2384 /* nname stays same */
2385 n->head=n2->head;
2386 n->curr=n2->curr;
2387 /* harray calculated later */
2388 n->numhist=n2->numhist;
2389 n->extvals=n2->extvals;
2390 n->msi=n2->msi;
2391 n->lsi=n2->lsi;
2392 }
2393 else
2394 {
2395 s->n->msi=v->msi;
2396 s->n->lsi=v->lsi;
2397
2398 s->n->extvals=1;
2399 }
2400
2401 #ifndef _WAVE_HAVE_JUDY
2402 s->n->nname=s->name;
2403 #endif
2404 if(!GLOBALS->firstnode)
2405 {
2406 GLOBALS->firstnode=
2407 GLOBALS->curnode=calloc_2(1, sizeof(struct symchain));
2408 }
2409 else
2410 {
2411 GLOBALS->curnode->next=calloc_2(1, sizeof(struct symchain));
2412 GLOBALS->curnode=GLOBALS->curnode->next;
2413 }
2414 GLOBALS->curnode->symbol=s;
2415
2416 GLOBALS->numfacs++;
2417 DEBUG(fprintf(stderr,"Added: %s\n",str));
2418 }
2419 }
2420 }
2421
2422 v=v->next;
2423 }
2424
2425 #ifdef _WAVE_HAVE_JUDY
2426 {
2427 Pvoid_t PJArray = GLOBALS->sym_judy;
2428 PPvoid_t PPValue;
2429 char *Index = calloc_2(1, longest);
2430
2431 for (PPValue = JudySLFirst (PJArray, (uint8_t *)Index, PJE0);
2432 PPValue != (PPvoid_t) NULL;
2433 PPValue = JudySLNext (PJArray, (uint8_t *)Index, PJE0))
2434 {
2435 struct symbol *s = *(struct symbol **)PPValue;
2436 s->name = strdup_2(Index);
2437 s->n->nname = s->name;
2438 }
2439
2440 free_2(Index);
2441 }
2442 #endif
2443
2444 if(sym_chain)
2445 {
2446 sym_curr=sym_chain;
2447 while(sym_curr)
2448 {
2449 sym_curr->val->vec_root= ((struct vcdsymbol *)sym_curr->val->vec_root)->sym_chain;
2450
2451 if ((struct vcdsymbol *)sym_curr->val->vec_chain)
2452 sym_curr->val->vec_chain=((struct vcdsymbol *)sym_curr->val->vec_chain)->sym_chain;
2453
2454 DEBUG(printf("Link: ('%s') '%s' -> '%s'\n",sym_curr->val->vec_root->name, sym_curr->val->name, sym_curr->val->vec_chain?sym_curr->val->vec_chain->name:"(END)"));
2455
2456 sym_chain=sym_curr;
2457 sym_curr=sym_curr->next;
2458 free_2(sym_chain);
2459 }
2460 }
2461 }
2462
2463 /*******************************************************************************/
2464
vcd_sortfacs(void)2465 void vcd_sortfacs(void)
2466 {
2467 int i;
2468
2469 GLOBALS->facs=(struct symbol **)malloc_2(GLOBALS->numfacs*sizeof(struct symbol *));
2470 GLOBALS->curnode=GLOBALS->firstnode;
2471 for(i=0;i<GLOBALS->numfacs;i++)
2472 {
2473 char *subst;
2474 #ifdef WAVE_HIERFIX
2475 char ch;
2476 #endif
2477 int len;
2478 struct symchain *sc;
2479
2480 GLOBALS->facs[i]=GLOBALS->curnode->symbol;
2481 subst=GLOBALS->facs[i]->name;
2482 if((len=strlen(subst))>GLOBALS->longestname) GLOBALS->longestname=len;
2483 sc = GLOBALS->curnode;
2484 GLOBALS->curnode=GLOBALS->curnode->next;
2485 free_2(sc);
2486 #ifdef WAVE_HIERFIX
2487 while((ch=(*subst)))
2488 {
2489 if(ch==GLOBALS->hier_delimeter) { *subst=VCDNAM_HIERSORT; } /* forces sort at hier boundaries */
2490 subst++;
2491 }
2492 #endif
2493 }
2494 GLOBALS->firstnode=GLOBALS->curnode=NULL;
2495
2496 /* quicksort(facs,0,numfacs-1); */ /* quicksort deprecated because it degenerates on sorted traces..badly. very badly. */
2497 wave_heapsort(GLOBALS->facs,GLOBALS->numfacs);
2498
2499 #ifdef WAVE_HIERFIX
2500 for(i=0;i<GLOBALS->numfacs;i++)
2501 {
2502 char *subst, ch;
2503
2504 subst=GLOBALS->facs[i]->name;
2505 while((ch=(*subst)))
2506 {
2507 if(ch==VCDNAM_HIERSORT) { *subst=GLOBALS->hier_delimeter; } /* restore back to normal */
2508 subst++;
2509 }
2510
2511 #ifdef DEBUG_FACILITIES
2512 printf("%-4d %s\n",i,facs[i]->name);
2513 #endif
2514 }
2515 #endif
2516
2517 GLOBALS->facs_are_sorted=1;
2518
2519 init_tree();
2520 for(i=0;i<GLOBALS->numfacs;i++)
2521 {
2522 char *n = GLOBALS->facs[i]->name;
2523 build_tree_from_name(n, i);
2524
2525 if(GLOBALS->escaped_names_found_vcd_c_1)
2526 {
2527 char *subst, ch;
2528 subst=GLOBALS->facs[i]->name;
2529 while((ch=(*subst)))
2530 {
2531 if(ch==VCDNAM_ESCAPE) { *subst=GLOBALS->hier_delimeter; } /* restore back to normal */
2532 subst++;
2533 }
2534 }
2535 }
2536 treegraft(&GLOBALS->treeroot);
2537 treesort(GLOBALS->treeroot, NULL);
2538
2539 if(GLOBALS->escaped_names_found_vcd_c_1)
2540 {
2541 treenamefix(GLOBALS->treeroot);
2542 }
2543 }
2544
2545 /*******************************************************************************/
2546
vcd_cleanup(void)2547 static void vcd_cleanup(void)
2548 {
2549 struct slist *s, *s2;
2550 struct vcdsymbol *v, *vt;
2551
2552 if(GLOBALS->indexed_vcd_c_1)
2553 {
2554 free_2(GLOBALS->indexed_vcd_c_1); GLOBALS->indexed_vcd_c_1=NULL;
2555 }
2556
2557 if(GLOBALS->sorted_vcd_c_1)
2558 {
2559 free_2(GLOBALS->sorted_vcd_c_1); GLOBALS->sorted_vcd_c_1=NULL;
2560 }
2561
2562 v=GLOBALS->vcdsymroot_vcd_c_1;
2563 while(v)
2564 {
2565 if(v->name) free_2(v->name);
2566 if(v->id) free_2(v->id);
2567 if(v->value) free_2(v->value);
2568 if(v->narray) free_2(v->narray);
2569 vt=v;
2570 v=v->next;
2571 free_2(vt);
2572 }
2573 GLOBALS->vcdsymroot_vcd_c_1=GLOBALS->vcdsymcurr_vcd_c_1=NULL;
2574
2575 if(GLOBALS->slisthier) { free_2(GLOBALS->slisthier); GLOBALS->slisthier=NULL; }
2576 s=GLOBALS->slistroot;
2577 while(s)
2578 {
2579 s2=s->next;
2580 if(s->str)free_2(s->str);
2581 free_2(s);
2582 s=s2;
2583 }
2584
2585 GLOBALS->slistroot=GLOBALS->slistcurr=NULL; GLOBALS->slisthier_len=0;
2586
2587 if(GLOBALS->vcd_is_compressed_vcd_c_1)
2588 {
2589 pclose(GLOBALS->vcd_handle_vcd_c_1);
2590 GLOBALS->vcd_handle_vcd_c_1 = NULL;
2591 }
2592 else
2593 {
2594 fclose(GLOBALS->vcd_handle_vcd_c_1);
2595 GLOBALS->vcd_handle_vcd_c_1 = NULL;
2596 }
2597
2598 if(GLOBALS->yytext_vcd_c_1)
2599 {
2600 free_2(GLOBALS->yytext_vcd_c_1);
2601 GLOBALS->yytext_vcd_c_1=NULL;
2602 }
2603 }
2604
2605 /*******************************************************************************/
2606
vcd_main(char * fname)2607 TimeType vcd_main(char *fname)
2608 {
2609 GLOBALS->pv_vcd_c_1=GLOBALS->rootv_vcd_c_1=NULL;
2610 GLOBALS->vcd_hier_delimeter[0]=GLOBALS->hier_delimeter;
2611
2612 errno=0; /* reset in case it's set for some reason */
2613
2614 GLOBALS->yytext_vcd_c_1=(char *)malloc_2(GLOBALS->T_MAX_STR_vcd_c_1+1);
2615
2616 if(!GLOBALS->hier_was_explicitly_set) /* set default hierarchy split char */
2617 {
2618 GLOBALS->hier_delimeter='.';
2619 }
2620
2621 if(suffix_check(fname, ".gz") || suffix_check(fname, ".zip"))
2622 {
2623 char *str;
2624 int dlen;
2625 dlen=strlen(WAVE_DECOMPRESSOR);
2626 str=wave_alloca(strlen(fname)+dlen+1);
2627 strcpy(str,WAVE_DECOMPRESSOR);
2628 strcpy(str+dlen,fname);
2629 GLOBALS->vcd_handle_vcd_c_1=popen(str,"r");
2630 GLOBALS->vcd_is_compressed_vcd_c_1=~0;
2631 }
2632 else
2633 {
2634 if(strcmp("-vcd",fname))
2635 {
2636 GLOBALS->vcd_handle_vcd_c_1=fopen(fname,"rb");
2637
2638 if(GLOBALS->vcd_handle_vcd_c_1)
2639 {
2640 fseeko(GLOBALS->vcd_handle_vcd_c_1, 0, SEEK_END); /* do status bar for vcd load */
2641 GLOBALS->vcd_fsiz_vcd_c_1 = ftello(GLOBALS->vcd_handle_vcd_c_1);
2642 fseeko(GLOBALS->vcd_handle_vcd_c_1, 0, SEEK_SET);
2643 }
2644
2645 if(GLOBALS->vcd_warning_filesize < 0) GLOBALS->vcd_warning_filesize = VCD_SIZE_WARN;
2646
2647 if(GLOBALS->vcd_warning_filesize)
2648 if(GLOBALS->vcd_fsiz_vcd_c_1 > (GLOBALS->vcd_warning_filesize * (1024 * 1024)))
2649 {
2650 fprintf(stderr, "Warning! File size is %d MB. This might fail to load.\n"
2651 "Consider converting it to the FST database format instead. (See the\n"
2652 "vcd2fst(1) manpage for more information.)\n"
2653 "To disable this warning, set rc variable vcd_warning_filesize to zero.\n"
2654 "Alternatively, use the -o, --optimize command line option to convert to LXT2.\n\n",
2655 (int)(GLOBALS->vcd_fsiz_vcd_c_1/(1024*1024)));
2656 }
2657 }
2658 else
2659 {
2660 GLOBALS->vcd_handle_vcd_c_1=stdin;
2661 GLOBALS->splash_disable = 1;
2662 }
2663 GLOBALS->vcd_is_compressed_vcd_c_1=0;
2664 }
2665
2666 if(!GLOBALS->vcd_handle_vcd_c_1)
2667 {
2668 fprintf(stderr, "Error opening %s .vcd file '%s'.\n",
2669 GLOBALS->vcd_is_compressed_vcd_c_1?"compressed":"", fname);
2670 perror("Why");
2671 vcd_exit(255);
2672 }
2673
2674 /* SPLASH */ splash_create();
2675
2676 sym_hash_initialize(GLOBALS);
2677 getch_alloc(); /* alloc membuff for vcd getch buffer */
2678
2679 build_slisthier();
2680
2681 vcd_parse();
2682 if(GLOBALS->varsplit_vcd_c_1)
2683 {
2684 free_2(GLOBALS->varsplit_vcd_c_1);
2685 GLOBALS->varsplit_vcd_c_1=NULL;
2686 }
2687
2688 if((!GLOBALS->sorted_vcd_c_1)&&(!GLOBALS->indexed_vcd_c_1))
2689 {
2690 fprintf(stderr, "No symbols in VCD file..is it malformed? Exiting!\n");
2691 vcd_exit(255);
2692 }
2693 add_tail_histents();
2694
2695 if(GLOBALS->vcd_save_handle) { fclose(GLOBALS->vcd_save_handle); GLOBALS->vcd_save_handle = NULL; }
2696
2697 fprintf(stderr, "["TTFormat"] start time.\n["TTFormat"] end time.\n", GLOBALS->start_time_vcd_c_1*GLOBALS->time_scale, GLOBALS->end_time_vcd_c_1*GLOBALS->time_scale);
2698 if(GLOBALS->num_glitches_vcd_c_2) fprintf(stderr, "Warning: encountered %d glitch%s across %d glitch region%s.\n",
2699 GLOBALS->num_glitches_vcd_c_2, (GLOBALS->num_glitches_vcd_c_2!=1)?"es":"",
2700 GLOBALS->num_glitch_regions_vcd_c_2, (GLOBALS->num_glitch_regions_vcd_c_2!=1)?"s":"");
2701
2702 if(GLOBALS->vcd_fsiz_vcd_c_1)
2703 {
2704 splash_sync(GLOBALS->vcd_fsiz_vcd_c_1, GLOBALS->vcd_fsiz_vcd_c_1);
2705 GLOBALS->vcd_fsiz_vcd_c_1 = 0;
2706 }
2707 else
2708 if(GLOBALS->vcd_is_compressed_vcd_c_1)
2709 {
2710 splash_sync(1,1);
2711 GLOBALS->vcd_fsiz_vcd_c_1 = 0;
2712 }
2713
2714 GLOBALS->min_time=GLOBALS->start_time_vcd_c_1*GLOBALS->time_scale;
2715 GLOBALS->max_time=GLOBALS->end_time_vcd_c_1*GLOBALS->time_scale;
2716 GLOBALS->global_time_offset = GLOBALS->global_time_offset * GLOBALS->time_scale;
2717
2718 if((GLOBALS->min_time==GLOBALS->max_time)&&(GLOBALS->max_time==LLDescriptor(-1)))
2719 {
2720 fprintf(stderr, "VCD times range is equal to zero. Exiting.\n");
2721 vcd_exit(255);
2722 }
2723
2724 vcd_build_symbols();
2725 vcd_sortfacs();
2726 vcd_cleanup();
2727
2728 getch_free(); /* free membuff for vcd getch buffer */
2729
2730 if(GLOBALS->blackout_regions)
2731 {
2732 struct blackout_region_t *bt = GLOBALS->blackout_regions;
2733 while(bt)
2734 {
2735 bt->bstart *= GLOBALS->time_scale;
2736 bt->bend *= GLOBALS->time_scale;
2737 bt = bt->next;
2738 }
2739 }
2740
2741 GLOBALS->is_vcd=~0;
2742
2743 /* SPLASH */ splash_finalize();
2744 return(GLOBALS->max_time);
2745 }
2746
2747 /*******************************************************************************/
2748
2749