From ba36e3bdc9066cc196deeb1a994e2919c8f8b7b2 Mon Sep 17 00:00:00 2001 From: Alfredo Tomasini Date: Wed, 12 Aug 2026 14:35:54 +0200 Subject: [PATCH] Prevent VSRC PWL glitches: The fold is exact on paper, but floor() on a ratio of doubles can leave time a few ulp PAST the last point: measured at 7.5e-23 s after about 1900 periods of a 1 ns clock. The search below then matches no segment at all, drops out of the loop without assigning, and the source silently keeps value's initialiser of 0 V for that one timepoint. On a clock that is a dropout to zero in the middle of an edge -- a glitch a downstream flip-flop reads as two extra edges, which is far worse than the tiny timing error it comes from. Clamp so the last segment always matches. --- src/spicelib/devices/isrc/isrcload.c | 3 +++ src/spicelib/devices/vsrc/vsrcload.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/spicelib/devices/isrc/isrcload.c b/src/spicelib/devices/isrc/isrcload.c index 13a19f68e..fc9a7a17b 100644 --- a/src/spicelib/devices/isrc/isrcload.c +++ b/src/spicelib/devices/isrc/isrcload.c @@ -322,6 +322,9 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt) time -= here->ISRCcoeffs[here->ISRCrBreakpt]; time -= period * floor(time / period); time += here->ISRCcoeffs[here->ISRCrBreakpt]; + /* prevent glitches */ + if (time > end_time) + time = end_time; } else { value = diff --git a/src/spicelib/devices/vsrc/vsrcload.c b/src/spicelib/devices/vsrc/vsrcload.c index 1dee79108..90eb7f64b 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -351,6 +351,9 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt) time -= here->VSRCcoeffs[here->VSRCrBreakpt]; time -= period * floor(time / period); time += here->VSRCcoeffs[here->VSRCrBreakpt]; + /* prevent glitches */ + if (time > end_time) + time = end_time; } else { value = here->VSRCcoeffs[here->VSRCfunctionOrder - 1];