1 /*
2 * Copyright (c) 2001-2014 Tony Bybell.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23 /*
24 * vcd.c 23jan99ajb
25 * evcd parts 29jun99ajb
26 * profiler optimizations 15jul99ajb
27 * stripped out of gtkwave 21jul99ajb
28 * fix for duplicate nets 19dec00ajb
29 * lxt conversion added 20nov01ajb
30 */
31 #if defined _AIX
32 #pragma alloca
33 #endif
34
35 #include <config.h>
36 #include <wavealloca.h>
37
38 #include "v2l_analyzer_lxt2.h"
39 #include "lxt2_write.h"
40 #include "wave_locale.h"
41
42 #undef VCD_BSEARCH_IS_PERFECT /* bsearch is imperfect under linux, but OK under AIX */
43
44 struct lxt2_wr_trace *lt=NULL;
45
46 int numfacs=0;
47 int deadcnt=0;
48
49 int opt_depth = 4;
50 uint64_t opt_break_size = 0;
51 int opt_partial_mode = -1;
52 int opt_checkpoint_disable = 0;
53 int opt_maxgranule = 8;
54
55 struct symbol **sym=NULL;
56 struct symbol **facs=NULL;
57 struct symbol *firstnode=NULL;
58 struct symbol *curnode=NULL;
59 TimeType min_time=-1, max_time=-1;
60 char hier_delimeter='.';
61 char deadchar='X';
62
63 int vcd_explicit_zero_subscripts=-1; /* 0=yes, -1=no */
64 char atomic_vectors=1;
65
66 static FILE *vcd_handle=NULL;
67 static char vcd_is_compressed=0;
68
69 static void add_histent(TimeType time, struct Node *n, char ch, int regadd, char *vector);
70 static void add_tail_histents(void);
71 static void evcd_strcpy(char *dst, char *src);
72
73 static int vcdlineno=1;
74 static int header_over=0;
75 static int dumping_off=0;
76 static TimeType start_time=-1;
77 static TimeType end_time=-1;
78 static TimeType current_time=-1;
79 static TimeType time_scale=1; /* multiplier is 1, 10, 100 */
80 static TimeType time_zero=0;
81
82 static char vcd_hier_delimeter[2]={0, 0}; /* fill in after rc reading code */
83
84 /******************************************************************/
85
86 static struct slist *slistroot=NULL, *slistcurr=NULL;
87 static char *slisthier=NULL;
88 static int slisthier_len=0;
89
90 /******************************************************************/
91
92 enum Tokens { T_VAR, T_END, T_SCOPE, T_UPSCOPE,
93 T_COMMENT, T_DATE, T_DUMPALL, T_DUMPOFF, T_DUMPON,
94 T_DUMPVARS, T_ENDDEFINITIONS,
95 T_DUMPPORTS, T_DUMPPORTSOFF, T_DUMPPORTSON, T_DUMPPORTSALL,
96 T_TIMESCALE, T_VERSION, T_VCDCLOSE, T_TIMEZERO,
97 T_EOF, T_STRING, T_UNKNOWN_KEY };
98
99 char *tokens[]={ "var", "end", "scope", "upscope",
100 "comment", "date", "dumpall", "dumpoff", "dumpon",
101 "dumpvars", "enddefinitions",
102 "dumpports", "dumpportsoff", "dumpportson", "dumpportsall",
103 "timescale", "version", "vcdclose", "timezero",
104 "", "", "" };
105
106 #define NUM_TOKENS 19
107
108 static int T_MAX_STR=1024; /* was originally a const..now it reallocs */
109 static char *yytext=NULL;
110 static int yylen=0, yylen_cache=0;
111
112 #define T_GET tok=get_token();if((tok==T_END)||(tok==T_EOF))break;
113
114 /******************************************************************/
115
116 static struct vcdsymbol *vcdsymroot=NULL, *vcdsymcurr=NULL;
117 static struct vcdsymbol **sorted=NULL;
118 static struct vcdsymbol **indexed=NULL;
119
120 enum VarTypes { V_EVENT, V_PARAMETER,
121 V_INTEGER, V_REAL, V_REAL_PARAMETER=V_REAL, V_REALTIME=V_REAL, V_STRINGTYPE=V_REAL, V_REG, V_SUPPLY0,
122 V_SUPPLY1, V_TIME, V_TRI, V_TRIAND, V_TRIOR,
123 V_TRIREG, V_TRI0, V_TRI1, V_WAND, V_WIRE, V_WOR, V_PORT, V_IN=V_PORT, V_OUT=V_PORT, V_INOUT=V_PORT,
124 V_END, V_LB, V_COLON, V_RB, V_STRING };
125
126 static char *vartypes[]={ "event", "parameter",
127 "integer", "real", "real_parameter", "realtime", "string", "reg", "supply0",
128 "supply1", "time", "tri", "triand", "trior",
129 "trireg", "tri0", "tri1", "wand", "wire", "wor", "port", "in", "out", "inout",
130 "$end", "", "", "", ""};
131
132 static const unsigned char varenums[] = { V_EVENT, V_PARAMETER,
133 V_INTEGER, V_REAL, V_REAL_PARAMETER, V_REALTIME, V_STRINGTYPE, V_REG, V_SUPPLY0,
134 V_SUPPLY1, V_TIME, V_TRI, V_TRIAND, V_TRIOR,
135 V_TRIREG, V_TRI0, V_TRI1, V_WAND, V_WIRE, V_WOR, V_PORT, V_IN, V_OUT, V_INOUT,
136 V_END, V_LB, V_COLON, V_RB, V_STRING };
137
138 #define NUM_VTOKENS 25
139
140 static int numsyms=0;
141
142 /******************************************************************/
143
144 static struct queuedevent *queuedevents=NULL;
145
146 /******************************************************************/
147
148 static unsigned int vcd_minid = ~0;
149 static unsigned int vcd_maxid = 0;
150
vcdid_hash(char * s,int len)151 static unsigned int vcdid_hash(char *s, int len)
152 {
153 unsigned int val=0;
154 int i;
155
156 s+=(len-1);
157
158 for(i=0;i<len;i++)
159 {
160 val *= 94;
161 val += (((unsigned char)*s) - 32);
162 s--;
163 }
164
165 return(val);
166 }
167
168
169
170 /******************************************************************/
171
172 /*
173 * bsearch compare
174 */
vcdsymbsearchcompare(const void * s1,const void * s2)175 static int vcdsymbsearchcompare(const void *s1, const void *s2)
176 {
177 char *v1;
178 struct vcdsymbol *v2;
179
180 v1=(char *)s1;
181 v2=*((struct vcdsymbol **)s2);
182
183 return(strcmp(v1, v2->id));
184 }
185
186
187 /*
188 * actual bsearch
189 */
bsearch_vcd(char * key,int len)190 static struct vcdsymbol *bsearch_vcd(char *key, int len)
191 {
192 struct vcdsymbol **v;
193 struct vcdsymbol *t;
194
195 if(indexed)
196 {
197 unsigned int hsh = vcdid_hash(key, len);
198 if((hsh>=vcd_minid)&&(hsh<=vcd_maxid))
199 {
200 return(indexed[hsh-vcd_minid]);
201 }
202 }
203
204 v=(struct vcdsymbol **)bsearch(key, sorted, numsyms,
205 sizeof(struct vcdsymbol *), vcdsymbsearchcompare);
206
207 if(v)
208 {
209 #ifndef VCD_BSEARCH_IS_PERFECT
210 for(;;)
211 {
212 t=*v;
213
214 if((v==sorted)||(strcmp((*(--v))->id, key)))
215 {
216 return(t);
217 }
218 }
219 #else
220 return(*v);
221 #endif
222 }
223 else
224 {
225 return(NULL);
226 }
227 }
228
229
230 /*
231 * sort on vcdsymbol pointers
232 */
vcdsymcompare(const void * s1,const void * s2)233 static int vcdsymcompare(const void *s1, const void *s2)
234 {
235 struct vcdsymbol *v1, *v2;
236
237 v1=*((struct vcdsymbol **)s1);
238 v2=*((struct vcdsymbol **)s2);
239
240 return(strcmp(v1->id, v2->id));
241 }
242
243 /*
244 * alias vs normal symbol adding
245 */
alias_vs_normal_symadd(struct vcdsymbol * v,struct vcdsymbol * root_v)246 static void alias_vs_normal_symadd(struct vcdsymbol *v, struct vcdsymbol *root_v)
247 {
248 if(!v) return; /* scan-build : should never happen */
249
250 if(!root_v)
251 {
252 if((v->vartype==V_INTEGER)||(v->vartype==V_REAL))
253 {
254 v->ltsym = lxt2_wr_symbol_add(lt, v->name, 0, v->msi, v->lsi, (v->vartype==V_INTEGER)?LXT2_WR_SYM_F_INTEGER:((v->vartype==V_REAL)?LXT2_WR_SYM_F_DOUBLE:LXT2_WR_SYM_F_BITS));
255 }
256 else
257 {
258 char buf[65537];
259 if(v->msi==v->lsi)
260 {
261 sprintf(buf, "%s[%d]", v->name, v->msi);
262 }
263 else
264 {
265 sprintf(buf, "%s[%d:%d]", v->name, v->msi, v->lsi);
266 }
267 v->ltsym = lxt2_wr_symbol_add(lt, buf, 0, v->msi, v->lsi, (v->vartype==V_INTEGER)?LXT2_WR_SYM_F_INTEGER:((v->vartype==V_REAL)?LXT2_WR_SYM_F_DOUBLE:LXT2_WR_SYM_F_BITS));
268 }
269 }
270 else
271 {
272 if((v->vartype==V_INTEGER)||(v->vartype==V_REAL))
273 {
274 lxt2_wr_symbol_alias(lt, root_v->name, v->name, v->msi, v->lsi);
275 }
276 else
277 {
278 char bufold[65537], buf[65537];
279 if(v->msi==v->lsi)
280 {
281 sprintf(bufold, "%s[%d]", root_v->name, root_v->msi);
282 sprintf(buf, "%s[%d]", v->name, v->msi);
283 }
284 else
285 {
286 sprintf(bufold, "%s[%d:%d]", root_v->name, root_v->msi, root_v->lsi);
287 sprintf(buf, "%s[%d:%d]", v->name, v->msi, v->lsi);
288 }
289 lxt2_wr_symbol_alias(lt, bufold, buf, v->msi, v->lsi);
290 }
291 }
292 }
293
294 /*
295 * create sorted (by id) table
296 */
create_sorted_table(void)297 static void create_sorted_table(void)
298 {
299 struct vcdsymbol *v;
300 struct vcdsymbol **pnt;
301 unsigned int vcd_distance;
302 struct vcdsymbol *root_v;
303 int i;
304
305 if(numsyms)
306 {
307 vcd_distance = vcd_maxid - vcd_minid + 1;
308
309 if(vcd_distance <= 8 * 1024 * 1024)
310 {
311 indexed = (struct vcdsymbol **)calloc_2(vcd_distance, sizeof(struct vcdsymbol *));
312
313 printf("%d symbols span ID range of %d, using indexing...\n", numsyms, vcd_distance);
314
315 v=vcdsymroot;
316 while(v)
317 {
318 if(!(root_v=indexed[v->nid - vcd_minid]))
319 {
320 indexed[v->nid - vcd_minid] = v;
321 }
322 alias_vs_normal_symadd(v, root_v);
323
324 v=v->next;
325 }
326 }
327 else
328 {
329 pnt=sorted=(struct vcdsymbol **)calloc_2(numsyms, sizeof(struct vcdsymbol *));
330 v=vcdsymroot;
331 while(v)
332 {
333 *(pnt++)=v;
334 v=v->next;
335 }
336
337 qsort(sorted, numsyms, sizeof(struct vcdsymbol *), vcdsymcompare);
338
339 root_v = NULL;
340 for(i=0;i<numsyms;i++)
341 {
342 if(sorted[i] != root_v) root_v = NULL;
343 alias_vs_normal_symadd(sorted[i], root_v);
344 }
345 }
346
347 v=vcdsymroot;
348 while(v)
349 {
350 free(v->name); v->name = NULL;
351 v=v->next;
352 }
353 }
354 }
355
356 /******************************************************************/
357
358 /*
359 * single char get
360 */
getch(void)361 static int getch(void)
362 {
363 int ch;
364
365 ch=fgetc(vcd_handle);
366 if(ch=='\n') vcdlineno++;
367 return(((ch==EOF)||(errno))?(-1):(ch));
368 }
369
getch_peek(void)370 static int getch_peek(void)
371 {
372 int ch;
373
374 ch=fgetc(vcd_handle);
375 ungetc(ch, vcd_handle);
376 return(((ch==EOF)||(errno))?(-1):(ch));
377 }
378
379
380 static char *varsplit=NULL, *vsplitcurr=NULL;
getch_patched(void)381 static int getch_patched(void)
382 {
383 char ch;
384
385 ch=*vsplitcurr;
386 if(!ch)
387 {
388 return(-1);
389 }
390 else
391 {
392 vsplitcurr++;
393 return((int)ch);
394 }
395 }
396
397
398 /*
399 * simple tokenizer
400 */
get_token(void)401 static int get_token(void)
402 {
403 int ch;
404 int i, len=0;
405 int is_string=0;
406 char *yyshadow;
407
408 for(;;)
409 {
410 ch=getch();
411 if(ch<0) return(T_EOF);
412 if(ch<=' ') continue; /* val<=' ' is a quick whitespace check */
413 break; /* (take advantage of fact that vcd is text) */
414 }
415 if(ch=='$')
416 {
417 yytext[len++]=ch;
418 for(;;)
419 {
420 ch=getch();
421 if(ch<0) return(T_EOF);
422 if(ch<=' ') continue;
423 break;
424 }
425 }
426 else
427 {
428 is_string=1;
429 }
430
431 for(yytext[len++]=ch;;yytext[len++]=ch)
432 {
433 if(len==T_MAX_STR)
434 {
435 yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1);
436 }
437 ch=getch();
438 if(ch<=' ') break;
439 }
440 yytext[len]=0; /* terminator */
441
442 if(is_string)
443 {
444 yylen=len;
445 return(T_STRING);
446 }
447
448 yyshadow=yytext;
449 do
450 {
451 yyshadow++;
452 for(i=0;i<NUM_TOKENS;i++)
453 {
454 if(!strcmp(yyshadow,tokens[i]))
455 {
456 return(i);
457 }
458 }
459
460 } while(*yyshadow=='$'); /* fix for RCS ids in version strings */
461
462 return(T_UNKNOWN_KEY);
463 }
464
465 static int var_prevch=0;
get_vartoken_patched(int match_kw)466 static int get_vartoken_patched(int match_kw)
467 {
468 int ch;
469 int i, len=0;
470
471 if(!var_prevch)
472 {
473 for(;;)
474 {
475 ch=getch_patched();
476 if(ch<0) { free_2(varsplit); varsplit=NULL; return(V_END); }
477 if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')) continue;
478 break;
479 }
480 }
481 else
482 {
483 ch=var_prevch;
484 var_prevch=0;
485 }
486
487 if(ch=='[') return(V_LB);
488 if(ch==':') return(V_COLON);
489 if(ch==']') return(V_RB);
490
491 for(yytext[len++]=ch;;yytext[len++]=ch)
492 {
493 if(len==T_MAX_STR)
494 {
495 yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1);
496 }
497 ch=getch_patched();
498 if(ch<0) { free_2(varsplit); varsplit=NULL; break; }
499 if((ch==':')||(ch==']'))
500 {
501 var_prevch=ch;
502 break;
503 }
504 }
505 yytext[len]=0; /* terminator */
506
507 if(match_kw)
508 for(i=0;i<NUM_VTOKENS;i++)
509 {
510 if(!strcmp(yytext,vartypes[i]))
511 {
512 if(ch<0) { free_2(varsplit); varsplit=NULL; }
513 return(varenums[i]);
514 }
515 }
516
517 yylen=len;
518 if(ch<0) { free_2(varsplit); varsplit=NULL; }
519 return(V_STRING);
520 }
521
522
get_vartoken(int match_kw)523 static int get_vartoken(int match_kw)
524 {
525 int ch;
526 int i, len=0;
527
528 if(varsplit)
529 {
530 int rc=get_vartoken_patched(match_kw);
531 if(rc!=V_END) return(rc);
532 var_prevch=0;
533 }
534
535 if(!var_prevch)
536 {
537 for(;;)
538 {
539 ch=getch();
540 if(ch<0) return(V_END);
541 if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')) continue;
542 break;
543 }
544 }
545 else
546 {
547 ch=var_prevch;
548 var_prevch=0;
549 }
550
551 if(ch=='[') return(V_LB);
552 if(ch==':') return(V_COLON);
553 if(ch==']') return(V_RB);
554
555 if(ch=='#') /* for MTI System Verilog '$var reg 64 >w #implicit-var###VarElem:ram_di[0.0] [63:0] $end' style declarations */
556 { /* debussy simply escapes until the space */
557 yytext[len++]= '\\';
558 }
559
560 for(yytext[len++]=ch;;yytext[len++]=ch)
561 {
562 if(len==T_MAX_STR)
563 {
564 yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1);
565 }
566
567 ch=getch();
568 if(ch==' ')
569 {
570 if(match_kw) break;
571 if(getch_peek() == '[')
572 {
573 ch = getch();
574 varsplit=yytext+len; /* keep looping so we get the *last* one */
575 continue;
576 }
577 }
578
579 if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')||(ch<0)) break;
580 if((ch=='[')&&(yytext[0]!='\\'))
581 {
582 varsplit=yytext+len; /* keep looping so we get the *last* one */
583 }
584 else
585 if(((ch==':')||(ch==']'))&&(!varsplit)&&(yytext[0]!='\\'))
586 {
587 var_prevch=ch;
588 break;
589 }
590 }
591 yytext[len]=0; /* absolute terminator */
592 if((varsplit)&&(yytext[len-1]==']'))
593 {
594 char *vst;
595 vst=malloc_2(strlen(varsplit)+1);
596 strcpy(vst, varsplit);
597
598 *varsplit=0x00; /* zero out var name at the left bracket */
599 len=varsplit-yytext;
600
601 varsplit=vsplitcurr=vst;
602 var_prevch=0;
603 }
604 else
605 {
606 varsplit=NULL;
607 }
608
609 if(match_kw)
610 for(i=0;i<NUM_VTOKENS;i++)
611 {
612 if(!strcmp(yytext,vartypes[i]))
613 {
614 return(varenums[i]);
615 }
616 }
617
618 yylen=len;
619 return(V_STRING);
620 }
621
get_strtoken(void)622 static int get_strtoken(void)
623 {
624 int ch;
625 int len=0;
626
627 if(!var_prevch)
628 {
629 for(;;)
630 {
631 ch=getch();
632 if(ch<0) return(V_END);
633 if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')) continue;
634 break;
635 }
636 }
637 else
638 {
639 ch=var_prevch;
640 var_prevch=0;
641 }
642
643 for(yytext[len++]=ch;;yytext[len++]=ch)
644 {
645 if(len==T_MAX_STR)
646 {
647 yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1);
648 }
649 ch=getch();
650 if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')||(ch<0)) break;
651 }
652 yytext[len]=0; /* terminator */
653
654 yylen=len;
655 return(V_STRING);
656 }
657
sync_end(char * hdr)658 static void sync_end(char *hdr)
659 {
660 int tok;
661
662 if(hdr) { DEBUG(fprintf(stderr,"%s",hdr)); }
663 for(;;)
664 {
665 tok=get_token();
666 if((tok==T_END)||(tok==T_EOF)) break;
667 if(hdr) { DEBUG(fprintf(stderr," %s",yytext)); }
668 }
669 if(hdr) { DEBUG(fprintf(stderr,"\n")); }
670 }
671
build_slisthier(void)672 static char *build_slisthier(void)
673 {
674 struct slist *s;
675 int len=0;
676
677 if(!slistroot)
678 {
679 if(slisthier)
680 {
681 free_2(slisthier);
682 }
683
684 slisthier_len=0;
685 slisthier=(char *)malloc_2(1);
686 *slisthier=0;
687 return(slisthier);
688 }
689
690 s=slistroot; len=0;
691 while(s)
692 {
693 len+=s->len+(s->next?1:0);
694 s=s->next;
695 }
696
697 if(slisthier)
698 {
699 free_2(slisthier);
700 }
701
702 slisthier=(char *)malloc_2((slisthier_len=len)+1);
703 s=slistroot; len=0;
704 while(s)
705 {
706 strcpy(slisthier+len,s->str);
707 len+=s->len;
708 if(s->next)
709 {
710 strcpy(slisthier+len,vcd_hier_delimeter);
711 len++;
712 }
713 s=s->next;
714 }
715 return(slisthier);
716 }
717
718
append_vcd_slisthier(char * str)719 void append_vcd_slisthier(char *str)
720 {
721 struct slist *s;
722 s=(struct slist *)calloc_2(1,sizeof(struct slist));
723 s->len=strlen(str);
724 s->str=(char *)malloc_2(s->len+1);
725 strcpy(s->str,str);
726
727 if(slistcurr)
728 {
729 slistcurr->next=s;
730 slistcurr=s;
731 }
732 else
733 {
734 slistcurr=slistroot=s;
735 }
736
737 build_slisthier();
738 DEBUG(fprintf(stderr, "SCOPE: %s\n",slisthier));
739 }
740
741
parse_valuechange(void)742 static void parse_valuechange(void)
743 {
744 struct vcdsymbol *v;
745 char *vector;
746 int vlen;
747
748 switch(yytext[0])
749 {
750 case '0':
751 case '1':
752 case 'x': case 'X':
753 case 'z': case 'Z':
754 case 'h': case 'H':
755 case 'u': case 'U':
756 case 'w': case 'W':
757 case 'l': case 'L':
758 case '-':
759 if(yylen>1)
760 {
761 v=bsearch_vcd(yytext+1, yylen-1);
762 if(!v)
763 {
764 fprintf(stderr,"Near line %d, Unknown VCD identifier: '%s'\n",vcdlineno,yytext+1);
765 }
766 else
767 {
768 if(v->vartype!=V_EVENT)
769 {
770 char vl[2];
771 vl[0]=yytext[0]; vl[1]=0;
772 lxt2_wr_emit_value_bit_string(lt, v->ltsym, 0, vl);
773
774 v->value[0]=yytext[0];
775 DEBUG(fprintf(stderr,"%s = '%c'\n",v->name,v->value[0]));
776 add_histent(current_time,v->narray[0],v->value[0],1, NULL);
777 }
778 else
779 {
780 char vl[2];
781
782 v->value[0]=(dumping_off)?'x':'1'; /* only '1' is relevant */
783 if(current_time!=(v->ev->last_event_time+1))
784 {
785 /* dump degating event */
786 DEBUG(fprintf(stderr,"#"TTFormat" %s = '%c' (event)\n",v->ev->last_event_time+1,v->name,'0'));
787 add_histent(v->ev->last_event_time+1,v->narray[0],'0',1, NULL);
788 }
789 DEBUG(fprintf(stderr,"%s = '%c' (event)\n",v->name,v->value[0]));
790 add_histent(current_time,v->narray[0],v->value[0],1, NULL);
791
792 vl[0]='1'; vl[1]=0;
793 lxt2_wr_emit_value_bit_string(lt, v->ltsym, 0, vl);
794 vl[0]='0'; vl[1]=0;
795 lxt2_wr_emit_value_bit_string(lt, v->ltsym, 0, vl);
796
797 v->ev->last_event_time=current_time;
798 }
799 }
800 }
801 else
802 {
803 fprintf(stderr,"Near line %d, Malformed VCD identifier\n", vcdlineno);
804 }
805 break;
806
807 case 'b':
808 case 'B':
809 /* extract binary number then.. */
810 vector=malloc_2(yylen_cache=yylen);
811 strcpy(vector,yytext+1);
812 vlen=yylen-1;
813
814 get_strtoken();
815 v=bsearch_vcd(yytext, yylen);
816 if(!v)
817 {
818 fprintf(stderr,"Near line %d, Unknown identifier: '%s'\n",vcdlineno, yytext);
819 free_2(vector);
820 }
821 else
822 {
823 if(vlen<v->size) /* fill in left part */
824 {
825 char extend;
826 int i, fill;
827
828 extend=(vector[0]=='1')?'0':vector[0];
829
830 fill=v->size-vlen;
831 for(i=0;i<fill;i++)
832 {
833 v->value[i]=extend;
834 }
835 strcpy(v->value+fill,vector);
836 }
837 else if(vlen==v->size) /* straight copy */
838 {
839 strcpy(v->value,vector);
840 }
841 else /* too big, so copy only right half */
842 {
843 int skip;
844
845 skip=vlen-v->size;
846 strcpy(v->value,vector+skip);
847 }
848 DEBUG(fprintf(stderr,"%s = '%s'\n",v->name, v->value));
849 lxt2_wr_emit_value_bit_string(lt, v->ltsym, 0, v->value);
850
851 if((v->size==1)||(!atomic_vectors))
852 {
853 int i;
854 for(i=0;i<v->size;i++)
855 {
856 add_histent(current_time, v->narray[i],v->value[i],1, NULL);
857 }
858 free_2(vector);
859 }
860 else
861 {
862 if(yylen_cache!=(v->size+1))
863 {
864 free_2(vector);
865 vector=malloc_2(v->size+1);
866 }
867 strcpy(vector,v->value);
868 add_histent(current_time, v->narray[0],0,1,vector);
869 free_2(vector);
870 }
871
872 }
873
874 break;
875
876
877 case 'p':
878 /* extract port dump value.. */
879 vector=malloc_2(yylen_cache=yylen);
880 strcpy(vector,yytext+1);
881 vlen=yylen-1;
882
883 get_strtoken(); /* throw away 0_strength_component */
884 get_strtoken(); /* throw away 0_strength_component */
885 get_strtoken(); /* this is the id */
886 v=bsearch_vcd(yytext, yylen);
887 if(!v)
888 {
889 fprintf(stderr,"Near line %d, Unknown identifier: '%s'\n",vcdlineno, yytext);
890 free_2(vector);
891 }
892 else
893 {
894 if(vlen<v->size) /* fill in left part */
895 {
896 char extend;
897 int i, fill;
898
899 extend='0';
900
901 fill=v->size-vlen;
902 for(i=0;i<fill;i++)
903 {
904 v->value[i]=extend;
905 }
906 evcd_strcpy(v->value+fill,vector);
907 }
908 else if(vlen==v->size) /* straight copy */
909 {
910 evcd_strcpy(v->value,vector);
911 }
912 else /* too big, so copy only right half */
913 {
914 int skip;
915
916 skip=vlen-v->size;
917 evcd_strcpy(v->value,vector+skip);
918 }
919 DEBUG(fprintf(stderr,"%s = '%s'\n",v->name, v->value));
920 lxt2_wr_emit_value_bit_string(lt, v->ltsym, 0, v->value);
921
922 if((v->size==1)||(!atomic_vectors))
923 {
924 int i;
925 for(i=0;i<v->size;i++)
926 {
927 add_histent(current_time, v->narray[i],v->value[i],1, NULL);
928 }
929 free_2(vector);
930 }
931 else
932 {
933 if(yylen_cache<v->size)
934 {
935 free_2(vector);
936 vector=malloc_2(v->size+1);
937 }
938 strcpy(vector,v->value);
939 add_histent(current_time, v->narray[0],0,1,vector);
940 free_2(vector);
941 }
942 }
943 break;
944
945
946 case 'r':
947 case 'R':
948 {
949 double *d;
950
951 d=malloc_2(sizeof(double));
952 *d = 0;
953 sscanf(yytext+1,"%lg",d);
954 errno = 0;
955
956 get_strtoken();
957 v=bsearch_vcd(yytext, yylen);
958 if(!v)
959 {
960 fprintf(stderr,"Near line %d, Unknown identifier: '%s'\n",vcdlineno, yytext);
961 free_2(d);
962 }
963 else
964 {
965 lxt2_wr_emit_value_double(lt, v->ltsym, 0, *d);
966 add_histent(current_time, v->narray[0],'g',1,(char *)d);
967 free_2(d);
968 }
969
970 break;
971 }
972
973 case 's':
974 case 'S':
975 {
976 get_strtoken(); /* simply skip for now */
977 break;
978 }
979 }
980
981 }
982
983
evcd_strcpy(char * dst,char * src)984 static void evcd_strcpy(char *dst, char *src)
985 {
986 static const char *evcd="DUNZduLHXTlh01?FAaBbCcf";
987 static const char *vcd="01xz0101xz0101xzxxxxxxz";
988
989 char ch;
990 int i;
991
992 while((ch=*src))
993 {
994 for(i=0;i<23;i++)
995 {
996 if(evcd[i]==ch)
997 {
998 *dst=vcd[i];
999 break;
1000 }
1001 }
1002 if(i==23) *dst='x';
1003
1004 src++;
1005 dst++;
1006 }
1007
1008 *dst=0; /* null terminate destination */
1009 }
1010
1011
vcd_parse(void)1012 static void vcd_parse(void)
1013 {
1014 int tok;
1015
1016 for(;;)
1017 {
1018 switch(get_token())
1019 {
1020 case T_COMMENT:
1021 sync_end("COMMENT:");
1022 break;
1023 case T_DATE:
1024 sync_end("DATE:");
1025 break;
1026 case T_VERSION:
1027 sync_end("VERSION:");
1028 break;
1029 case T_TIMEZERO:
1030 {
1031 int vtok=get_token();
1032 if((vtok==T_END)||(vtok==T_EOF)) break;
1033 time_zero=atoi_64(yytext);
1034 lxt2_wr_set_timezero(lt, time_zero);
1035 sync_end(NULL);
1036 }
1037 break;
1038 case T_TIMESCALE:
1039 {
1040 int vtok;
1041 int i;
1042 char prefix=' ';
1043 int timelogadjust = 0;
1044
1045 vtok=get_token();
1046 if((vtok==T_END)||(vtok==T_EOF)) break;
1047 time_scale=atoi_64(yytext);
1048 if(!time_scale) time_scale=1;
1049 else if (time_scale == 10) timelogadjust = +1;
1050 else if (time_scale == 100) timelogadjust = +2;
1051 for(i=0;i<yylen;i++)
1052 {
1053 if((yytext[i]<'0')||(yytext[i]>'9'))
1054 {
1055 prefix=yytext[i];
1056 break;
1057 }
1058 }
1059 if(prefix==' ')
1060 {
1061 vtok=get_token();
1062 if((vtok==T_END)||(vtok==T_EOF)) break;
1063 prefix=yytext[0];
1064 }
1065 switch(prefix)
1066 {
1067 case 's':
1068 case ' ': lxt2_wr_set_timescale(lt, 0+timelogadjust); break;
1069 case 'm': lxt2_wr_set_timescale(lt, -3+timelogadjust); break;
1070 case 'u': lxt2_wr_set_timescale(lt, -6+timelogadjust); break;
1071 case 'n': lxt2_wr_set_timescale(lt, -9+timelogadjust); break;
1072 case 'p': lxt2_wr_set_timescale(lt, -12+timelogadjust); break;
1073 case 'f': lxt2_wr_set_timescale(lt, -15+timelogadjust); break;
1074 default: /* unknown */
1075 lxt2_wr_set_timescale(lt, -9+timelogadjust); break;
1076 }
1077
1078 sync_end(NULL);
1079 }
1080 break;
1081 case T_SCOPE:
1082 T_GET;
1083 T_GET;
1084 if(tok==T_STRING)
1085 {
1086 struct slist *s;
1087 s=(struct slist *)calloc_2(1,sizeof(struct slist));
1088 s->len=yylen;
1089 s->str=(char *)malloc_2(yylen+1);
1090 strcpy(s->str,yytext);
1091
1092 if(slistcurr)
1093 {
1094 slistcurr->next=s;
1095 slistcurr=s;
1096 }
1097 else
1098 {
1099 slistcurr=slistroot=s;
1100 }
1101
1102 build_slisthier();
1103 DEBUG(fprintf(stderr, "SCOPE: %s\n",slisthier));
1104 }
1105 sync_end(NULL);
1106 break;
1107 case T_UPSCOPE:
1108 if(slistroot)
1109 {
1110 struct slist *s;
1111
1112 s=slistroot;
1113 if(!s->next)
1114 {
1115 free_2(s->str);
1116 free_2(s);
1117 slistroot=slistcurr=NULL;
1118 }
1119 else
1120 for(;;)
1121 {
1122 if(!s->next->next)
1123 {
1124 free_2(s->next->str);
1125 free_2(s->next);
1126 s->next=NULL;
1127 slistcurr=s;
1128 break;
1129 }
1130 s=s->next;
1131 }
1132 build_slisthier();
1133 DEBUG(fprintf(stderr, "SCOPE: %s\n",slisthier));
1134 }
1135 sync_end(NULL);
1136 break;
1137 case T_VAR:
1138 {
1139 int vtok;
1140 struct vcdsymbol *v=NULL;
1141
1142 var_prevch=0;
1143 if(varsplit)
1144 {
1145 free_2(varsplit);
1146 varsplit=NULL;
1147 }
1148 vtok=get_vartoken(1);
1149 if(vtok>V_PORT) goto bail;
1150
1151 v=(struct vcdsymbol *)calloc_2(1,sizeof(struct vcdsymbol));
1152 v->vartype=vtok;
1153 v->msi=v->lsi=vcd_explicit_zero_subscripts; /* indicate [un]subscripted status */
1154
1155 if(vtok==V_PORT)
1156 {
1157 vtok=get_vartoken(1);
1158 if(vtok==V_STRING)
1159 {
1160 v->size=atoi_64(yytext);
1161 if(!v->size) v->size=1;
1162 }
1163 else
1164 if(vtok==V_LB)
1165 {
1166 vtok=get_vartoken(1);
1167 if(vtok==V_END) goto err;
1168 if(vtok!=V_STRING) goto err;
1169 v->msi=atoi_64(yytext);
1170 vtok=get_vartoken(0);
1171 if(vtok==V_RB)
1172 {
1173 v->lsi=v->msi;
1174 v->size=1;
1175 }
1176 else
1177 {
1178 if(vtok!=V_COLON) goto err;
1179 vtok=get_vartoken(0);
1180 if(vtok!=V_STRING) goto err;
1181 v->lsi=atoi_64(yytext);
1182 vtok=get_vartoken(0);
1183 if(vtok!=V_RB) goto err;
1184
1185 if(v->msi>v->lsi)
1186 {
1187 v->size=v->msi-v->lsi+1;
1188 }
1189 else
1190 {
1191 v->size=v->lsi-v->msi+1;
1192 }
1193 }
1194 }
1195 else goto err;
1196
1197 vtok=get_strtoken();
1198 if(vtok==V_END) goto err;
1199 v->id=(char *)malloc_2(yylen+1);
1200 strcpy(v->id, yytext);
1201 v->nid=vcdid_hash(yytext,yylen);
1202
1203 if(v->nid < vcd_minid) vcd_minid = v->nid;
1204 if(v->nid > vcd_maxid) vcd_maxid = v->nid;
1205
1206 vtok=get_vartoken(0);
1207 if(vtok!=V_STRING) goto err;
1208 if(slisthier_len)
1209 {
1210 v->name=(char *)malloc_2(slisthier_len+1+yylen+1);
1211 strcpy(v->name,slisthier);
1212 strcpy(v->name+slisthier_len,vcd_hier_delimeter);
1213 strcpy(v->name+slisthier_len+1,yytext);
1214 }
1215 else
1216 {
1217 v->name=(char *)malloc_2(yylen+1);
1218 strcpy(v->name,yytext);
1219 }
1220 }
1221 else /* regular vcd var, not an evcd port var */
1222 {
1223 vtok=get_vartoken(1);
1224 if(vtok==V_END) goto err;
1225 v->size=atoi_64(yytext);
1226 vtok=get_strtoken();
1227 if(vtok==V_END) goto err;
1228 v->id=(char *)malloc_2(yylen+1);
1229 strcpy(v->id, yytext);
1230 v->nid=vcdid_hash(yytext,yylen);
1231
1232 if(v->nid < vcd_minid) vcd_minid = v->nid;
1233 if(v->nid > vcd_maxid) vcd_maxid = v->nid;
1234
1235 vtok=get_vartoken(0);
1236 if(vtok!=V_STRING) goto err;
1237 if(slisthier_len)
1238 {
1239 v->name=(char *)malloc_2(slisthier_len+1+yylen+1);
1240 strcpy(v->name,slisthier);
1241 strcpy(v->name+slisthier_len,vcd_hier_delimeter);
1242 strcpy(v->name+slisthier_len+1,yytext);
1243 }
1244 else
1245 {
1246 v->name=(char *)malloc_2(yylen+1);
1247 strcpy(v->name,yytext);
1248 }
1249
1250 vtok=get_vartoken(1);
1251 if(vtok==V_END) goto dumpv;
1252 if(vtok!=V_LB) goto err;
1253 vtok=get_vartoken(0);
1254 if(vtok!=V_STRING) goto err;
1255 v->msi=atoi_64(yytext);
1256 vtok=get_vartoken(0);
1257 if(vtok==V_RB)
1258 {
1259 v->lsi=v->msi;
1260 goto dumpv;
1261 }
1262 if(vtok!=V_COLON) goto err;
1263 vtok=get_vartoken(0);
1264 if(vtok!=V_STRING) goto err;
1265 v->lsi=atoi_64(yytext);
1266 vtok=get_vartoken(0);
1267 if(vtok!=V_RB) goto err;
1268 }
1269
1270 dumpv:
1271 if(v->size == 0) { v->vartype = V_REAL; } /* MTI fix */
1272
1273 if(v->vartype==V_REAL)
1274 {
1275 v->size=1; /* override any data we parsed in */
1276 v->msi=v->lsi=0;
1277 }
1278 else
1279 if((v->size>1)&&(v->msi<=0)&&(v->lsi<=0))
1280 {
1281 if(v->vartype==V_EVENT)
1282 {
1283 v->size=1;
1284 }
1285 else
1286 {
1287 /* any criteria for the direction here? */
1288 v->msi=v->size-1;
1289 v->lsi=0;
1290 }
1291 }
1292 else
1293 if((v->msi>v->lsi)&&((v->msi-v->lsi+1)!=v->size))
1294 {
1295 if(v->vartype!=V_EVENT) goto err;
1296 v->size=v->msi-v->lsi+1;
1297 }
1298 else
1299 if((v->lsi>=v->msi)&&((v->lsi-v->msi+1)!=v->size))
1300 {
1301 if(v->vartype!=V_EVENT) goto err;
1302 v->size=v->msi-v->lsi+1;
1303 }
1304
1305 /* initial conditions */
1306 v->value=(char *)malloc_2(v->size+1);
1307 v->value[v->size]=0;
1308 v->narray=(struct Node **)calloc_2(v->size,sizeof(struct Node *));
1309 {
1310 int i;
1311 for(i=0;i<v->size;i++)
1312 {
1313 v->value[i]='x';
1314
1315 v->narray[i]=(struct Node *)calloc_2(1,sizeof(struct Node));
1316 v->narray[i]->head.time=-1;
1317 v->narray[i]->head.v.val=1;
1318 }
1319 }
1320
1321 if(v->vartype==V_EVENT)
1322 {
1323 struct queuedevent *q;
1324 v->ev=q=(struct queuedevent *)calloc_2(1,sizeof(struct queuedevent));
1325 q->sym=v;
1326 q->last_event_time=-1;
1327 q->next=queuedevents;
1328 queuedevents=q;
1329 }
1330
1331 if(!vcdsymroot)
1332 {
1333 vcdsymroot=vcdsymcurr=v;
1334 }
1335 else
1336 {
1337 vcdsymcurr->next=v;
1338 vcdsymcurr=v;
1339 }
1340 numsyms++;
1341
1342 #if 0
1343 if((v->vartype==V_INTEGER)||(v->vartype==V_REAL))
1344 {
1345 v->ltsym = lxt2_wr_symbol_add(lt, v->name, 0, v->msi, v->lsi, (v->vartype==V_INTEGER)?LXT2_WR_SYM_F_INTEGER:((v->vartype==V_REAL)?LXT2_WR_SYM_F_DOUBLE:LXT2_WR_SYM_F_BITS));
1346 }
1347 else
1348 {
1349 char buf[65537];
1350 if(v->msi==v->lsi)
1351 {
1352 sprintf(buf, "%s[%d]", v->name, v->msi);
1353 }
1354 else
1355 {
1356 sprintf(buf, "%s[%d:%d]", v->name, v->msi, v->lsi);
1357 }
1358 v->ltsym = lxt2_wr_symbol_add(lt, buf, 0, v->msi, v->lsi, (v->vartype==V_INTEGER)?LXT2_WR_SYM_F_INTEGER:((v->vartype==V_REAL)?LXT2_WR_SYM_F_DOUBLE:LXT2_WR_SYM_F_BITS));
1359 }
1360 #endif
1361
1362 DEBUG(fprintf(stderr,"VAR %s %d %s %s[%d:%d]\n",
1363 vartypes[v->vartype], v->size, v->id, v->name,
1364 v->msi, v->lsi));
1365 goto bail;
1366 err:
1367 if(v)
1368 {
1369 if(v->name) free_2(v->name);
1370 if(v->id) free_2(v->id);
1371 if(v->value) free_2(v->value);
1372 free_2(v);
1373 }
1374
1375 bail:
1376 if(vtok!=V_END) sync_end(NULL);
1377 break;
1378 }
1379 case T_ENDDEFINITIONS:
1380 if(!header_over)
1381 {
1382 header_over=1; /* do symbol table management here */
1383 create_sorted_table();
1384 if((!sorted)&&(!indexed))
1385 {
1386 fprintf(stderr, "No symbols in VCD file..nothing to do!\n");
1387 exit(1);
1388 }
1389 }
1390 break;
1391 case T_STRING:
1392 if(header_over)
1393 {
1394 /* catchall for events when header over */
1395 if(yytext[0]=='#')
1396 {
1397 TimeType t_time;
1398 t_time=atoi_64(yytext+1);
1399
1400 if(start_time<0)
1401 {
1402 start_time=t_time;
1403 }
1404
1405 if(t_time < current_time) /* avoid backtracking time counts which can happen on malformed files */
1406 {
1407 t_time = current_time;
1408 }
1409
1410 current_time=t_time;
1411 if(end_time<t_time) end_time=t_time; /* in case of malformed vcd files */
1412
1413 lxt2_wr_set_time64(lt, current_time);
1414 DEBUG(fprintf(stderr,"#"TTFormat"\n",t_time));
1415 }
1416 else
1417 {
1418 parse_valuechange();
1419 }
1420 }
1421 break;
1422 case T_DUMPALL: /* dump commands modify vals anyway so */
1423 case T_DUMPPORTSALL:
1424 break; /* just loop through.. */
1425 case T_DUMPOFF:
1426 case T_DUMPPORTSOFF:
1427 dumping_off=1;
1428 lxt2_wr_set_dumpoff(lt);
1429 break;
1430 case T_DUMPON:
1431 case T_DUMPPORTSON:
1432 dumping_off=0;
1433 lxt2_wr_set_dumpon(lt);
1434 break;
1435 case T_DUMPVARS:
1436 case T_DUMPPORTS:
1437 if(current_time<0)
1438 { start_time=current_time=end_time=0; /* lxt2_wr_set_time(lt, current_time); */ }
1439 break;
1440 case T_VCDCLOSE:
1441 sync_end("VCDCLOSE:");
1442 break; /* next token will be '#' time related followed by $end */
1443 case T_END: /* either closure for dump commands or */
1444 break; /* it's spurious */
1445 case T_UNKNOWN_KEY:
1446 sync_end(NULL); /* skip over unknown keywords */
1447 break;
1448 case T_EOF:
1449 return;
1450 default:
1451 DEBUG(fprintf(stderr,"UNKNOWN TOKEN\n"));
1452 }
1453 }
1454 }
1455
1456
1457 /*******************************************************************************/
1458
1459 /*
1460 * this function doesn't do anything useful anymore except for to mark
1461 * statistics on the various nets...
1462 */
add_histent(TimeType t_time,struct Node * n,char ch,int regadd,char * vector)1463 void add_histent(TimeType t_time, struct Node *n, char ch, int regadd, char *vector)
1464 {
1465 struct HistEnt *he;
1466
1467 if(!vector)
1468 {
1469 if(!n->curr)
1470 {
1471 he=(struct HistEnt *)calloc_2(1,sizeof(struct HistEnt));
1472 he->time=-1;
1473 he->v.val=1;
1474
1475 n->curr=he;
1476 n->head.next=he;
1477
1478 add_histent(t_time,n,ch,regadd, vector);
1479 }
1480 else
1481 {
1482 /* if(regadd) { t_time*=(time_scale); } */ /* scan-build : never read */
1483
1484 if(toupper((int)(unsigned char)ch)!=deadchar) n->notdead=1;
1485 n->numtrans++;
1486 }
1487 }
1488 else
1489 {
1490 if(ch=='g') /* real number */
1491 {
1492 if(!n->curr)
1493 {
1494 he=(struct HistEnt *)calloc_2(1,sizeof(struct HistEnt));
1495 he->time=-1;
1496 he->v.vector=NULL;
1497
1498 n->curr=he;
1499 n->head.next=he;
1500
1501 add_histent(t_time,n,ch,regadd, vector);
1502 }
1503 else
1504 {
1505 n->notdead=1;
1506 n->numtrans++;
1507 }
1508 }
1509 else
1510 {
1511 if(!n->curr)
1512 {
1513 he=(struct HistEnt *)calloc_2(1,sizeof(struct HistEnt));
1514 he->time=-1;
1515 he->v.vector=NULL;
1516
1517 n->curr=he;
1518 n->head.next=he;
1519
1520 add_histent(t_time,n,ch,regadd, vector);
1521 }
1522 else
1523 {
1524 int i, nlen;
1525
1526 nlen = strlen(vector);
1527 if(nlen)
1528 {
1529 n->numtrans++;
1530 for(i=0;i<nlen;i++)
1531 {
1532 if(toupper((int)(unsigned char)vector[i])!=deadchar)
1533 {
1534 n->notdead=1;
1535 return;
1536 }
1537 }
1538 }
1539 }
1540 }
1541 }
1542
1543 }
1544
1545
add_tail_histents(void)1546 static void add_tail_histents(void)
1547 {
1548 /* dump out any pending events 1st */
1549 struct queuedevent *q;
1550 q=queuedevents;
1551 while(q)
1552 {
1553 struct vcdsymbol *v;
1554
1555 v=q->sym;
1556 if(current_time!=(v->ev->last_event_time+1))
1557 {
1558 /* dump degating event */
1559 DEBUG(fprintf(stderr,"#"TTFormat" %s = '%c' (event)\n",v->ev->last_event_time+1,v->name,'0'));
1560 add_histent(v->ev->last_event_time+1,v->narray[0],'0',1, NULL);
1561 }
1562 q=q->next;
1563 }
1564 }
1565
1566 /*******************************************************************************/
1567
vcd_main(char * fname,char * lxname)1568 TimeType vcd_main(char *fname, char *lxname)
1569 {
1570 #ifdef ONLY_NEEDED_FOR_VALGRIND_CLEAN_TEST
1571 struct vcdsymbol *v, *v2;
1572 #endif
1573
1574 vcd_hier_delimeter[0]=hier_delimeter;
1575
1576 errno=0; /* reset in case it's set for some reason */
1577
1578 yytext=(char *)malloc_2(T_MAX_STR+1);
1579
1580 if((strlen(fname)>2)&&(!strcmp(fname+strlen(fname)-3,".gz")))
1581 {
1582 char *str;
1583 int dlen;
1584 dlen=strlen(WAVE_DECOMPRESSOR);
1585 str=(char *)wave_alloca(strlen(fname)+dlen+1);
1586 strcpy(str,WAVE_DECOMPRESSOR);
1587 strcpy(str+dlen,fname);
1588 vcd_handle=popen(str,"r");
1589 vcd_is_compressed=~0;
1590 }
1591 else
1592 {
1593 if(strcmp("-",fname))
1594 {
1595 vcd_handle=fopen(fname,"rb");
1596 }
1597 else
1598 {
1599 vcd_handle=stdin;
1600 }
1601 vcd_is_compressed=0;
1602 }
1603
1604 if(!vcd_handle)
1605 {
1606 fprintf(stderr, "Error opening %s .vcd file '%s'.\n",
1607 vcd_is_compressed?"compressed":"", fname);
1608 exit(1);
1609 }
1610
1611 lt=lxt2_wr_init(lxname);
1612 if(!lt)
1613 {
1614 fprintf(stderr, "Problem opening output file '%s'\n", lxname);
1615 perror("Why");
1616 exit(255);
1617 }
1618
1619 if(opt_partial_mode>=0)
1620 {
1621 lxt2_wr_set_partial_on(lt, opt_partial_mode);
1622 }
1623
1624 if((opt_checkpoint_disable)&&(!opt_break_size))
1625 {
1626 lxt2_wr_set_checkpoint_off(lt);
1627 }
1628
1629 lxt2_wr_set_compression_depth(lt, opt_depth);
1630 lxt2_wr_set_break_size(lt, (off_t)opt_break_size);
1631 lxt2_wr_set_maxgranule(lt, opt_maxgranule);
1632 lxt2_wr_symbol_bracket_stripping(lt, 1); /* this is intentional */
1633
1634 sym=(struct symbol **)calloc_2(SYMPRIME,sizeof(struct symbol *));
1635 printf("\nConverting VCD File '%s' to LXT2 file '%s'...\n\n",(vcd_handle!=stdin)?fname:"from stdin", lxname);
1636 build_slisthier();
1637 vcd_parse();
1638 if(varsplit)
1639 {
1640 free_2(varsplit);
1641 varsplit=NULL;
1642 }
1643
1644 add_tail_histents();
1645
1646 printf("["TTFormat"] start time.\n["TTFormat"] end time.\n\n", start_time, end_time);
1647
1648 lxt2_wr_close(lt);
1649 lt=NULL;
1650
1651 min_time=start_time*time_scale;
1652 max_time=end_time*time_scale;
1653
1654 if((min_time==max_time)||(max_time==0))
1655 {
1656 fprintf(stderr, "VCD times range is equal to zero. Exiting.\n");
1657 exit(1);
1658 }
1659
1660 if(vcd_handle!=stdin)
1661 {
1662 fclose(vcd_handle);
1663 vcd_handle=NULL;
1664 }
1665
1666 free(yytext); yytext=NULL;
1667 if(indexed) { free(indexed); indexed=NULL; }
1668 if(sorted) { free(sorted); sorted=NULL; }
1669
1670 #ifdef ONLY_NEEDED_FOR_VALGRIND_CLEAN_TEST
1671 v=vcdsymroot;
1672 while(v)
1673 {
1674 if(v->name) { free(v->name); v->name=NULL; }
1675 if(v->id) { free(v->id); v->id=NULL; }
1676 if(v->value) { free(v->value); v->value=NULL; }
1677
1678 if(v->narray)
1679 {
1680 int i;
1681 for(i=0;i<v->size;i++)
1682 {
1683 struct HistEnt *h1, *h2;
1684
1685 if((h1 = v->narray[i]->head.next))
1686 {
1687 h1 = v->narray[i]->head.next;
1688 while(h1)
1689 {
1690 h2 = h1->next;
1691 free(h1);
1692 h1 = h2;
1693 }
1694 }
1695
1696 free(v->narray[i]); v->narray[i]=NULL;
1697 }
1698
1699 free(v->narray); v->narray=NULL;
1700 }
1701
1702 v2=v->next;
1703 free(v);
1704 v=v2;
1705 }
1706 vcdsymroot=vcdsymcurr=NULL;
1707 #endif
1708
1709 free(sym); sym=NULL;
1710
1711 if(slisthier) { free(slisthier); slisthier=NULL; }
1712
1713 return(max_time);
1714 }
1715
1716 /*******************************************************************************/
1717
1718 /*
1719 * Generic hash function for symbol names...
1720 */
hash(char * s)1721 int hash(char *s)
1722 {
1723 char *p;
1724 unsigned int h=0, g;
1725 for(p=s;*p;p++)
1726 {
1727 h=(h<<4)+(*p);
1728 if((g=h&0xf0000000))
1729 {
1730 h=h^(g>>24);
1731 h=h^g;
1732 }
1733 }
1734 return(h%SYMPRIME);
1735 }
1736
1737 /*
1738 * add symbol to table. no duplicate checking
1739 * is necessary as aet's are "correct."
1740 */
symadd(char * name,int hv)1741 struct symbol *symadd(char *name, int hv)
1742 {
1743 struct symbol *s;
1744
1745 s=(struct symbol *)calloc_2(1,sizeof(struct symbol));
1746 strcpy(s->name=(char *)malloc_2(strlen(name)+1),name);
1747 s->next=sym[hv];
1748 sym[hv]=s;
1749 return(s);
1750 }
1751
1752 /*
1753 * find a slot already in the table...
1754 */
symfind(char * s)1755 struct symbol *symfind(char *s)
1756 {
1757 int hv;
1758 struct symbol *temp;
1759
1760 hv=hash(s);
1761 if(!(temp=sym[hv])) return(NULL); /* no hash entry, add here wanted to add */
1762
1763 while(temp)
1764 {
1765 if(!strcmp(temp->name,s))
1766 {
1767 return(temp); /* in table already */
1768 }
1769 if(!temp->next) break;
1770 temp=temp->next;
1771 }
1772
1773 return(NULL); /* not found, add here if you want to add*/
1774 }
1775
sigcmp(char * s1,char * s2)1776 int sigcmp(char *s1, char *s2)
1777 {
1778 unsigned char c1, c2;
1779 int u1, u2;
1780
1781 for(;;)
1782 {
1783 c1=(unsigned char)*(s1++);
1784 c2=(unsigned char)*(s2++);
1785
1786 if((!c1)&&(!c2)) return(0);
1787 if((c1<='9')&&(c2<='9')&&(c2>='0')&&(c1>='0'))
1788 {
1789 u1=(int)(c1&15);
1790 u2=(int)(c2&15);
1791
1792 while(((c2=(unsigned char)*s2)>='0')&&(c2<='9'))
1793 {
1794 u2*=10;
1795 u2+=(unsigned int)(c2&15);
1796 s2++;
1797 }
1798
1799 while(((c2=(unsigned char)*s1)>='0')&&(c2<='9'))
1800 {
1801 u1*=10;
1802 u1+=(unsigned int)(c2&15);
1803 s1++;
1804 }
1805
1806 if(u1==u2) continue;
1807 else return((int)u1-(int)u2);
1808 }
1809 else
1810 {
1811 if(c1!=c2) return((int)c1-(int)c2);
1812 }
1813 }
1814 }
1815
1816
partition(struct symbol ** a,int p,int r)1817 int partition(struct symbol **a, int p, int r)
1818 {
1819 struct symbol *x, *t;
1820 int i,j;
1821
1822 x=a[p];
1823 i=p-1;
1824 j=r+1;
1825
1826 while(1)
1827 {
1828 do
1829 {
1830 j--;
1831 } while(sigcmp(a[j]->name,x->name)>0);
1832
1833 do {
1834 i++;
1835 } while(sigcmp(a[i]->name,x->name)<0);
1836
1837 if(i<j)
1838 {
1839 t=a[i];
1840 a[i]=a[j];
1841 a[j]=t;
1842 }
1843 else
1844 {
1845 return(j);
1846 }
1847 }
1848 }
1849
quicksort(struct symbol ** a,int p,int r)1850 void quicksort(struct symbol **a, int p, int r)
1851 {
1852 int q;
1853
1854 if(p<r)
1855 {
1856 q=partition(a,p,r);
1857 quicksort(a,p,q);
1858 quicksort(a,q+1,r);
1859 }
1860 }
1861
1862
1863 /*******************************************************************************/
1864
print_help(char * nam)1865 void print_help(char *nam)
1866 {
1867 #ifdef __linux__
1868 printf(
1869 "Usage: %s [OPTION]... [VCDFILE] [LXT2FILE]\n\n"
1870 " -v, --vcdname=FILE specify VCD input filename\n"
1871 " -l, --lxtname=FILE specify LXT2 output filename\n"
1872 " -d, --depth=value specify 0..9 compression depth (default = 4)\n"
1873 " -m, --maxgranule=value specify number of granules per section (def = 8)\n"
1874 " -b, --break=value specify break size (default = 0 = off)\n"
1875 " -p, --partialmode=mode specify partial zip mode 0=monolithic/1=separate\n"
1876 " -c, --checkpoint=mode specify checkpoint mode (0 = on [def], 1 = off)\n"
1877 " -h, --help display this help then exit\n\n"
1878
1879 "VCD files may be compressed with zip or gzip. Note that VCDFILE and LXTFILE\n"
1880 "are optional provided the --vcdname and --lxtname options are specified.\n"
1881 "Use \"-\" as a VCD filename to accept uncompressed input from stdin.\n\n"
1882 "Report bugs to <"PACKAGE_BUGREPORT">.\n",nam);
1883 #else
1884 printf(
1885 "Usage: %s [OPTION]... [VCDFILE] [LXT2FILE]\n\n"
1886 " -v FILE specify VCD input filename\n"
1887 " -l FILE specify LXT2 output filename\n"
1888 " -d value specify 0..9 compression depth (default = 4)\n"
1889 " -m value specify number of granules per section (def = 8)\n"
1890 " -b value specify break size (default = 0 = off)\n"
1891 " -p mode specify partial zip mode 0=monolithic/1=separate\n"
1892 " -c mode specify checkpoint mode (0 = on [def], 1 = off)\n"
1893 " -h display this help then exit\n\n"
1894
1895 "VCD files may be compressed with zip or gzip. Note that VCDFILE and LXTFILE\n"
1896 "are optional provided the --vcdname and --lxtname options are specified.\n"
1897 "Use \"-\" as a VCD filename to accept uncompressed input from stdin.\n\n"
1898 "Report bugs to <"PACKAGE_BUGREPORT">.\n",nam);
1899 #endif
1900
1901 exit(0);
1902 }
1903
1904
main(int argc,char ** argv)1905 int main(int argc, char **argv)
1906 {
1907 char opt_errors_encountered=0;
1908 char *vname=NULL, *lxname=NULL;
1909 int c;
1910
1911 WAVE_LOCALE_FIX
1912
1913 while (1)
1914 {
1915 #ifdef __linux__
1916 int option_index = 0;
1917
1918 static struct option long_options[] =
1919 {
1920 {"vcdname", 1, 0, 'v'},
1921 {"lxtname", 1, 0, 'l'},
1922 {"depth", 1, 0, 'd'},
1923 {"maxgranule", 1, 0, 'm'},
1924 {"break", 1, 0, 'b'},
1925 {"partialmode", 1, 0, 'p'},
1926 {"checkpoint", 1, 0, 'c'},
1927 {"help", 0, 0, 'h'},
1928 {0, 0, 0, 0}
1929 };
1930
1931 c = getopt_long (argc, argv, "v:l:d:m:b:p:c:h", long_options, &option_index);
1932 #else
1933 c = getopt (argc, argv, "v:l:d:m:b:p:c:h");
1934 #endif
1935
1936 if (c == -1) break; /* no more args */
1937
1938 switch (c)
1939 {
1940 case 'v':
1941 if(vname) free(vname);
1942 vname = malloc_2(strlen(optarg)+1);
1943 strcpy(vname, optarg);
1944 break;
1945
1946 case 'l':
1947 if(lxname) free(lxname);
1948 lxname = malloc_2(strlen(optarg)+1);
1949 strcpy(lxname, optarg);
1950 break;
1951
1952 case 'd':
1953 opt_depth = atoi(optarg);
1954 if(opt_depth<0) opt_depth = 0;
1955 if(opt_depth>9) opt_depth = 9;
1956 break;
1957
1958 case 'm':
1959 opt_maxgranule = atoi(optarg);
1960 if(opt_maxgranule<1) opt_maxgranule=1;
1961 break;
1962
1963 case 'b':
1964 sscanf(optarg, "%"SCNu64, &opt_break_size);
1965 errno = 0;
1966 break;
1967
1968 case 'p':
1969 opt_partial_mode = atoi(optarg);
1970 if(opt_depth<0) opt_partial_mode = 0;
1971 if(opt_depth>1) opt_partial_mode = 1;
1972 break;
1973
1974 case 'c':
1975 opt_checkpoint_disable = atoi(optarg);
1976 break;
1977
1978 case 'h':
1979 print_help(argv[0]);
1980 break;
1981
1982 case '?':
1983 opt_errors_encountered=1;
1984 break;
1985
1986 default:
1987 /* unreachable */
1988 break;
1989 }
1990 }
1991
1992 if(opt_errors_encountered)
1993 {
1994 print_help(argv[0]);
1995 }
1996
1997 if (optind < argc)
1998 {
1999 while (optind < argc)
2000 {
2001 if(!vname)
2002 {
2003 vname = malloc_2(strlen(argv[optind])+1);
2004 strcpy(vname, argv[optind++]);
2005 }
2006 else if(!lxname)
2007 {
2008 lxname = malloc_2(strlen(argv[optind])+1);
2009 strcpy(lxname, argv[optind++]);
2010 }
2011 else
2012 {
2013 break;
2014 }
2015 }
2016 }
2017
2018 if((!vname)||(!lxname))
2019 {
2020 print_help(argv[0]);
2021 }
2022
2023 vcd_main(vname, lxname);
2024
2025 free(vname); free(lxname);
2026
2027 return(0);
2028 }
2029
2030