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
)
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
;
65 if (t
->left
== NULL
) break;
66 if (i
< t
->left
->item
) {
67 y
= t
->left
; /* rotate right */
71 if (t
->left
== NULL
) break;
73 r
->left
= t
; /* link right */
76 } else if (i
> t
->item
) {
77 if (t
->right
== NULL
) break;
78 if (i
> t
->right
->item
) {
79 y
= t
->right
; /* rotate left */
83 if (t
->right
== NULL
) break;
85 l
->right
= t
; /* link left */
92 l
->right
= t
->left
; /* assemble */
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. */
105 n
= (lxt2_wr_ds_Tree
*) calloc (1, sizeof (lxt2_wr_ds_Tree
));
107 fprintf(stderr
, "ds_insert: ran out of memory, exiting.\n");
113 n
->left
= n
->right
= NULL
;
116 t
= lxt2_wr_ds_splay(i
,t
);
122 } else if (i
> t
->item
) {
127 } else { /* We get here if it's already in the tree */
128 /* Don't add it again */
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
;
144 lxt2_wr_dslxt_success
= 0;
146 if (t
== NULL
) return t
;
147 N
.left
= N
.right
= NULL
;
151 dir
= strcmp(i
, t
->item
);
153 if (t
->left
== NULL
) break;
154 if (strcmp(i
, t
->left
->item
)<0) {
155 y
= t
->left
; /* rotate right */
159 if (t
->left
== NULL
) break;
161 r
->left
= t
; /* link right */
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 */
171 if (t
->right
== NULL
) break;
173 l
->right
= t
; /* link left */
177 lxt2_wr_dslxt_success
=1;
181 l
->right
= t
->left
; /* assemble */
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
;
195 n
= (lxt2_wr_dslxt_Tree
*) calloc (1, sizeof (lxt2_wr_dslxt_Tree
));
197 fprintf(stderr
, "dslxt_insert: ran out of memory, exiting.\n");
203 n
->left
= n
->right
= NULL
;
206 t
= lxt2_wr_dslxt_splay(i
,t
);
207 dir
= strcmp(i
,t
->item
);
218 } else { /* We get here if it's already in the tree */
219 /* Don't add it again */
225 /************************ splay ************************/
228 * functions which emit various big endian
231 static int lxt2_wr_emit_u8(struct lxt2_wr_trace
*lt
, int value
)
233 unsigned char buf
[1];
236 buf
[0] = value
& 0xff;
237 nmemb
=fwrite(buf
, sizeof(char), 1, lt
->handle
);
243 static int lxt2_wr_emit_u16(struct lxt2_wr_trace
*lt
, int value
)
245 unsigned char buf
[2];
248 buf
[0] = (value
>>8) & 0xff;
249 buf
[1] = value
& 0xff;
250 nmemb
= fwrite(buf
, sizeof(char), 2, lt
->handle
);
256 static int lxt2_wr_emit_u32(struct lxt2_wr_trace
*lt
, int value
)
258 unsigned char buf
[4];
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
);
271 static int lxt2_wr_emit_u64(struct lxt2_wr_trace
*lt
, int valueh
, int valuel
)
275 if((rc
=lxt2_wr_emit_u32(lt
, valueh
)))
277 rc
=lxt2_wr_emit_u32(lt
, valuel
);
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
290 static int gzwrite_buffered(struct lxt2_wr_trace
*lt
)
294 if(lt
->gzbufpnt
> LXT2_WR_GZWRITE_BUFFER
)
296 rc
= gzwrite(lt
->zhandle
, lt
->gzdest
, lt
->gzbufpnt
);
304 static void gzflush_buffered(struct lxt2_wr_trace
*lt
, int doclose
)
308 gzwrite(lt
->zhandle
, lt
->gzdest
, lt
->gzbufpnt
);
312 gzflush(lt
->zhandle
, Z_SYNC_FLUSH
);
318 gzclose(lt
->zhandle
);
323 static int lxt2_wr_emit_u8z(struct lxt2_wr_trace
*lt
, int value
)
327 lt
->gzdest
[lt
->gzbufpnt
++] = value
& 0xff;
329 nmemb
=gzwrite_buffered(lt
);
336 static int lxt2_wr_emit_u16z(struct lxt2_wr_trace
*lt
, int value
)
340 lt
->gzdest
[lt
->gzbufpnt
++] = (value
>>8) & 0xff;
341 lt
->gzdest
[lt
->gzbufpnt
++] = value
& 0xff;
342 nmemb
= gzwrite_buffered(lt
);
349 static int lxt2_wr_emit_u24z(struct lxt2_wr_trace
*lt
, int value
)
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
);
363 static int lxt2_wr_emit_u32z(struct lxt2_wr_trace
*lt
, int value
)
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
);
379 static int lxt2_wr_emit_u64z(struct lxt2_wr_trace
*lt
, int valueh
, int valuel
)
383 if((rc
=lxt2_wr_emit_u32z(lt
, valueh
)))
385 rc
=lxt2_wr_emit_u32z(lt
, valuel
);
392 static int lxt2_wr_emit_stringz(struct lxt2_wr_trace
*lt
, char *value
)
397 rc
&=lxt2_wr_emit_u8z(lt
, *value
);
404 * hash/symtable manipulation
406 static int lxt2_wr_hash(const char *s
)
410 unsigned int h
=0, h2
=0, pos
=0, g
;
415 h2
-=((unsigned int)ch
+(pos
++)); /* this handles stranded vectors quite well.. */
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
);
442 static struct lxt2_wr_symbol
*lxt2_wr_symfind(struct lxt2_wr_trace
*lt
, const char *s
)
445 struct lxt2_wr_symbol
*temp
;
448 if(!(temp
=lt
->sym
[hv
])) return(NULL
); /* no hash entry, add here wanted to add */
452 if(!strcmp(temp
->name
,s
))
454 return(temp
); /* in table already */
456 if(!temp
->next
) break;
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
)
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
);
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
);
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;
522 while(lastch
!=s
->name
)
535 static void lxt2_wr_emitfacs(struct lxt2_wr_trace
*lt
)
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
;
557 for(i
=0;i
<lt
->numfacs
;i
++)
559 lt
->sorted_facs
[i
] = s
;
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
];
580 prefcache
[prefs_encountered
] = lt
->sorted_facs
[i
];
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
;
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
];
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) */
633 lt
->zfacname_size
= lt
->position
;
634 lt
->zhandle
= gzdopen(dup(fileno(lt
->handle
)), "wb9");
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
);
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"))))
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 */
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';
724 void lxt2_wr_set_break_size(struct lxt2_wr_trace
*lt
, off_t siz
)
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
)
745 void lxt2_wr_set_partial_on(struct lxt2_wr_trace
*lt
, int zipmode
)
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
);
764 while(s
->aliased_to
) /* find root alias */
769 s
->partial_preference
= 1;
776 * enable/disable checkpointing (for smaller files)
778 void lxt2_wr_set_checkpoint_off(struct lxt2_wr_trace
*lt
)
782 lt
->no_checkpoint
= 1;
786 void lxt2_wr_set_checkpoint_on(struct lxt2_wr_trace
*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
)
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
);
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
;
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
));
846 s
->flags
= flags
&(~LXT2_WR_SYM_F_ALIAS
); /* aliasing makes no sense here.. */
852 s
->len
= (msb
<lsb
) ? (lsb
-msb
+1) : (msb
-lsb
+1);
855 if(flags
&LXT2_WR_SYM_F_DOUBLE
)
857 s
->value
= strdup("NaN");
861 if(flags
& LXT2_WR_SYM_F_INTEGER
)
866 s
->value
= malloc(s
->len
+ 1);
867 memset(s
->value
, lt
->initial_value
, s
->len
);
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
;
886 if((len
=strlen(name
)) > lt
->longestname
) lt
->longestname
= len
;
887 lt
->numfacbytes
+= (len
+1);
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
;
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 */
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 */
926 sa
->symchain
= lt
->symchain
;
930 if((len
=strlen(alias
)) > lt
->longestname
) lt
->longestname
= len
;
931 lt
->numfacbytes
+= (len
+1);
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
);
963 char *tname
= malloc(len
+ 30);
970 if(lt
->lxtname
[i
]=='.') break;
975 sprintf(tname
, "%s_%03d.lxt", lt
->lxtname
, ++lt
->break_number
);
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 */
990 clone
= fopen(lt
->lxtname
, "rb");
992 { /* this should never happen */
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
))
1008 fread(buf
, seg
, 1, clone
);
1009 fwrite(buf
, seg
, 1, f2
);
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;
1034 if(lt
->flushtime
== lt
->lasttime
)
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
;
1051 partial_iter
= lt
->numfacs
;
1054 if(!lt
->timegranule
)
1056 int attempt_break_state
= 2;
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
--;
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 */
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
);
1088 lt
->zpackcount_cumulative
= 0;
1095 for(iter
=0; iter
<lt
->numfacs
; iter
=iter_hi
)
1097 unsigned int total_chgs
;
1098 unsigned int partial_length
;
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
;
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; }
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 */
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 */
1166 lt
->zhandle
= gzdopen(dup(fileno(lt
->handle
)), lt
->zmode
);
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
);
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
++)
1191 s
=lt
->sorted_facs
[j
];
1192 lt
->mapdict
= lxt2_wr_ds_splay (s
->msk
, lt
->mapdict
);
1193 val
= lt
->mapdict
->val
;
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
++)
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;
1227 if(using_partial_zip
)
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
);
1244 gzflush_buffered(lt
, 0);
1246 } /* ...for(iter) */
1254 early_flush
= (ftello(lt
->handle
) >= lt
->break_size
);
1261 if((lt
->timegranule
>=lt
->maxgranule
)||(do_finalize
)||(early_flush
))
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 */
1276 lt
->zhandle
= gzdopen(dup(fileno(lt
->handle
)), lt
->zmode
);
1280 /* fprintf(stderr, "reached granule %d, finalizing block for section %d\n", lt->timegranule, lt->numsections); */
1283 /* finalize string dictionary */
1284 lxt2_wr_emit_u8z(lt
, LXT2_WR_GRAN_SECT_DICT
);
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); */
1294 fprintf(stderr
, "internal error line %d\n", __LINE__
);
1298 lxt2_wr_emit_stringz(lt
, ds
->item
);
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); */
1315 fprintf(stderr
, "internal error line %d\n", __LINE__
);
1319 #if LXT2_WR_GRANULE_SIZE > 32
1320 lxt2_wr_emit_u64z(lt
, (dt
->item
>>32)&0xffffffff, dt
->item
&0xffffffff);
1322 lxt2_wr_emit_u32z(lt
, dt
->item
);
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
)
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
);
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
);
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); */
1391 lt
->flush_valid
= 1;
1392 lt
->flushtime
= lt
->lasttime
;
1397 int lxt2_wr_set_time64(struct lxt2_wr_trace
*lt
, lxttime_t timeval
)
1405 if(timeval
> lt
->maxtime
)
1411 if(!lt
->flush_valid
)
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
;
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"); */
1454 lxt2_wr_set_dumpoff(lt
);
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
)
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
);
1482 /* fprintf(stderr, "done initial value burst timepos==0, timegranule==0\n"); */
1485 lt
->granule_dirty
= 1;
1494 * sets trace timescale as 10**x seconds
1496 void lxt2_wr_set_timescale(struct lxt2_wr_trace
*lt
, int timescale
)
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
)
1513 if(!maxgranule
) maxgranule
= ~0;
1514 lt
->maxgranule
= maxgranule
;
1520 * Sets bracket stripping (useful for VCD conversions of
1523 void lxt2_wr_symbol_bracket_stripping(struct lxt2_wr_trace
*lt
, int doit
)
1527 lt
->do_strip_brackets
= (doit
!=0);
1533 static char *lxt2_wr_expand_integer_to_bits(unsigned int len
, int value
)
1545 *(p
++) = '0' | ((value
& (1<<(len
-i
)))!=0);
1553 int lxt2_wr_emit_value_int(struct lxt2_wr_trace
*lt
, struct lxt2_wr_symbol
*s
, unsigned int row
, int value
)
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
)
1568 if((!lt
)||(lt
->blackout
)||(!s
)||(row
)) return(rc
);
1572 lxt2_wr_emitfacs(lt
);
1577 lxt2_wr_set_time(lt
, 0);
1581 while(s
->aliased_to
) /* find root alias if exists */
1586 if(s
->flags
&LXT2_WR_SYM_F_DOUBLE
)
1592 sprintf(d_buf
, "%.16g", value
);
1593 if(!strcmp(d_buf
, s
->value
)) return(rc
);
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
);
1611 lt
->dict_curr
->next
= lt
->dict
;
1612 lt
->dict_curr
= lt
->dict
;
1616 lt
->dict_head
= lt
->dict_curr
= lt
->dict
;
1619 idx
= lt
->num_dict_entries
+ LXT2_WR_DICT_START
;
1620 lt
->num_dict_entries
++;
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
;
1636 s
->chg
[s
->chgpos
-1] = idx
;
1639 lt
->granule_dirty
= 1;
1646 int lxt2_wr_emit_value_string(struct lxt2_wr_trace
*lt
, struct lxt2_wr_symbol
*s
, unsigned int row
, char *value
)
1650 if((!lt
)||(lt
->blackout
)||(!s
)||(!value
)||(row
)) return(rc
);
1654 lxt2_wr_emitfacs(lt
);
1659 lxt2_wr_set_time(lt
, 0);
1663 while(s
->aliased_to
) /* find root alias if exists */
1668 if(s
->flags
&LXT2_WR_SYM_F_STRING
)
1673 if(!strcmp(value
, s
->value
)) return(rc
);
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
);
1691 lt
->dict_curr
->next
= lt
->dict
;
1692 lt
->dict_curr
= lt
->dict
;
1696 lt
->dict_head
= lt
->dict_curr
= lt
->dict
;
1699 idx
= lt
->num_dict_entries
+ LXT2_WR_DICT_START
;
1700 lt
->num_dict_entries
++;
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
;
1716 s
->chg
[s
->chgpos
-1] = idx
;
1719 lt
->granule_dirty
= 1;
1726 int lxt2_wr_emit_value_bit_string(struct lxt2_wr_trace
*lt
, struct lxt2_wr_symbol
*s
, unsigned int row
, char *value
)
1734 if((!lt
)||(lt
->blackout
)||(!s
)||(!value
)||(!*value
)||(row
)) return(rc
);
1738 lxt2_wr_emitfacs(lt
);
1743 lxt2_wr_set_time(lt
, 0);
1747 while(s
->aliased_to
) /* find root alias if exists */
1752 valuelen
= strlen(value
); /* ensure string is proper length */
1753 if(valuelen
== s
->len
)
1755 vfix
= alloca(s
->len
+1);
1756 strcpy(vfix
, value
);
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
);
1771 memcpy(vfix
, value
, s
->len
);
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
)))
1814 case '0': idx
= LXT2_WR_ENC_0
; break;
1815 case '1': idx
= LXT2_WR_ENC_1
; break;
1817 case 'x': idx
= LXT2_WR_ENC_X
; break;
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
++)
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
;
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);
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);
1861 unsigned int intval_old
= 0, intval_new
= 0;
1864 for(i
=0;i
<s
->len
;i
++)
1867 if((ch
!='0')&&(ch
!='1')) goto idxchk
;
1869 intval_new
|= ((unsigned int)(ch
&1));
1872 if((ch
!='0')&&(ch
!='1')) goto idxchk
;
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
; }
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
; }
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
);
1913 lt
->dict_curr
->next
= lt
->dict
;
1914 lt
->dict_curr
= lt
->dict
;
1918 lt
->dict_head
= lt
->dict_curr
= lt
->dict
;
1921 idx
= lt
->num_dict_entries
+ LXT2_WR_DICT_START
;
1922 lt
->num_dict_entries
++;
1926 idx
= lt
->dict
->val
+ LXT2_WR_DICT_START
;
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
;
1940 s
->chg
[s
->chgpos
-1] = idx
;
1943 strncpy(s
->value
, value
, s
->len
);
1945 lt
->granule_dirty
= 1;
1955 void lxt2_wr_set_dumpoff(struct lxt2_wr_trace
*lt
)
1957 struct lxt2_wr_symbol
*s
;
1959 if((lt
)&&(!lt
->blackout
))
1963 lxt2_wr_emitfacs(lt
);
1968 lxt2_wr_set_time(lt
, 0);
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
;
1984 s
->chg
[s
->chgpos
-1] = LXT2_WR_ENC_BLACKOUT
;
1992 lt
->granule_dirty
= 1;
1997 void lxt2_wr_set_dumpon(struct lxt2_wr_trace
*lt
)
2000 struct lxt2_wr_symbol
*s
;
2002 if((lt
)&&(lt
->blackout
))
2009 if(s
->flags
&LXT2_WR_SYM_F_DOUBLE
)
2012 s
->value
= strdup("0"); /* will cause mismatch then flush */
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 */
2028 s
->value
= calloc(1, 1*sizeof(char));
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
)
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");
2062 * flush the trace...
2064 void lxt2_wr_flush(struct lxt2_wr_trace
*lt
)
2068 if((lt
->timegranule
)||(lt
->timepos
> 0))
2070 if(lt
->granule_dirty
)
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
)
2087 if(lt
->granule_dirty
)
2090 lxt2_wr_flush_granule(lt
, 1);
2095 struct lxt2_wr_symbol
*s
= lt
->symchain
;
2096 struct lxt2_wr_symbol
*s2
;
2100 if(s
->name
) { free(s
->name
); }
2101 if(s
->value
) { free(s
->value
); }
2110 free(lt
->sorted_facs
);
2118 * set compression depth
2120 void lxt2_wr_set_compression_depth(struct lxt2_wr_trace
*lt
, unsigned int depth
)
2124 if(depth
> 9) depth
= 9;
2125 sprintf(lt
->zmode
, "wb%d", depth
);