Skip to content

Keep the time steps of a flushed block without value changes - #35

Merged
tbybell merged 2 commits into
gtkwave:mainfrom
marcobrambilla99:fix-empty-flush-times
Nov 9, 2026
Merged

tbybell merged 2 commits into
gtkwave:mainfrom
marcobrambilla99:fix-empty-flush-times

Conversation

@marcobrambilla99

@marcobrambilla99 marcobrambilla99 commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Problem. If fstWriterFlushContext() is called when no value has changed since the last flush, value changes written after it are read back at the wrong times. Example: one 1-bit variable over 400 time steps, flushed at every time step; a change written at time 230 is read back at time 500. A caller that emits time changes without value changes and then asks for a flush, for example at regular intervals, writes such a file.

Cause. The flush itself does nothing, because the block has no value changes. But fstWriterEmitTimeChange() then appends the current time to the time table, as it does after a real flush, where that time starts a new table. Here no new table was started, so the reader takes the absolute time as one more time step, and every later change in the section is shifted.

Fix. fstWriterEmitTimeChange() does not flush a block without value changes: it drops the flush request, and the time table continues.

Test. tests/flush_without_changes.c asks for a flush every 1, 2 and 3 time steps on traces of 1, 2 and 4 variables, so that some blocks have no change. It checks that every change reads back at its time and that the file's end time is the last time step. Without the fix the test fails; with it, the test passes with gcc 13 and clang 18, also with AddressSanitizer and UndefinedBehaviorSanitizer and with ThreadSanitizer. The rest of the suite gives the same results as on main: under ThreadSanitizer write_error reports a data race in the parallel mode (fixed by #36), and under gcc's UndefinedBehaviorSanitizer empty_file and mask_no_variables report a null pointer with a length of 0 passed to fwrite().

AI-assisted (Claude Opus 5.5)

Problem: when fstWriterFlushContext() is called and no value changed since
the last flush, the value changes written after it are read back at wrong
times. The flush itself returns at once, since the block has no value
changes, but fstWriterEmitTimeChange() then appends the current time to the
time table as if a new table had been started. The reader takes that
absolute time as one more time step, and every later change of the section
is read back at a later time than it was written: a 1-bit variable changed
at time 230 is read back at time 500. A simulator that flushes the file at
regular intervals, as for $dumpflush, meets this as soon as one interval
has no change.

Solution: fstWriterEmitTimeChange() does not flush a block without value
changes. The flush request is dropped and the time table goes on.

tests/flush_without_changes.c asks for a flush every 1, 2 and 3 time steps
of 1, 2 and 4 variables, so that some blocks have no change, and checks
that every change reads back at its time and that the end time is the last
time step.

Signed-off-by: Marco Brambilla <marco@hairyotter.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tbybell
tbybell merged commit f3cbc43 into gtkwave:main Nov 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants