diff --git a/vpi/lxt2_write.c b/vpi/lxt2_write.c index 60e814363..bcb8f096a 100644 --- a/vpi/lxt2_write.c +++ b/vpi/lxt2_write.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Tony Bybell. + * Copyright (c) 2003-2004 Tony Bybell. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -645,8 +645,8 @@ if((lt)&&(lt->numfacs)) lt->zfacname_predec_size = lt->zpackcount; gzflush_buffered(lt, 1); - fseek(lt->handle, 0L, SEEK_END); - lt->position=ftell(lt->handle); + fseeko(lt->handle, 0L, SEEK_END); + lt->position=ftello(lt->handle); lt->zfacname_size = lt->position - lt->zfacname_size; lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9"); @@ -671,11 +671,12 @@ if((lt)&&(lt->numfacs)) } gzflush_buffered(lt, 1); - fseek(lt->handle, 0L, SEEK_END); - lt->position=ftell(lt->handle); + fseeko(lt->handle, 0L, SEEK_END); + lt->position=ftello(lt->handle); + lt->break_header_size = lt->position; /* in case we need to emit multiple lxt2s with same header */ lt->zfacgeometry_size = lt->position - lt->facgeometry_offset; - fseek(lt->handle, lt->facname_offset + 12, SEEK_SET); + fseeko(lt->handle, lt->facname_offset + 12, SEEK_SET); lxt2_wr_emit_u32(lt, lt->zfacname_size); /* backpatch sizes... */ lxt2_wr_emit_u32(lt, lt->zfacname_predec_size); lxt2_wr_emit_u32(lt, lt->zfacgeometry_size); @@ -695,13 +696,15 @@ struct lxt2_wr_trace *lxt2_wr_init(const char *name) { struct lxt2_wr_trace *lt=(struct lxt2_wr_trace *)calloc(1, sizeof(struct lxt2_wr_trace)); -if(!(lt->handle=fopen(name, "wb"))) +if((!name)||(!(lt->handle=fopen(name, "wb")))) { free(lt); lt=NULL; } else { + lt->lxtname = strdup(name); + lxt2_wr_emit_u16(lt, LXT2_WR_HDRID); lxt2_wr_emit_u16(lt, LXT2_WR_VERSION); lxt2_wr_emit_u8 (lt, LXT2_WR_GRANULE_SIZE); /* currently 32 or 64 */ @@ -715,6 +718,18 @@ return(lt); } +/* + * setting break size + */ +void lxt2_wr_set_break_size(struct lxt2_wr_trace *lt, off_t siz) +{ +if(lt) + { + lt->break_size = siz; + } +} + + /* * enable/disable partial dump mode (for faster reads) */ @@ -938,6 +953,72 @@ return(lxt2_wr_set_time64(lt, lt->maxtime + timeval)); } +/* + * file size limiting/header cloning... + */ +static void lxt2_wr_emit_do_breakfile(struct lxt2_wr_trace *lt) +{ +unsigned int len = strlen(lt->lxtname); +int i; +char *tname = malloc(len + 30); +FILE *f2, *clone; +off_t cnt, seg; +char buf[32768]; + +for(i=len;i>0;i--) + { + if(lt->lxtname[i]=='.') break; + } + +if(!i) + { + sprintf(tname, "%s_%03d.lxt", lt->lxtname, ++lt->break_number); + } + else + { + memcpy(tname, lt->lxtname, i); + sprintf(tname+i, "_%03d.lxt", ++lt->break_number); + } + +f2 = fopen(tname, "wb"); +if(!f2) /* if error, keep writing to same output file...sorry */ + { + free(tname); + return; + } + +clone = fopen(lt->lxtname, "rb"); +if(!clone) + { /* this should never happen */ + fclose(f2); + unlink(tname); + free(tname); + return; + } + +/* clone original header */ +for(cnt = 0; cnt < lt->break_header_size; cnt += sizeof(buf)) + { + seg = lt->break_header_size - cnt; + if(seg > sizeof(buf)) + { + seg = sizeof(buf); + } + + fread(buf, seg, 1, clone); + fwrite(buf, seg, 1, f2); + } + +fclose(clone); +fclose(lt->handle); +lt->handle = f2; +free(tname); +} + + +/* + * emit granule + */ void lxt2_wr_flush_granule(struct lxt2_wr_trace *lt, int do_finalize) { unsigned int idx_nbytes, map_nbytes, i, j; @@ -945,7 +1026,8 @@ struct lxt2_wr_symbol *s; unsigned int partial_iter; unsigned int iter, iter_hi; unsigned char using_partial, using_partial_zip=0; -unsigned int current_iter_pos=0; +off_t current_iter_pos=0; +int early_flush; if(lt->flush_valid) { @@ -969,11 +1051,25 @@ if((using_partial=(lt->partial)&&(lt->numfacs>lt->partial_iter))) partial_iter = lt->numfacs; } - if(!lt->timegranule) { - fseek(lt->handle, 0L, SEEK_END); - lt->current_chunk=lt->position = ftell(lt->handle); + int attempt_break_state = 2; + + do { + fseeko(lt->handle, 0L, SEEK_END); + lt->current_chunk=lt->position = ftello(lt->handle); + + if((lt->break_size)&&(attempt_break_state==2)&&(lt->position >= lt->break_size)&&(lt->position != lt->break_header_size)) + { + lxt2_wr_emit_do_breakfile(lt); + attempt_break_state--; + } + else + { + attempt_break_state = 0; + } + } while(attempt_break_state); + /* fprintf(stderr, "First chunk position is %d (0x%08x)\n", lt->current_chunk, lt->current_chunk); */ lxt2_wr_emit_u32(lt, 0); /* size of this section (uncompressed) */ lxt2_wr_emit_u32(lt, 0); /* size of this section (compressed) */ @@ -1060,8 +1156,8 @@ if(using_partial) if(using_partial_zip) { - fseek(lt->handle, 0L, SEEK_END); - current_iter_pos = ftell(lt->handle); + fseeko(lt->handle, 0L, SEEK_END); + current_iter_pos = ftello(lt->handle); lxt2_wr_emit_u32(lt, 0); /* size of this section (compressed) */ lxt2_wr_emit_u32(lt, partial_length+9); /* size of this section (uncompressed) */ lxt2_wr_emit_u32(lt, iter); /* begin iter of section */ @@ -1130,14 +1226,14 @@ for(j=iter;jhandle, 0L, SEEK_END); - lt->position=ftell(lt->handle); + fseeko(lt->handle, 0L, SEEK_END); + lt->position=ftello(lt->handle); clen = lt->position - current_iter_pos - 12; - fseek(lt->handle, current_iter_pos, SEEK_SET); + fseeko(lt->handle, current_iter_pos, SEEK_SET); lt->zpackcount_cumulative+=lt->zpackcount; @@ -1152,16 +1248,26 @@ if(using_partial_zip) lt->timepos = 0; lt->timegranule++; -if((lt->timegranule>=lt->maxgranule)||(do_finalize)) + +if(lt->break_size) { - unsigned int unclen, clen; + early_flush = (ftello(lt->handle) >= lt->break_size); + } + else + { + early_flush = 0; + } + +if((lt->timegranule>=lt->maxgranule)||(do_finalize)||(early_flush)) + { + off_t unclen, clen; lxt2_wr_ds_Tree *dt, *dt2; lxt2_wr_dslxt_Tree *ds, *ds2; if(using_partial_zip) { - fseek(lt->handle, 0L, SEEK_END); - current_iter_pos = ftell(lt->handle); + fseeko(lt->handle, 0L, SEEK_END); + current_iter_pos = ftello(lt->handle); lxt2_wr_emit_u32(lt, 0); /* size of this section (compressed) */ lxt2_wr_emit_u32(lt, 0); /* size of this section (uncompressed) */ lxt2_wr_emit_u32(lt, ~0); /* control section */ @@ -1233,14 +1339,14 @@ if((lt->timegranule>=lt->maxgranule)||(do_finalize)) if(using_partial_zip) { - unsigned int clen; + off_t clen; gzflush_buffered(lt, 1); - fseek(lt->handle, 0L, SEEK_END); - lt->position=ftell(lt->handle); + fseeko(lt->handle, 0L, SEEK_END); + lt->position=ftello(lt->handle); clen = lt->position - current_iter_pos - 12; - fseek(lt->handle, current_iter_pos, SEEK_SET); + fseeko(lt->handle, current_iter_pos, SEEK_SET); lt->zpackcount_cumulative+=lt->zpackcount; lxt2_wr_emit_u32(lt, clen); @@ -1251,8 +1357,8 @@ if((lt->timegranule>=lt->maxgranule)||(do_finalize)) gzflush_buffered(lt, 1); } - fseek(lt->handle, 0L, SEEK_END); - lt->position=ftell(lt->handle); + fseeko(lt->handle, 0L, SEEK_END); + lt->position=ftello(lt->handle); /* fprintf(stderr, "file position after dumping dict: %d 0x%08x\n", lt->position, lt->position); */ unclen = lt->zpackcount; @@ -1260,7 +1366,7 @@ if((lt->timegranule>=lt->maxgranule)||(do_finalize)) /* fprintf(stderr, "%d/%d un/compressed bytes in section\n", unclen, clen); */ - fseek(lt->handle, lt->current_chunk, SEEK_SET); + fseeko(lt->handle, lt->current_chunk, SEEK_SET); if(using_partial_zip) { lxt2_wr_emit_u32(lt, lt->zpackcount_cumulative); @@ -1434,7 +1540,7 @@ if(len>32) len=32; len--; -for(i=0;i #include +#if defined _MSC_VER || defined __MINGW32__ +#define fseeko fseek +#define ftello ftell +#endif + + #define LXT2_WR_HDRID (0x1380) #define LXT2_WR_VERSION (0x0001) @@ -50,7 +56,11 @@ typedef uint64_t lxttime_t; #ifndef _MSC_VER - #define LXT2_WR_LLD "%lld" + #ifdef __MINGW32__ + #define LXT2_WR_LLD "%I64d" + #else + #define LXT2_WR_LLD "%lld" + #endif #define LXT2_WR_LLDESC(x) x##LL #define LXT2_WR_ULLDESC(x) x##ULL #else @@ -94,7 +104,7 @@ enum LXT2_WR_Encodings { LXT2_WR_ENC_BLACKOUT, - LXT2_WR_DICT_START, + LXT2_WR_DICT_START }; /* @@ -137,10 +147,10 @@ unsigned int num_map_entries; lxt2_wr_ds_Tree *mapdict_head; lxt2_wr_ds_Tree *mapdict_curr; -unsigned int position; -unsigned int zfacname_predec_size, zfacname_size, zfacgeometry_size; -unsigned int zpackcount, zpackcount_cumulative; -unsigned int current_chunk, current_chunkz; +off_t position; +off_t zfacname_predec_size, zfacname_size, zfacgeometry_size; +off_t zpackcount, zpackcount_cumulative; +off_t current_chunk, current_chunkz; struct lxt2_wr_symbol *sym[LXT2_WR_SYMPRIME]; struct lxt2_wr_symbol **sorted_facs; @@ -150,7 +160,7 @@ int numfacbytes; int longestname; int numsections, numblock; -unsigned int facname_offset, facgeometry_offset; +off_t facname_offset, facgeometry_offset; lxttime_t mintime, maxtime; unsigned int timegranule; @@ -184,6 +194,11 @@ char initial_value; char zmode[4]; /* fills in with "wb0".."wb9" */ unsigned int gzbufpnt; unsigned char gzdest[LXT2_WR_GZWRITE_BUFFER + 4]; /* enough for zlib buffering */ + +char *lxtname; +off_t break_size; +off_t break_header_size; +unsigned int break_number; }; @@ -242,6 +257,9 @@ struct lxt2_wr_trace * lxt2_wr_init(const char *name); void lxt2_wr_flush(struct lxt2_wr_trace *lt); void lxt2_wr_close(struct lxt2_wr_trace *lt); + /* for dealing with very large traces, split into multiple files approximately "siz" in length */ +void lxt2_wr_set_break_size(struct lxt2_wr_trace *lt, off_t siz); + /* 0 = no compression, 9 = best compression, 4 = default */ void lxt2_wr_set_compression_depth(struct lxt2_wr_trace *lt, unsigned int depth); @@ -261,7 +279,7 @@ struct lxt2_wr_symbol * lxt2_wr_symbol_add(struct lxt2_wr_trace *lt, const char struct lxt2_wr_symbol * lxt2_wr_symbol_alias(struct lxt2_wr_trace *lt, const char *existing_name, const char *alias, int msb, int lsb); void lxt2_wr_symbol_bracket_stripping(struct lxt2_wr_trace *lt, int doit); - /* each granule is LXT2_WR_GRANULE_SIZE (32 or 64) timesteps, default is 8 per section */ + /* each granule is LXT2_WR_GRANULE_SIZE (32 or 64) timesteps, default is 256 per section */ void lxt2_wr_set_maxgranule(struct lxt2_wr_trace *lt, unsigned int maxgranule); /* time ops */ diff --git a/vpi/sys_lxt2.c b/vpi/sys_lxt2.c index fba794232..cc42b81c7 100644 --- a/vpi/sys_lxt2.c +++ b/vpi/sys_lxt2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2004 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: sys_lxt2.c,v 1.5 2004/01/21 01:22:53 steve Exp $" +#ident "$Id: sys_lxt2.c,v 1.6 2004/02/06 18:23:30 steve Exp $" #endif # include "sys_priv.h" @@ -48,6 +48,7 @@ static enum lxm_optimum_mode_e { LXM_SPEED = 2 } lxm_optimum_mode = LXM_SPEED; +static off_t lxt2_file_size_limit = 0x40000000UL; /* * The lxt_scope head and current pointers are used to keep a scope @@ -424,6 +425,7 @@ static void open_dumpfile(const char*path) lxt2_wr_set_initial_value(dump_file, 'x'); lxt2_wr_set_compression_depth(dump_file, 4); lxt2_wr_set_partial_on(dump_file, 1); + lxt2_wr_set_break_size(dump_file, lxt2_file_size_limit); atexit((void(*)(void))close_dumpfile); } @@ -815,6 +817,9 @@ void sys_lxt2_register() /* * $Log: sys_lxt2.c,v $ + * Revision 1.6 2004/02/06 18:23:30 steve + * Add support for lxt2 break size + * * Revision 1.5 2004/01/21 01:22:53 steve * Give the vip directory its own configure and vpi_config.h *