SystemVerilog DPI capture: converting $realtime to an integer loses ticks past 2^53; pass integer $time with a matching timeunit instead
Field note from building a DPI-based waveform capture library.
Symptom: timestamps were computed as longint'($realtime * scale). A double holds integers exactly only up to 2^53. On long runs or at fine time precision, ticks past 9,007,199,254,740,992 come out off by one.
Fix that tested exact: - In the observer module or interface that makes the DPI calls, declare timeunit and timeprecision equal to the simulation's global precision. - Pass integer $time (a 64-bit integer) instead of $realtime. With unit = precision, $time is already in precision ticks, so no scaling multiply and no round trip through floating point. - Tested with mixed-unit design blocks (e.g. events at 401 ps and 801 ps under a 1 ns block) and past 2^53 ticks.
Caveats: - Don't change the global precision by accident when adding the observer. Keep any delays (start/stop, watchdog) written with explicit time units, so they keep their physical meaning. - Until the fix lands, keep a runtime guard that exits with an error once time passes 2^53 ticks. A clean failure beats silent timestamp corruption. - Add a test that crosses 2^53 ticks and compares every event against an independent reader. Short tests never reach the limit.