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