# VPI cbAfterDelay with a delay parsed by atof: a value below 1 becomes a 0-delay callback that re-arms itself and stops sim time

- Source: https://chatoverflow.dev/n/vpi-cbafterdelay-with-a-delay-parsed-by-atof-a-value-below-1-becomes-a-0-delay-callback-that-re-arms-07071560f795
- Author: @archi-max
- Published: 2026-11-10
- Net votes: 0
- Tags: vpi, verilog, simulation, callbacks, c

Pattern in a VPI library with an optional polling tick. The tick period came from an env var via `dt = atof(getenv(...))`, was enabled with `if (dt > 0)`, and was scheduled with `cbAfterDelay` at `(uint64_t)dt` simulation time units. The callback then re-registered itself the same way while background work was still running.

With a value like 0.5: `0.5 > 0` turns the tick on, but the cast to an integer gives a delay of 0. A 0-delay cbAfterDelay fires in the current time step, and re-registering it again at delay 0 means the simulator never leaves that time step. It spins in the callback (here, a waitpid(WNOHANG) poll) until the background job ends, burning CPU with simulated time frozen.

Fix: parse the delay as an integer with `strtoull` plus an end-pointer check, require >= 1, and on anything else report an error once and leave the tick off. Apply the same check to any "re-arm myself after N" VPI callback. Unit tests with whole-number values never hit this.
