GTKWave .gtkw save files: flag bits, group encoding, zoom formula (verified from source and real files)
Writing or reading GTKWave .gtkw files from another viewer. Facts checked against gtkwave/gtkwave source (src/analyzer.h, src/savefile.c, src/wavewindow.c calczoom) and real GTKWave-written files:
- @<hex> sets trace flags; they PERSIST for every following trace line until the next @ (des.gtkw example: @22 before [color] 7 / top.clk makes clk hex).
- Flag bit positions (enum TraceEntFlagBits): HIGHLIGHT 0, HEX 1, DEC 2, BIN 3, OCT 4, RJUSTIFY 5, INVERT 6, REVERSE 7, EXCLUDE 8, BLANK 9, SIGNED 10, ASCII 11, COLLAPSED 12, FTRANSLATED 13, PTRANSLATED 14, ANALOG_STEP 15, ANALOG_INTERP 16, REAL 18, CLOSED 22, GRP_BEGIN 23, GRP_END 24, ... TTRANSLATED 28, ENUM 32, FFO 34. Flags exceed 32 bits: use BigInt in JS, not &.
- Typical values: @28 binary, @22 hex, @24 decimal, @424 signed decimal, @30 octal, @200 comment/blank line (-text).
- Groups: open = @800200 -Name ... @1000200 -Name; CLOSED group = @c00200 begin and @1401200 end (end also has COLLAPSED; begin does not). Verified in GTKWave 3.3.103 output.
- (31)top.v[31:0] = a single bit of a vector.
- *<zoom> <primary marker|-1> <26 named markers A..Z, -1 unset>; names via [markername] A<alias> or [markername_long] A <alias>.
- Times ([timestart], markers) are in the dump own ticks.
- Zoom: nsperframe = max(1, zoombase^-zoom), ticks per pixel = nsperframe/200, zoombase default 2 (rc zoombase, clamped 1.5..10). So zoom = -log2(200 * ticksPerPixel). Written with %f (6 decimals) so round trips are ~1e-6 relative.
- [color] n applies to the next trace only: 1 red, 2 orange, 3 yellow, 4 green, 5 blue, 6 indigo, 7 violet.
- Public GTKWave-written fixtures: gtkwave repo examples/des.gtkw and examples/transaction.gtkw; GitHub code search "@1401200" extension:gtkw finds many real files with closed groups.