Fix for assertion error when expanding macro.
[iverilog.git] / vpi / lxt2_write.c
blob94dff12b2358de834a2d89d210645e0d00fe2f7d
1 /*
2 * Copyright (c) 2003-2004 Tony Bybell.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 #include "lxt2_write.h"
26 static char *lxt2_wr_vcd_truncate_bitvec(char *s)
28 char l, r;
30 r=*s;
31 if(r=='1')
33 return s;
35 else
37 s++;
40 for(;;s++)
42 l=r; r=*s;
43 if(!r) return (s-1);
45 if(l!=r)
47 return(((l=='0')&&(r=='1'))?s:s-1);
53 /************************ splay ************************/
55 static lxt2_wr_ds_Tree * lxt2_wr_ds_splay (granmsk_t i, lxt2_wr_ds_Tree * t) {
56 /* Simple top down splay, not requiring i to be in the tree t. */
57 /* What it does is described above. */
58 lxt2_wr_ds_Tree N, *l, *r, *y;
59 if (t == NULL) return t;
60 N.left = N.right = NULL;
61 l = r = &N;
63 for (;;) {
64 if (i < t->item) {
65 if (t->left == NULL) break;
66 if (i < t->left->item) {
67 y = t->left; /* rotate right */
68 t->left = y->right;
69 y->right = t;
70 t = y;
71 if (t->left == NULL) break;
73 r->left = t; /* link right */
74 r = t;
75 t = t->left;
76 } else if (i > t->item) {
77 if (t->right == NULL) break;
78 if (i > t->right->item) {
79 y = t->right; /* rotate left */
80 t->right = y->left;
81 y->left = t;
82 t = y;
83 if (t->right == NULL) break;
85 l->right = t; /* link left */
86 l = t;
87 t = t->right;
88 } else {
89 break;
92 l->right = t->left; /* assemble */
93 r->left = t->right;
94 t->left = N.right;
95 t->right = N.left;
96 return t;
100 static lxt2_wr_ds_Tree * lxt2_wr_ds_insert(granmsk_t i, lxt2_wr_ds_Tree * t, int val) {
101 /* Insert i into the tree t, unless it's already there. */
102 /* Return a pointer to the resulting tree. */
103 lxt2_wr_ds_Tree * n;
105 n = (lxt2_wr_ds_Tree *) calloc (1, sizeof (lxt2_wr_ds_Tree));
106 if (n == NULL) {
107 fprintf(stderr, "ds_insert: ran out of memory, exiting.\n");
108 exit(255);
110 n->item = i;
111 n->val = val;
112 if (t == NULL) {
113 n->left = n->right = NULL;
114 return n;
116 t = lxt2_wr_ds_splay(i,t);
117 if (i < t->item) {
118 n->left = t->left;
119 n->right = t;
120 t->left = NULL;
121 return n;
122 } else if (i > t->item) {
123 n->right = t->right;
124 n->left = t;
125 t->right = NULL;
126 return n;
127 } else { /* We get here if it's already in the tree */
128 /* Don't add it again */
129 free(n);
130 return t;
134 /************************ splay ************************/
136 static int lxt2_wr_dslxt_success;
138 static lxt2_wr_dslxt_Tree * lxt2_wr_dslxt_splay (char *i, lxt2_wr_dslxt_Tree * t) {
139 /* Simple top down splay, not requiring i to be in the tree t. */
140 /* What it does is described above. */
141 lxt2_wr_dslxt_Tree N, *l, *r, *y;
142 int dir;
144 lxt2_wr_dslxt_success = 0;
146 if (t == NULL) return t;
147 N.left = N.right = NULL;
148 l = r = &N;
150 for (;;) {
151 dir = strcmp(i, t->item);
152 if (dir < 0) {
153 if (t->left == NULL) break;
154 if (strcmp(i, t->left->item)<0) {
155 y = t->left; /* rotate right */
156 t->left = y->right;
157 y->right = t;
158 t = y;
159 if (t->left == NULL) break;
161 r->left = t; /* link right */
162 r = t;
163 t = t->left;
164 } else if (dir > 0) {
165 if (t->right == NULL) break;
166 if (strcmp(i, t->right->item)>0) {
167 y = t->right; /* rotate left */
168 t->right = y->left;
169 y->left = t;
170 t = y;
171 if (t->right == NULL) break;
173 l->right = t; /* link left */
174 l = t;
175 t = t->right;
176 } else {
177 lxt2_wr_dslxt_success=1;
178 break;
181 l->right = t->left; /* assemble */
182 r->left = t->right;
183 t->left = N.right;
184 t->right = N.left;
185 return t;
189 static lxt2_wr_dslxt_Tree * lxt2_wr_dslxt_insert(char *i, lxt2_wr_dslxt_Tree * t, unsigned int val) {
190 /* Insert i into the tree t, unless it's already there. */
191 /* Return a pointer to the resulting tree. */
192 lxt2_wr_dslxt_Tree * n;
193 int dir;
195 n = (lxt2_wr_dslxt_Tree *) calloc (1, sizeof (lxt2_wr_dslxt_Tree));
196 if (n == NULL) {
197 fprintf(stderr, "dslxt_insert: ran out of memory, exiting.\n");
198 exit(255);
200 n->item = i;
201 n->val = val;
202 if (t == NULL) {
203 n->left = n->right = NULL;
204 return n;
206 t = lxt2_wr_dslxt_splay(i,t);
207 dir = strcmp(i,t->item);
208 if (dir<0) {
209 n->left = t->left;
210 n->right = t;
211 t->left = NULL;
212 return n;
213 } else if (dir>0) {
214 n->right = t->right;
215 n->left = t;
216 t->right = NULL;
217 return n;
218 } else { /* We get here if it's already in the tree */
219 /* Don't add it again */
220 free(n);
221 return t;
225 /************************ splay ************************/
228 * functions which emit various big endian
229 * data to a file
231 static int lxt2_wr_emit_u8(struct lxt2_wr_trace *lt, int value)
233 unsigned char buf[1];
234 int nmemb;
236 buf[0] = value & 0xff;
237 nmemb=fwrite(buf, sizeof(char), 1, lt->handle);
238 lt->position+=nmemb;
239 return(nmemb);
243 static int lxt2_wr_emit_u16(struct lxt2_wr_trace *lt, int value)
245 unsigned char buf[2];
246 int nmemb;
248 buf[0] = (value>>8) & 0xff;
249 buf[1] = value & 0xff;
250 nmemb = fwrite(buf, sizeof(char), 2, lt->handle);
251 lt->position+=nmemb;
252 return(nmemb);
256 static int lxt2_wr_emit_u32(struct lxt2_wr_trace *lt, int value)
258 unsigned char buf[4];
259 int nmemb;
261 buf[0] = (value>>24) & 0xff;
262 buf[1] = (value>>16) & 0xff;
263 buf[2] = (value>>8) & 0xff;
264 buf[3] = value & 0xff;
265 nmemb=fwrite(buf, sizeof(char), 4, lt->handle);
266 lt->position+=nmemb;
267 return(nmemb);
271 static int lxt2_wr_emit_u64(struct lxt2_wr_trace *lt, int valueh, int valuel)
273 int rc;
275 if((rc=lxt2_wr_emit_u32(lt, valueh)))
277 rc=lxt2_wr_emit_u32(lt, valuel);
280 return(rc);
285 * gzfunctions which emit various big endian
286 * data to a file. (lt->position needs to be
287 * fixed up on gzclose so the tables don't
288 * get out of sync!)
290 static int gzwrite_buffered(struct lxt2_wr_trace *lt)
292 int rc = 1;
294 if(lt->gzbufpnt > LXT2_WR_GZWRITE_BUFFER)
296 rc = gzwrite(lt->zhandle, lt->gzdest, lt->gzbufpnt);
297 rc = rc ? 1 : 0;
298 lt->gzbufpnt = 0;
301 return(rc);
304 static void gzflush_buffered(struct lxt2_wr_trace *lt, int doclose)
306 if(lt->gzbufpnt)
308 gzwrite(lt->zhandle, lt->gzdest, lt->gzbufpnt);
309 lt->gzbufpnt = 0;
310 if(!doclose)
312 gzflush(lt->zhandle, Z_SYNC_FLUSH);
316 if(doclose)
318 gzclose(lt->zhandle);
323 static int lxt2_wr_emit_u8z(struct lxt2_wr_trace *lt, int value)
325 int nmemb;
327 lt->gzdest[lt->gzbufpnt++] = value & 0xff;
329 nmemb=gzwrite_buffered(lt);
330 lt->zpackcount++;
331 lt->position++;
332 return(nmemb);
336 static int lxt2_wr_emit_u16z(struct lxt2_wr_trace *lt, int value)
338 int nmemb;
340 lt->gzdest[lt->gzbufpnt++] = (value>>8) & 0xff;
341 lt->gzdest[lt->gzbufpnt++] = value & 0xff;
342 nmemb = gzwrite_buffered(lt);
343 lt->zpackcount+=2;
344 lt->position+=2;
345 return(nmemb);
349 static int lxt2_wr_emit_u24z(struct lxt2_wr_trace *lt, int value)
351 int nmemb;
353 lt->gzdest[lt->gzbufpnt++] = (value>>16) & 0xff;
354 lt->gzdest[lt->gzbufpnt++] = (value>>8) & 0xff;
355 lt->gzdest[lt->gzbufpnt++] = value & 0xff;
356 nmemb=gzwrite_buffered(lt);
357 lt->zpackcount+=3;
358 lt->position+=3;
359 return(nmemb);
363 static int lxt2_wr_emit_u32z(struct lxt2_wr_trace *lt, int value)
365 int nmemb;
367 lt->gzdest[lt->gzbufpnt++] = (value>>24) & 0xff;
368 lt->gzdest[lt->gzbufpnt++] = (value>>16) & 0xff;
369 lt->gzdest[lt->gzbufpnt++] = (value>>8) & 0xff;
370 lt->gzdest[lt->gzbufpnt++] = value & 0xff;
371 nmemb=gzwrite_buffered(lt);
373 lt->zpackcount+=4;
374 lt->position+=4;
375 return(nmemb);
379 static int lxt2_wr_emit_u64z(struct lxt2_wr_trace *lt, int valueh, int valuel)
381 int rc;
383 if((rc=lxt2_wr_emit_u32z(lt, valueh)))
385 rc=lxt2_wr_emit_u32z(lt, valuel);
388 return(rc);
392 static int lxt2_wr_emit_stringz(struct lxt2_wr_trace *lt, char *value)
394 int rc=1;
397 rc&=lxt2_wr_emit_u8z(lt, *value);
398 } while(*(value++));
399 return(rc);
404 * hash/symtable manipulation
406 static int lxt2_wr_hash(const char *s)
408 const char *p;
409 char ch;
410 unsigned int h=0, h2=0, pos=0, g;
411 for(p=s;*p;p++)
413 ch=*p;
414 h2<<=3;
415 h2-=((unsigned int)ch+(pos++)); /* this handles stranded vectors quite well.. */
417 h=(h<<4)+ch;
418 if((g=h&0xf0000000))
420 h=h^(g>>24);
421 h=h^g;
425 h^=h2; /* combine the two hashes */
426 return(h%LXT2_WR_SYMPRIME);
430 static struct lxt2_wr_symbol *lxt2_wr_symadd(struct lxt2_wr_trace *lt, const char *name, int hv)
432 struct lxt2_wr_symbol *s;
434 s=(struct lxt2_wr_symbol *)calloc(1,sizeof(struct lxt2_wr_symbol));
435 strcpy(s->name=(char *)malloc((s->namlen=strlen(name))+1),name);
436 s->next=lt->sym[hv];
437 lt->sym[hv]=s;
438 return(s);
442 static struct lxt2_wr_symbol *lxt2_wr_symfind(struct lxt2_wr_trace *lt, const char *s)
444 int hv;
445 struct lxt2_wr_symbol *temp;
447 hv=lxt2_wr_hash(s);
448 if(!(temp=lt->sym[hv])) return(NULL); /* no hash entry, add here wanted to add */
450 while(temp)
452 if(!strcmp(temp->name,s))
454 return(temp); /* in table already */
456 if(!temp->next) break;
457 temp=temp->next;
460 return(NULL); /* not found, add here if you want to add*/
465 * compress facs to a prefix count + string + 0x00
467 static void lxt2_wr_compress_fac(struct lxt2_wr_trace *lt, char *str)
469 int i;
470 int len = strlen(str);
471 int minlen = (len<lt->compress_fac_len) ? len : lt->compress_fac_len;
473 if(minlen>65535) minlen=65535; /* keep in printable range--most hierarchies won't be this big anyway */
475 if(lt->compress_fac_str)
477 for(i=0;i<minlen;i++)
479 if(lt->compress_fac_str[i]!=str[i]) break;
481 lxt2_wr_emit_u16z(lt, i);
482 lxt2_wr_emit_stringz(lt, str+i);
483 free(lt->compress_fac_str);
485 else
487 lxt2_wr_emit_u16z(lt, 0);
488 lxt2_wr_emit_stringz(lt, str);
491 lt->compress_fac_str = (char *) malloc((lt->compress_fac_len=len)+1);
492 strcpy(lt->compress_fac_str, str);
497 * emit facs in sorted order along with geometry
498 * and sync table info
500 static int lxt2_wr_compare(const void *v1, const void *v2)
502 struct lxt2_wr_symbol *s1 = *(struct lxt2_wr_symbol **)v1;
503 struct lxt2_wr_symbol *s2 = *(struct lxt2_wr_symbol **)v2;
504 int rc = strcmp(s1->name, s2->name);
505 if(rc)
507 return(rc);
509 else
511 return(s1->msb - s2->msb);
516 static void strip_brack(struct lxt2_wr_symbol *s)
518 char *lastch = s->name+s->namlen - 1;
519 if(*lastch!=']') return;
520 if(s->namlen<3) return;
521 lastch--;
522 while(lastch!=s->name)
524 if(*lastch=='[')
526 *lastch=0x00;
527 return;
529 lastch--;
531 return;
535 static void lxt2_wr_emitfacs(struct lxt2_wr_trace *lt)
537 int i;
539 if((lt)&&(lt->numfacs))
541 struct lxt2_wr_symbol *s = lt->symchain;
542 struct lxt2_wr_symbol **aliascache = calloc(lt->numalias, sizeof(struct lxt2_wr_symbol *));
543 int aliases_encountered, facs_encountered;
545 lt->sorted_facs = (struct lxt2_wr_symbol **)calloc(lt->numfacs, sizeof(struct lxt2_wr_symbol *));
547 if(lt->sorted_facs && aliascache)
549 if(lt->do_strip_brackets)
550 for(i=0;i<lt->numfacs;i++)
552 lt->sorted_facs[i] = s;
553 strip_brack(s);
554 s=s->symchain;
556 else
557 for(i=0;i<lt->numfacs;i++)
559 lt->sorted_facs[i] = s;
560 s=s->symchain;
562 qsort((void *)lt->sorted_facs, lt->numfacs, sizeof(struct lxt2_wr_symbol *), lxt2_wr_compare);
564 if(lt->partial_preference)
566 /* move preferenced facs up */
567 struct lxt2_wr_symbol **prefcache = aliascache;
568 int prefs_encountered = 0;
570 facs_encountered = 0;
571 for(i=0;i<lt->numfacs;i++)
573 if((lt->sorted_facs[i]->partial_preference)==0)
575 lt->sorted_facs[facs_encountered] = lt->sorted_facs[i];
576 facs_encountered++;
578 else
580 prefcache[prefs_encountered] = lt->sorted_facs[i];
581 prefs_encountered++;
584 /* then append the non-preferenced facs */
585 for(i=0;i<facs_encountered;i++)
587 prefcache[prefs_encountered+i] = lt->sorted_facs[i];
590 /* now make prefcache the main cache */
591 aliascache = lt->sorted_facs;
592 lt->sorted_facs = prefcache;
595 /* move facs up */
596 aliases_encountered = 0, facs_encountered = 0;
597 for(i=0;i<lt->numfacs;i++)
599 if((lt->sorted_facs[i]->flags&LXT2_WR_SYM_F_ALIAS)==0)
601 lt->sorted_facs[facs_encountered] = lt->sorted_facs[i];
602 facs_encountered++;
604 else
606 aliascache[aliases_encountered] = lt->sorted_facs[i];
607 aliases_encountered++;
610 /* then append the aliases */
611 for(i=0;i<aliases_encountered;i++)
613 lt->sorted_facs[facs_encountered+i] = aliascache[i];
617 for(i=0;i<lt->numfacs;i++)
619 lt->sorted_facs[i]->facnum = i;
622 lt->facname_offset=lt->position;
624 lxt2_wr_emit_u32(lt, lt->numfacs); /* uncompressed */
625 lxt2_wr_emit_u32(lt, lt->numfacbytes); /* uncompressed */
626 lxt2_wr_emit_u32(lt, lt->longestname); /* uncompressed */
627 lxt2_wr_emit_u32(lt, 0); /* uncompressed : placeholder for zfacnamesize */
628 lxt2_wr_emit_u32(lt, 0); /* uncompressed : placeholder for zfacname_predec_size */
629 lxt2_wr_emit_u32(lt, 0); /* uncompressed : placeholder for zfacgeometrysize */
630 lxt2_wr_emit_u8(lt, lt->timescale); /* timescale (-9 default == nsec) */
632 fflush(lt->handle);
633 lt->zfacname_size = lt->position;
634 lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9");
636 lt->zpackcount = 0;
637 for(i=0;i<lt->numfacs;i++)
639 lxt2_wr_compress_fac(lt, lt->sorted_facs[i]->name);
640 free(lt->sorted_facs[i]->name);
641 lt->sorted_facs[i]->name = NULL;
643 free(lt->compress_fac_str); lt->compress_fac_str=NULL;
644 lt->compress_fac_len=0;
645 lt->zfacname_predec_size = lt->zpackcount;
647 gzflush_buffered(lt, 1);
648 fseeko(lt->handle, 0L, SEEK_END);
649 lt->position=ftello(lt->handle);
650 lt->zfacname_size = lt->position - lt->zfacname_size;
652 lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9");
654 lt->facgeometry_offset = lt->position;
655 for(i=0;i<lt->numfacs;i++)
657 if((lt->sorted_facs[i]->flags&LXT2_WR_SYM_F_ALIAS)==0)
659 lxt2_wr_emit_u32z(lt, lt->sorted_facs[i]->rows);
660 lxt2_wr_emit_u32z(lt, lt->sorted_facs[i]->msb);
661 lxt2_wr_emit_u32z(lt, lt->sorted_facs[i]->lsb);
662 lxt2_wr_emit_u32z(lt, lt->sorted_facs[i]->flags);
664 else
666 lxt2_wr_emit_u32z(lt, lt->sorted_facs[i]->aliased_to->facnum);
667 lxt2_wr_emit_u32z(lt, lt->sorted_facs[i]->msb);
668 lxt2_wr_emit_u32z(lt, lt->sorted_facs[i]->lsb);
669 lxt2_wr_emit_u32z(lt, LXT2_WR_SYM_F_ALIAS);
673 gzflush_buffered(lt, 1);
674 fseeko(lt->handle, 0L, SEEK_END);
675 lt->position=ftello(lt->handle);
676 lt->break_header_size = lt->position; /* in case we need to emit multiple lxt2s with same header */
677 lt->zfacgeometry_size = lt->position - lt->facgeometry_offset;
679 fseeko(lt->handle, lt->facname_offset + 12, SEEK_SET);
680 lxt2_wr_emit_u32(lt, lt->zfacname_size); /* backpatch sizes... */
681 lxt2_wr_emit_u32(lt, lt->zfacname_predec_size);
682 lxt2_wr_emit_u32(lt, lt->zfacgeometry_size);
684 lt->numfacs = facs_encountered; /* don't process alias value changes ever */
687 if(aliascache) free(aliascache);
693 * initialize the trace and get back and lt context
695 struct lxt2_wr_trace *lxt2_wr_init(const char *name)
697 struct lxt2_wr_trace *lt=(struct lxt2_wr_trace *)calloc(1, sizeof(struct lxt2_wr_trace));
699 if((!name)||(!(lt->handle=fopen(name, "wb"))))
701 free(lt);
702 lt=NULL;
704 else
706 lt->lxtname = strdup(name);
708 lxt2_wr_emit_u16(lt, LXT2_WR_HDRID);
709 lxt2_wr_emit_u16(lt, LXT2_WR_VERSION);
710 lxt2_wr_emit_u8 (lt, LXT2_WR_GRANULE_SIZE); /* currently 32 or 64 */
711 lt->timescale = -9;
712 lt->maxgranule = LXT2_WR_GRANULE_NUM;
713 lxt2_wr_set_compression_depth(lt, 4); /* set fast/loose compression depth, user can fix this any time after init */
714 lt->initial_value = 'x';
717 return(lt);
722 * setting break size
724 void lxt2_wr_set_break_size(struct lxt2_wr_trace *lt, off_t siz)
726 if(lt)
728 lt->break_size = siz;
734 * enable/disable partial dump mode (for faster reads)
736 void lxt2_wr_set_partial_off(struct lxt2_wr_trace *lt)
738 if(lt)
740 lt->partial = 0;
741 lt->partial_zip = 0;
745 void lxt2_wr_set_partial_on(struct lxt2_wr_trace *lt, int zipmode)
747 if(lt)
749 lt->partial = 1;
750 lt->partial_zip = (zipmode != 0);
751 lt->partial_iter = LXT2_WR_PARTIAL_SIZE;
755 void lxt2_wr_set_partial_preference(struct lxt2_wr_trace *lt, const char *name)
757 struct lxt2_wr_symbol *s;
759 if((lt)&&(name)&&(!lt->sorted_facs))
761 s=lxt2_wr_symfind(lt, name);
762 if(s)
764 while(s->aliased_to) /* find root alias */
766 s=s->aliased_to;
769 s->partial_preference = 1;
776 * enable/disable checkpointing (for smaller files)
778 void lxt2_wr_set_checkpoint_off(struct lxt2_wr_trace *lt)
780 if(lt)
782 lt->no_checkpoint = 1;
786 void lxt2_wr_set_checkpoint_on(struct lxt2_wr_trace *lt)
788 if(lt)
790 lt->no_checkpoint = 0;
796 * set initial value of trace (0, 1, x, z) only legal vals
798 void lxt2_wr_set_initial_value(struct lxt2_wr_trace *lt, char value)
800 if(lt)
802 switch(value)
804 case '0':
805 case '1':
806 case 'x':
807 case 'z': break;
808 case 'Z': value = 'z'; break;
809 default: value = 'x'; break;
812 lt->initial_value = value;
818 * maint function for finding a symbol if it exists
820 struct lxt2_wr_symbol *lxt2_wr_symbol_find(struct lxt2_wr_trace *lt, const char *name)
822 struct lxt2_wr_symbol *s=NULL;
824 if((lt)&&(name)) s=lxt2_wr_symfind(lt, name);
825 return(s);
830 * add a trace (if it doesn't exist already)
832 struct lxt2_wr_symbol *lxt2_wr_symbol_add(struct lxt2_wr_trace *lt, const char *name, unsigned int rows, int msb, int lsb, int flags)
834 struct lxt2_wr_symbol *s;
835 int len;
836 int flagcnt;
838 if((!lt)||(lt->sorted_facs)) return(NULL);
840 flagcnt = ((flags&LXT2_WR_SYM_F_INTEGER)!=0) + ((flags&LXT2_WR_SYM_F_DOUBLE)!=0) + ((flags&LXT2_WR_SYM_F_STRING)!=0);
842 if((flagcnt>1)||(!lt)||(!name)||(lxt2_wr_symfind(lt, name))) return (NULL);
844 s=lxt2_wr_symadd(lt, name, lxt2_wr_hash(name));
845 s->rows = rows;
846 s->flags = flags&(~LXT2_WR_SYM_F_ALIAS); /* aliasing makes no sense here.. */
848 if(!flagcnt)
850 s->msb = msb;
851 s->lsb = lsb;
852 s->len = (msb<lsb) ? (lsb-msb+1) : (msb-lsb+1);
855 if(flags&LXT2_WR_SYM_F_DOUBLE)
857 s->value = strdup("NaN");
859 else
861 if(flags & LXT2_WR_SYM_F_INTEGER)
863 s->len = 32;
866 s->value = malloc(s->len + 1);
867 memset(s->value, lt->initial_value, s->len);
868 s->value[s->len]=0;
870 s->msk = LXT2_WR_GRAN_1VAL; /* stuff in an initial value */
871 switch(lt->initial_value)
873 case '0': s->chg[0] = LXT2_WR_ENC_0; break;
874 case '1': s->chg[0] = LXT2_WR_ENC_1; break;
875 case 'z': s->chg[0] = LXT2_WR_ENC_Z; break;
876 default: s->chg[0] = LXT2_WR_ENC_X; break;
878 s->chgpos++; /* don't worry that a time doesn't exist as it will soon enough.. */
881 s->symchain = lt->symchain;
882 lt->symchain = s;
884 lt->numfacs++;
886 if((len=strlen(name)) > lt->longestname) lt->longestname = len;
887 lt->numfacbytes += (len+1);
889 return(s);
893 * add an alias trace (if it doesn't exist already and orig is found)
895 struct lxt2_wr_symbol *lxt2_wr_symbol_alias(struct lxt2_wr_trace *lt, const char *existing_name, const char *alias, int msb, int lsb)
897 struct lxt2_wr_symbol *s, *sa;
898 int len;
899 int bitlen;
900 int flagcnt;
902 if((!lt)||(!existing_name)||(!alias)||(!(s=lxt2_wr_symfind(lt, existing_name)))||(lxt2_wr_symfind(lt, alias))) return (NULL);
904 if(lt->sorted_facs) return(NULL);
906 while(s->aliased_to) /* find root alias */
908 s=s->aliased_to;
911 flagcnt = ((s->flags&LXT2_WR_SYM_F_INTEGER)!=0) + ((s->flags&LXT2_WR_SYM_F_DOUBLE)!=0) + ((s->flags&LXT2_WR_SYM_F_STRING)!=0);
912 bitlen = (msb<lsb) ? (lsb-msb+1) : (msb-lsb+1);
913 if((!flagcnt)&&(bitlen!=s->len)) return(NULL);
915 sa=lxt2_wr_symadd(lt, alias, lxt2_wr_hash(alias));
916 sa->flags = LXT2_WR_SYM_F_ALIAS; /* only point this can get set */
917 sa->aliased_to = s;
919 if(!flagcnt)
921 sa->msb = msb;
922 sa->lsb = lsb;
923 sa->len = bitlen;
926 sa->symchain = lt->symchain;
927 lt->symchain = sa;
928 lt->numfacs++;
929 lt->numalias++;
930 if((len=strlen(alias)) > lt->longestname) lt->longestname = len;
931 lt->numfacbytes += (len+1);
933 return(sa);
938 * set current time/granule updating
940 int lxt2_wr_inc_time_by_delta(struct lxt2_wr_trace *lt, unsigned int timeval)
942 return(lxt2_wr_set_time64(lt, lt->maxtime + (lxttime_t)timeval));
945 int lxt2_wr_set_time(struct lxt2_wr_trace *lt, unsigned int timeval)
947 return(lxt2_wr_set_time64(lt, (lxttime_t)timeval));
950 int lxt2_wr_inc_time_by_delta64(struct lxt2_wr_trace *lt, lxttime_t timeval)
952 return(lxt2_wr_set_time64(lt, lt->maxtime + timeval));
957 * file size limiting/header cloning...
959 static void lxt2_wr_emit_do_breakfile(struct lxt2_wr_trace *lt)
961 unsigned int len = strlen(lt->lxtname);
962 int i;
963 char *tname = malloc(len + 30);
964 FILE *f2, *clone;
965 off_t cnt, seg;
966 char buf[32768];
968 for(i=len;i>0;i--)
970 if(lt->lxtname[i]=='.') break;
973 if(!i)
975 sprintf(tname, "%s_%03d.lxt", lt->lxtname, ++lt->break_number);
977 else
979 memcpy(tname, lt->lxtname, i);
980 sprintf(tname+i, "_%03d.lxt", ++lt->break_number);
983 f2 = fopen(tname, "wb");
984 if(!f2) /* if error, keep writing to same output file...sorry */
986 free(tname);
987 return;
990 clone = fopen(lt->lxtname, "rb");
991 if(!clone)
992 { /* this should never happen */
993 fclose(f2);
994 unlink(tname);
995 free(tname);
996 return;
999 /* clone original header */
1000 for(cnt = 0; cnt < lt->break_header_size; cnt += sizeof(buf))
1002 seg = lt->break_header_size - cnt;
1003 if(seg > sizeof(buf))
1005 seg = sizeof(buf);
1008 fread(buf, seg, 1, clone);
1009 fwrite(buf, seg, 1, f2);
1012 fclose(clone);
1013 fclose(lt->handle);
1014 lt->handle = f2;
1015 free(tname);
1020 * emit granule
1022 void lxt2_wr_flush_granule(struct lxt2_wr_trace *lt, int do_finalize)
1024 unsigned int idx_nbytes, map_nbytes, i, j;
1025 struct lxt2_wr_symbol *s;
1026 unsigned int partial_iter;
1027 unsigned int iter, iter_hi;
1028 unsigned char using_partial, using_partial_zip=0;
1029 off_t current_iter_pos=0;
1030 int early_flush;
1032 if(lt->flush_valid)
1034 if(lt->flushtime == lt->lasttime)
1036 return;
1039 lt->flush_valid = 0;
1042 lt->granule_dirty = 0;
1044 if((using_partial=(lt->partial)&&(lt->numfacs>lt->partial_iter)))
1046 partial_iter = lt->partial_iter;
1047 using_partial_zip = lt->partial_zip;
1049 else
1051 partial_iter = lt->numfacs;
1054 if(!lt->timegranule)
1056 int attempt_break_state = 2;
1058 do {
1059 fseeko(lt->handle, 0L, SEEK_END);
1060 lt->current_chunk=lt->position = ftello(lt->handle);
1062 if((lt->break_size)&&(attempt_break_state==2)&&(lt->position >= lt->break_size)&&(lt->position != lt->break_header_size))
1064 lxt2_wr_emit_do_breakfile(lt);
1065 attempt_break_state--;
1067 else
1069 attempt_break_state = 0;
1071 } while(attempt_break_state);
1073 /* fprintf(stderr, "First chunk position is %d (0x%08x)\n", lt->current_chunk, lt->current_chunk); */
1074 lxt2_wr_emit_u32(lt, 0); /* size of this section (uncompressed) */
1075 lxt2_wr_emit_u32(lt, 0); /* size of this section (compressed) */
1076 lxt2_wr_emit_u64(lt, 0, 0); /* begin time of section */
1077 lxt2_wr_emit_u64(lt, 0, 0); /* end time of section */
1078 fflush(lt->handle);
1079 lt->current_chunkz = lt->position;
1080 /* fprintf(stderr, "First chunkz position is %d (0x%08x)\n", lt->current_chunkz, lt->current_chunkz); */
1082 if(!using_partial_zip)
1084 lt->zhandle = gzdopen(dup(fileno(lt->handle)), lt->zmode);
1086 else
1088 lt->zpackcount_cumulative = 0;
1090 lt->zpackcount = 0;
1095 for(iter=0; iter<lt->numfacs; iter=iter_hi)
1097 unsigned int total_chgs;
1098 unsigned int partial_length;
1100 total_chgs = 0;
1101 partial_length = 0;
1103 iter_hi = iter + partial_iter;
1104 if(iter_hi > lt->numfacs) iter_hi = lt->numfacs;
1106 for(j=iter;j<iter_hi;j++)
1108 granmsk_t msk = lt->sorted_facs[j]->msk;
1110 lt->mapdict = lxt2_wr_ds_splay (msk, lt->mapdict);
1111 if((!lt->mapdict)||(lt->mapdict->item != msk))
1113 lt->mapdict = lxt2_wr_ds_insert(msk, lt->mapdict, lt->num_map_entries);
1114 lt->num_map_entries++;
1116 if(lt->mapdict_curr)
1118 lt->mapdict_curr->next = lt->mapdict;
1119 lt->mapdict_curr = lt->mapdict;
1121 else
1123 lt->mapdict_head = lt->mapdict_curr = lt->mapdict;
1128 if(lt->num_map_entries <= 256) { map_nbytes = 1; }
1129 else if(lt->num_map_entries <= 256*256) { map_nbytes = 2; }
1130 else if(lt->num_map_entries <= 256*256*256) { map_nbytes = 3; }
1131 else { map_nbytes = 4; }
1133 if((lt->num_dict_entries+LXT2_WR_DICT_START) <= 256) { idx_nbytes = 1; }
1134 else if((lt->num_dict_entries+LXT2_WR_DICT_START) <= 256*256) { idx_nbytes = 2; }
1135 else if((lt->num_dict_entries+LXT2_WR_DICT_START) <= 256*256*256) { idx_nbytes = 3; }
1136 else { idx_nbytes = 4; }
1138 if(using_partial)
1140 /* skip */
1141 partial_length = 1 + /* lt->timepos */
1142 lt->timepos * sizeof(lxttime_t)+ /* timevals */
1144 1 + /* map_nbytes */
1145 (iter_hi-iter) * map_nbytes + /* actual map */
1146 1; /* idx_nbytes */
1148 for(j=iter;j<iter_hi;j++)
1150 s=lt->sorted_facs[j];
1151 total_chgs += s->chgpos;
1153 total_chgs *= idx_nbytes; /* vch skip */
1155 partial_length += total_chgs; /* actual changes */
1157 if(using_partial_zip)
1159 fseeko(lt->handle, 0L, SEEK_END);
1160 current_iter_pos = ftello(lt->handle);
1161 lxt2_wr_emit_u32(lt, 0); /* size of this section (compressed) */
1162 lxt2_wr_emit_u32(lt, partial_length+9); /* size of this section (uncompressed) */
1163 lxt2_wr_emit_u32(lt, iter); /* begin iter of section */
1164 fflush(lt->handle);
1166 lt->zhandle = gzdopen(dup(fileno(lt->handle)), lt->zmode);
1167 lt->zpackcount = 0;
1170 lxt2_wr_emit_u8z(lt, LXT2_WR_GRAN_SECT_TIME_PARTIAL);
1171 lxt2_wr_emit_u32z(lt, iter);
1172 lxt2_wr_emit_u32z(lt, partial_length);
1174 else
1176 lxt2_wr_emit_u8z(lt, LXT2_WR_GRAN_SECT_TIME);
1179 lxt2_wr_emit_u8z(lt, lt->timepos);
1180 for(i=0;i<lt->timepos;i++)
1182 lxt2_wr_emit_u64z(lt, (lt->timetable[i]>>32)&0xffffffff, lt->timetable[i]&0xffffffff);
1184 gzflush_buffered(lt, 0);
1187 lxt2_wr_emit_u8z(lt, map_nbytes);
1188 for(j=iter;j<iter_hi;j++)
1190 unsigned int val;
1191 s=lt->sorted_facs[j];
1192 lt->mapdict = lxt2_wr_ds_splay (s->msk, lt->mapdict);
1193 val = lt->mapdict->val;
1195 switch(map_nbytes)
1197 case 1: lxt2_wr_emit_u8z(lt, val); break;
1198 case 2: lxt2_wr_emit_u16z(lt, val); break;
1199 case 3: lxt2_wr_emit_u24z(lt, val); break;
1200 case 4: lxt2_wr_emit_u32z(lt, val); break;
1203 s->msk = LXT2_WR_GRAN_0VAL;
1207 lxt2_wr_emit_u8z(lt, idx_nbytes);
1208 gzflush_buffered(lt, 0);
1209 for(j=iter;j<iter_hi;j++)
1211 s=lt->sorted_facs[j];
1213 for(i=0;i<s->chgpos;i++)
1215 switch(idx_nbytes)
1217 case 1: lxt2_wr_emit_u8z (lt, s->chg[i]); break;
1218 case 2: lxt2_wr_emit_u16z(lt, s->chg[i]); break;
1219 case 3: lxt2_wr_emit_u24z(lt, s->chg[i]); break;
1220 case 4: lxt2_wr_emit_u32z(lt, s->chg[i]); break;
1224 s->chgpos = 0;
1227 if(using_partial_zip)
1229 off_t clen;
1231 gzflush_buffered(lt, 1);
1232 fseeko(lt->handle, 0L, SEEK_END);
1233 lt->position=ftello(lt->handle);
1235 clen = lt->position - current_iter_pos - 12;
1236 fseeko(lt->handle, current_iter_pos, SEEK_SET);
1238 lt->zpackcount_cumulative+=lt->zpackcount;
1240 lxt2_wr_emit_u32(lt, clen);
1242 else
1244 gzflush_buffered(lt, 0);
1246 } /* ...for(iter) */
1249 lt->timepos = 0;
1250 lt->timegranule++;
1252 if(lt->break_size)
1254 early_flush = (ftello(lt->handle) >= lt->break_size);
1256 else
1258 early_flush = 0;
1261 if((lt->timegranule>=lt->maxgranule)||(do_finalize)||(early_flush))
1263 off_t unclen, clen;
1264 lxt2_wr_ds_Tree *dt, *dt2;
1265 lxt2_wr_dslxt_Tree *ds, *ds2;
1267 if(using_partial_zip)
1269 fseeko(lt->handle, 0L, SEEK_END);
1270 current_iter_pos = ftello(lt->handle);
1271 lxt2_wr_emit_u32(lt, 0); /* size of this section (compressed) */
1272 lxt2_wr_emit_u32(lt, 0); /* size of this section (uncompressed) */
1273 lxt2_wr_emit_u32(lt, ~0); /* control section */
1274 fflush(lt->handle);
1276 lt->zhandle = gzdopen(dup(fileno(lt->handle)), lt->zmode);
1277 lt->zpackcount = 0;
1280 /* fprintf(stderr, "reached granule %d, finalizing block for section %d\n", lt->timegranule, lt->numsections); */
1281 lt->numsections++;
1283 /* finalize string dictionary */
1284 lxt2_wr_emit_u8z(lt, LXT2_WR_GRAN_SECT_DICT);
1286 ds = lt->dict_head;
1287 /* fprintf(stderr, "num_dict_entries: %d\n", lt->num_dict_entries); */
1288 gzflush_buffered(lt, 0);
1289 for(i=0;i<lt->num_dict_entries;i++)
1291 /* fprintf(stderr, "%8d %8d) '%s'\n", ds->val, i, ds->item); */
1292 if(ds->val != i)
1294 fprintf(stderr, "internal error line %d\n", __LINE__);
1295 exit(255);
1298 lxt2_wr_emit_stringz(lt, ds->item);
1299 ds2 = ds->next;
1300 free(ds->item);
1301 free(ds);
1302 ds = ds2;
1304 lt->dict_head = lt->dict_curr = lt->dict = NULL;
1306 /* finalize map dictionary */
1307 dt = lt->mapdict_head;
1308 /* fprintf(stderr, "num_map_entries: %d\n", lt->num_map_entries); */
1309 gzflush_buffered(lt, 0);
1310 for(i=0;i<lt->num_map_entries;i++)
1312 /* fprintf(stderr, "+++ %08x (%d)(%d)\n", dt->item, i, dt->val); */
1313 if(dt->val != i)
1315 fprintf(stderr, "internal error line %d\n", __LINE__);
1316 exit(255);
1319 #if LXT2_WR_GRANULE_SIZE > 32
1320 lxt2_wr_emit_u64z(lt, (dt->item>>32)&0xffffffff, dt->item&0xffffffff);
1321 #else
1322 lxt2_wr_emit_u32z(lt, dt->item);
1323 #endif
1325 dt2 = dt->next;
1326 free(dt);
1327 dt = dt2;
1329 lt->mapdict_head = lt->mapdict_curr = lt->mapdict = NULL;
1331 lxt2_wr_emit_u32z(lt, lt->num_dict_entries); /* -12 */
1332 lxt2_wr_emit_u32z(lt, lt->dict_string_mem_required); /* -8 */
1333 lxt2_wr_emit_u32z(lt, lt->num_map_entries); /* -4 */
1335 lt->num_map_entries = 0;
1336 lt->num_dict_entries = lt->dict_string_mem_required = 0;
1338 /* fprintf(stderr, "returned from finalize..\n"); */
1340 if(using_partial_zip)
1342 off_t clen;
1344 gzflush_buffered(lt, 1);
1345 fseeko(lt->handle, 0L, SEEK_END);
1346 lt->position=ftello(lt->handle);
1348 clen = lt->position - current_iter_pos - 12;
1349 fseeko(lt->handle, current_iter_pos, SEEK_SET);
1351 lt->zpackcount_cumulative+=lt->zpackcount;
1352 lxt2_wr_emit_u32(lt, clen);
1353 lxt2_wr_emit_u32(lt, lt->zpackcount);
1355 else
1357 gzflush_buffered(lt, 1);
1360 fseeko(lt->handle, 0L, SEEK_END);
1361 lt->position=ftello(lt->handle);
1362 /* fprintf(stderr, "file position after dumping dict: %d 0x%08x\n", lt->position, lt->position); */
1364 unclen = lt->zpackcount;
1365 clen = lt->position - lt->current_chunkz;
1367 /* fprintf(stderr, "%d/%d un/compressed bytes in section\n", unclen, clen); */
1369 fseeko(lt->handle, lt->current_chunk, SEEK_SET);
1370 if(using_partial_zip)
1372 lxt2_wr_emit_u32(lt, lt->zpackcount_cumulative);
1373 lxt2_wr_emit_u32(lt, clen);
1375 else
1377 lxt2_wr_emit_u32(lt, unclen);
1378 lxt2_wr_emit_u32(lt, clen);
1380 lxt2_wr_emit_u64(lt, (lt->firsttime>>32)&0xffffffff, lt->firsttime&0xffffffff);
1381 lxt2_wr_emit_u64(lt, (lt->lasttime>>32)&0xffffffff, lt->lasttime&0xffffffff);
1383 /* fprintf(stderr, "start: %Ld, end %Ld\n", lt->firsttime, lt->lasttime); */
1385 lt->timegranule=0;
1386 lt->numblock++;
1389 if(do_finalize)
1391 lt->flush_valid = 1;
1392 lt->flushtime = lt->lasttime;
1397 int lxt2_wr_set_time64(struct lxt2_wr_trace *lt, lxttime_t timeval)
1399 int rc=0;
1401 if(lt)
1403 if(lt->timeset)
1405 if(timeval > lt->maxtime)
1407 if(lt->bumptime)
1409 lt->bumptime = 0;
1411 if(!lt->flush_valid)
1413 lt->timepos++;
1415 else
1417 lt->flush_valid = 0;
1420 if(lt->timepos == LXT2_WR_GRANULE_SIZE)
1422 /* fprintf(stderr, "flushing granule to disk at time %d\n", (unsigned int)timeval); */
1423 lxt2_wr_flush_granule(lt, 0);
1427 /* fprintf(stderr, "updating time to %d (%d dict entries/%d bytes)\n", (unsigned int)timeval, lt->num_dict_entries, lt->dict_string_mem_required); */
1428 lt->timetable[lt->timepos] = timeval;
1429 lt->lasttime = timeval;
1432 else
1434 lt->timeset = 1;
1435 lt->mintime = lt->maxtime = timeval;
1437 lt->timetable[lt->timepos] = timeval;
1440 if( (!lt->timepos) && (!lt->timegranule) )
1442 lt->firsttime = timeval;
1443 lt->lasttime = timeval;
1446 if( (!lt->timepos) && (!lt->timegranule) && ((!lt->numblock)||(!lt->no_checkpoint)) )
1448 struct lxt2_wr_symbol *s = lt->symchain;
1450 /* fprintf(stderr, "initial value burst timepos==0, timegranule==0\n"); */
1451 if(lt->blackout)
1453 lt->blackout = 0;
1454 lxt2_wr_set_dumpoff(lt);
1456 else
1458 s = lt->symchain;
1459 while(s)
1461 if((!(s->flags&LXT2_WR_SYM_F_ALIAS))&&(s->rows<2))
1463 if(!(s->flags&(LXT2_WR_SYM_F_DOUBLE|LXT2_WR_SYM_F_STRING)))
1465 lxt2_wr_emit_value_bit_string(lt, s, 0, s->value);
1467 else if (s->flags&LXT2_WR_SYM_F_DOUBLE)
1469 double value;
1471 sscanf(s->value, "%lg", &value);
1472 lxt2_wr_emit_value_double(lt, s, 0, value);
1474 else if (s->flags&LXT2_WR_SYM_F_STRING)
1476 lxt2_wr_emit_value_string(lt, s, 0, s->value);
1479 s=s->symchain;
1482 /* fprintf(stderr, "done initial value burst timepos==0, timegranule==0\n"); */
1485 lt->granule_dirty = 1;
1486 rc = 1;
1489 return(rc);
1494 * sets trace timescale as 10**x seconds
1496 void lxt2_wr_set_timescale(struct lxt2_wr_trace *lt, int timescale)
1498 if(lt)
1500 lt->timescale = timescale;
1506 * set number of granules per section
1507 * (can modify dynamically)
1509 void lxt2_wr_set_maxgranule(struct lxt2_wr_trace *lt, unsigned int maxgranule)
1511 if(lt)
1513 if(!maxgranule) maxgranule = ~0;
1514 lt->maxgranule = maxgranule;
1520 * Sets bracket stripping (useful for VCD conversions of
1521 * bitblasted nets)
1523 void lxt2_wr_symbol_bracket_stripping(struct lxt2_wr_trace *lt, int doit)
1525 if(lt)
1527 lt->do_strip_brackets = (doit!=0);
1533 static char *lxt2_wr_expand_integer_to_bits(unsigned int len, int value)
1535 static char s[33];
1536 char *p = s;
1537 unsigned int i;
1539 if(len>32) len=32;
1541 len--;
1543 for(i=0;i<=len;i++)
1545 *(p++) = '0' | ((value & (1<<(len-i)))!=0);
1547 *p = 0;
1549 return(s);
1553 int lxt2_wr_emit_value_int(struct lxt2_wr_trace *lt, struct lxt2_wr_symbol *s, unsigned int row, int value)
1555 int rc=0;
1557 if((!lt)||(lt->blackout)||(!s)||(row)) return(rc);
1559 return(lxt2_wr_emit_value_bit_string(lt, s, row, lxt2_wr_expand_integer_to_bits(s->len, value)));
1564 int lxt2_wr_emit_value_double(struct lxt2_wr_trace *lt, struct lxt2_wr_symbol *s, unsigned int row, double value)
1566 int rc=0;
1568 if((!lt)||(lt->blackout)||(!s)||(row)) return(rc);
1570 if(!lt->emitted)
1572 lxt2_wr_emitfacs(lt);
1573 lt->emitted = 1;
1575 if(!lt->timeset)
1577 lxt2_wr_set_time(lt, 0);
1581 while(s->aliased_to) /* find root alias if exists */
1583 s=s->aliased_to;
1586 if(s->flags&LXT2_WR_SYM_F_DOUBLE)
1588 char d_buf[32];
1589 unsigned int idx;
1591 rc = 1;
1592 sprintf(d_buf, "%.16g", value);
1593 if(!strcmp(d_buf, s->value)) return(rc);
1595 lt->bumptime = 1;
1596 free(s->value);
1597 s->value = strdup(d_buf);
1599 lt->dict = lxt2_wr_dslxt_splay (s->value, lt->dict);
1601 if(!lxt2_wr_dslxt_success)
1603 unsigned int vlen = strlen(d_buf)+1;
1604 char *vcopy = (char *)malloc(vlen);
1605 strcpy(vcopy, d_buf);
1606 lt->dict_string_mem_required += vlen;
1607 lt->dict = lxt2_wr_dslxt_insert(vcopy, lt->dict, lt->num_dict_entries);
1609 if(lt->dict_curr)
1611 lt->dict_curr->next = lt->dict;
1612 lt->dict_curr = lt->dict;
1614 else
1616 lt->dict_head = lt->dict_curr = lt->dict;
1619 idx = lt->num_dict_entries + LXT2_WR_DICT_START;
1620 lt->num_dict_entries++;
1622 else
1624 idx = lt->dict->val + LXT2_WR_DICT_START;
1627 if((s->msk & (LXT2_WR_GRAN_1VAL<<lt->timepos)) == LXT2_WR_GRAN_0VAL)
1629 s->msk |= (LXT2_WR_GRAN_1VAL<<lt->timepos);
1630 s->chg[s->chgpos] = idx;
1632 s->chgpos++;
1634 else
1636 s->chg[s->chgpos-1] = idx;
1639 lt->granule_dirty = 1;
1642 return(rc);
1646 int lxt2_wr_emit_value_string(struct lxt2_wr_trace *lt, struct lxt2_wr_symbol *s, unsigned int row, char *value)
1648 int rc=0;
1650 if((!lt)||(lt->blackout)||(!s)||(!value)||(row)) return(rc);
1652 if(!lt->emitted)
1654 lxt2_wr_emitfacs(lt);
1655 lt->emitted = 1;
1657 if(!lt->timeset)
1659 lxt2_wr_set_time(lt, 0);
1663 while(s->aliased_to) /* find root alias if exists */
1665 s=s->aliased_to;
1668 if(s->flags&LXT2_WR_SYM_F_STRING)
1670 unsigned int idx;
1672 rc = 1;
1673 if(!strcmp(value, s->value)) return(rc);
1675 lt->bumptime = 1;
1676 free(s->value);
1677 s->value = strdup(value);
1679 lt->dict = lxt2_wr_dslxt_splay (s->value, lt->dict);
1681 if(!lxt2_wr_dslxt_success)
1683 unsigned int vlen = strlen(value)+1;
1684 char *vcopy = (char *)malloc(vlen);
1685 strcpy(vcopy, value);
1686 lt->dict_string_mem_required += vlen;
1687 lt->dict = lxt2_wr_dslxt_insert(vcopy, lt->dict, lt->num_dict_entries);
1689 if(lt->dict_curr)
1691 lt->dict_curr->next = lt->dict;
1692 lt->dict_curr = lt->dict;
1694 else
1696 lt->dict_head = lt->dict_curr = lt->dict;
1699 idx = lt->num_dict_entries + LXT2_WR_DICT_START;
1700 lt->num_dict_entries++;
1702 else
1704 idx = lt->dict->val + LXT2_WR_DICT_START;
1707 if((s->msk & (LXT2_WR_GRAN_1VAL<<lt->timepos)) == LXT2_WR_GRAN_0VAL)
1709 s->msk |= (LXT2_WR_GRAN_1VAL<<lt->timepos);
1710 s->chg[s->chgpos] = idx;
1712 s->chgpos++;
1714 else
1716 s->chg[s->chgpos-1] = idx;
1719 lt->granule_dirty = 1;
1722 return(rc);
1726 int lxt2_wr_emit_value_bit_string(struct lxt2_wr_trace *lt, struct lxt2_wr_symbol *s, unsigned int row, char *value)
1728 int rc=0;
1729 char *vpnt;
1730 char *vfix;
1731 int valuelen;
1732 int i;
1734 if((!lt)||(lt->blackout)||(!s)||(!value)||(!*value)||(row)) return(rc);
1736 if(!lt->emitted)
1738 lxt2_wr_emitfacs(lt);
1739 lt->emitted = 1;
1741 if(!lt->timeset)
1743 lxt2_wr_set_time(lt, 0);
1747 while(s->aliased_to) /* find root alias if exists */
1749 s=s->aliased_to;
1752 valuelen = strlen(value); /* ensure string is proper length */
1753 if(valuelen == s->len)
1755 vfix = alloca(s->len+1);
1756 strcpy(vfix, value);
1757 value = vfix;
1759 else
1761 vfix = alloca(s->len+1);
1763 if(valuelen < s->len)
1765 int lendelta = s->len - valuelen;
1766 memset(vfix, (value[0]!='1') ? value[0] : '0', lendelta);
1767 strcpy(vfix+lendelta, value);
1769 else
1771 memcpy(vfix, value, s->len);
1772 vfix[s->len] = 0;
1775 value = vfix;
1778 for(i=0;i<s->len;i++)
1780 unsigned char ch = value[i];
1781 if((ch>='A')&&(ch<='Z')) value[i] = ch + ('a'-'A');
1784 if ( (lt->timepos || lt->timegranule) && !strcmp(value, s->value) )
1786 return(1); /* redundant value change */
1790 if(!(s->flags&(LXT2_WR_SYM_F_DOUBLE|LXT2_WR_SYM_F_STRING)))
1792 char prevch;
1793 int idx;
1795 lt->bumptime = 1;
1797 vpnt = value;
1798 prevch = *vpnt;
1799 while(*vpnt)
1801 if(prevch == *vpnt)
1803 vpnt++;
1805 else
1807 prevch = 0;
1808 break;
1812 switch(prevch)
1814 case '0': idx = LXT2_WR_ENC_0; break;
1815 case '1': idx = LXT2_WR_ENC_1; break;
1816 case 'X':
1817 case 'x': idx = LXT2_WR_ENC_X; break;
1818 case 'Z':
1819 case 'z': idx = LXT2_WR_ENC_Z; break;
1820 default: idx = -1; break;
1823 if((lt->timepos)||(lt->timegranule))
1825 for(i=0;i<s->len;i++)
1827 char ch = value[i];
1829 switch(ch)
1831 case '0': if(s->value[i]!='1') goto nextalg; else break;
1832 case '1': if(s->value[i]!='0') goto nextalg; else break;
1833 default: goto nextalg;
1836 idx = LXT2_WR_ENC_INV; goto do_enc;
1838 nextalg:
1839 if(s->len > 1)
1841 if(!memcmp(s->value+1, value, s->len-1))
1843 if((value[s->len-1]&0xfe)=='0')
1845 idx = LXT2_WR_ENC_LSH0 + (value[s->len-1]&0x01);
1846 goto do_enc;
1849 else
1850 if(!memcmp(s->value, value+1, s->len-1))
1852 if((value[0]&0xfe)=='0')
1854 idx = LXT2_WR_ENC_RSH0 + (value[0]&0x01);
1855 goto do_enc;
1859 if(s->len <= 32)
1861 unsigned int intval_old = 0, intval_new = 0;
1862 unsigned int msk;
1864 for(i=0;i<s->len;i++)
1866 char ch = value[i];
1867 if((ch!='0')&&(ch!='1')) goto idxchk;
1868 intval_new <<= 1;
1869 intval_new |= ((unsigned int)(ch&1));
1871 ch = s->value[i];
1872 if((ch!='0')&&(ch!='1')) goto idxchk;
1873 intval_old <<= 1;
1874 intval_old |= ((unsigned int)(ch&1));
1877 msk = (~0)>>(32-s->len);
1878 if( ((intval_old+1)&msk) == intval_new ) { idx = LXT2_WR_ENC_ADD1; goto do_enc; }
1879 if( ((intval_old-1)&msk) == intval_new ) { idx = LXT2_WR_ENC_SUB1; goto do_enc; }
1881 if( ((intval_old+2)&msk) == intval_new ) { idx = LXT2_WR_ENC_ADD2; goto do_enc; }
1882 if( ((intval_old-2)&msk) == intval_new ) { idx = LXT2_WR_ENC_SUB2; goto do_enc; }
1884 if( ((intval_old+3)&msk) == intval_new ) { idx = LXT2_WR_ENC_ADD3; goto do_enc; }
1885 if( ((intval_old-3)&msk) == intval_new ) { idx = LXT2_WR_ENC_SUB3; goto do_enc; }
1887 if(s->len > 2)
1889 if( ((intval_old+4)&msk) == intval_new ) { idx = LXT2_WR_ENC_ADD4; goto do_enc; }
1890 if( ((intval_old-4)&msk) == intval_new ) { idx = LXT2_WR_ENC_SUB4; goto do_enc; }
1898 idxchk: if(idx<0)
1900 vpnt = lxt2_wr_vcd_truncate_bitvec(value);
1901 lt->dict = lxt2_wr_dslxt_splay (vpnt, lt->dict);
1903 if(!lxt2_wr_dslxt_success)
1905 unsigned int vlen = strlen(vpnt)+1;
1906 char *vcopy = (char *)malloc(vlen);
1907 strcpy(vcopy, vpnt);
1908 lt->dict_string_mem_required += vlen;
1909 lt->dict = lxt2_wr_dslxt_insert(vcopy, lt->dict, lt->num_dict_entries);
1911 if(lt->dict_curr)
1913 lt->dict_curr->next = lt->dict;
1914 lt->dict_curr = lt->dict;
1916 else
1918 lt->dict_head = lt->dict_curr = lt->dict;
1921 idx = lt->num_dict_entries + LXT2_WR_DICT_START;
1922 lt->num_dict_entries++;
1924 else
1926 idx = lt->dict->val + LXT2_WR_DICT_START;
1930 do_enc:
1931 if((s->msk & (LXT2_WR_GRAN_1VAL<<lt->timepos)) == LXT2_WR_GRAN_0VAL)
1933 s->msk |= (LXT2_WR_GRAN_1VAL<<lt->timepos);
1934 s->chg[s->chgpos] = idx;
1936 s->chgpos++;
1938 else
1940 s->chg[s->chgpos-1] = idx;
1943 strncpy(s->value, value, s->len);
1945 lt->granule_dirty = 1;
1948 return(rc);
1953 * dumping control
1955 void lxt2_wr_set_dumpoff(struct lxt2_wr_trace *lt)
1957 struct lxt2_wr_symbol *s;
1959 if((lt)&&(!lt->blackout))
1961 if(!lt->emitted)
1963 lxt2_wr_emitfacs(lt);
1964 lt->emitted = 1;
1966 if(!lt->timeset)
1968 lxt2_wr_set_time(lt, 0);
1972 s = lt->symchain;
1973 while(s)
1975 if((s->msk & (LXT2_WR_GRAN_1VAL<<lt->timepos)) == LXT2_WR_GRAN_0VAL)
1977 s->msk |= (LXT2_WR_GRAN_1VAL<<lt->timepos);
1978 s->chg[s->chgpos] = LXT2_WR_ENC_BLACKOUT;
1980 s->chgpos++;
1982 else
1984 s->chg[s->chgpos-1] = LXT2_WR_ENC_BLACKOUT;
1987 s=s->symchain;
1990 lt->bumptime = 1;
1991 lt->blackout = 1;
1992 lt->granule_dirty = 1;
1997 void lxt2_wr_set_dumpon(struct lxt2_wr_trace *lt)
1999 int i;
2000 struct lxt2_wr_symbol *s;
2002 if((lt)&&(lt->blackout))
2004 lt->blackout = 0;
2006 s = lt->symchain;
2007 while(s)
2009 if(s->flags&LXT2_WR_SYM_F_DOUBLE)
2011 free(s->value);
2012 s->value = strdup("0"); /* will cause mismatch then flush */
2014 else
2016 if(!(s->flags&LXT2_WR_SYM_F_STRING))
2018 s->value[0] = '-'; /* will cause mismatch then flush */
2019 for(i=1;i<s->len;i++)
2021 s->value[i] = 'x'; /* initial value */
2023 s->value[i]=0;
2025 else
2027 free(s->value);
2028 s->value = calloc(1, 1*sizeof(char));
2032 s=s->symchain;
2035 s = lt->symchain;
2036 while(s)
2038 if((!(s->flags&LXT2_WR_SYM_F_ALIAS))&&(s->rows<2))
2040 if(!(s->flags&(LXT2_WR_SYM_F_DOUBLE|LXT2_WR_SYM_F_STRING)))
2042 lxt2_wr_emit_value_bit_string(lt, s, 0, "x");
2044 else if (s->flags&LXT2_WR_SYM_F_DOUBLE)
2046 double value;
2047 sscanf("NaN", "%lg", &value);
2048 lxt2_wr_emit_value_double(lt, s, 0, value);
2050 else if (s->flags&LXT2_WR_SYM_F_STRING)
2052 lxt2_wr_emit_value_string(lt, s, 0, "UNDEF");
2055 s=s->symchain;
2062 * flush the trace...
2064 void lxt2_wr_flush(struct lxt2_wr_trace *lt)
2066 if(lt)
2068 if((lt->timegranule)||(lt->timepos > 0))
2070 if(lt->granule_dirty)
2072 lt->timepos++;
2073 lxt2_wr_flush_granule(lt, 1);
2081 * close out the trace and fixate it
2083 void lxt2_wr_close(struct lxt2_wr_trace *lt)
2085 if(lt)
2087 if(lt->granule_dirty)
2089 lt->timepos++;
2090 lxt2_wr_flush_granule(lt, 1);
2093 if(lt->symchain)
2095 struct lxt2_wr_symbol *s = lt->symchain;
2096 struct lxt2_wr_symbol *s2;
2098 while(s)
2100 if(s->name) { free(s->name); }
2101 if(s->value) { free(s->value); }
2102 s2=s->symchain;
2103 free(s);
2104 s=s2;
2107 lt->symchain=NULL;
2110 free(lt->sorted_facs);
2111 fclose(lt->handle);
2112 free(lt);
2118 * set compression depth
2120 void lxt2_wr_set_compression_depth(struct lxt2_wr_trace *lt, unsigned int depth)
2122 if(lt)
2124 if(depth > 9) depth = 9;
2125 sprintf(lt->zmode, "wb%d", depth);