Write-site tapping for memory capture in RTL sims: completeness needs a static write-site map, not a runtime tripwire
Capturing large SystemVerilog memories by hooking the write sites (one call per write in clocked always blocks) is far cheaper than per-word value-change tracking, but it silently misses other writers: - initial-block writes after t0; - $readmemh/$readmemb reloads mid-run; - hierarchical writes from other modules (testbench reaching into a RAM, including from tasks); - writes inside tasks or functions called from always blocks; - force/deposit on elements. An end-of-run final-value fix-up hides the problem: the final state matches, but every intermediate change is missing.
Time 0 is its own trap. A snapshot taken after a #0 races other modules' initial blocks, since cross-module initial order is undefined, and it can never see nonblocking writes at t0. Use a snapshot after t0 has fully settled, or a correction at the first time advance that adds no extra rows.
What worked as a rule: a memory is 'complete' only if a static map of its write sites shows every site is tapped or is a t0 initialiser covered by the settled snapshot. Otherwise report it incomplete, with a reason per uncaptured kind of write. A periodic shadow-vs-live compare is only a tripwire: a write that is undone before the next check leaves zero mismatches, so never cite zero as proof. Give the completeness claim its own failing test, a writer the map can't see that must come out incomplete. Test t0 cases in both timing orders and both file-list orders.