[Trick sharing] Skip the C-block when running on Hypothetical timestep

We all understand that C-block is called at all time right after circuit solver is completed for each timestep. The problem is, Qspice often run multiple hypothetical timestep before commiting to a certain timestep and store the waveform result in .qraw file.

For C-block that doesnt have anything to do with time control or dont use Trunc(), most of the time you may not want to call your function unless you are running on an APPROVED timestep.

So, we can use this trick to add
if(*ForKeeps == 0) return;
on the first line to quickly skip the C-block easily when we dont want it to be executed.

Cheers,
Arief,

2 Likes

What is the difference compared to right-clicking the DLL symbol to disable the block?

Very different, when you disable the block then the whole C-block will never be called ever

What I shared is, lets say for my analyzer (FRA, THD, and EMI), these blocks only need to execute get executed when actual timestep is used (and real actual waveform).

When is called from within hypothetical timestep, the Cblock can immediately exit this evaluation function without ever need to go through the long calculations and wasting cycle.

This is particularly important for my EMI analyzer where I call FFT with large data size repeatedly.

Oh, I see—you are not disabling your block entirely, but only during the hypothetical state. Your suggestion looks very useful if the DLL is purely for analysis and does not actively control signals in the circuit.

Didn’t you already discuss/document this?

@KSKelvin 颱風假當你休息一下 :laughing:

@RDunn too many features in Qspice, that sometimes thing are just not easy to keep track of…

1 Like

The use case for *ForKeeps in this post is interesting, which I initially didn’t realize. @physicboy posted his EMI receiver project here, where the C code doesn’t rely on Trunc():
[Share and looking for feedback] CISPR16 EMI receiver emulation - QSPICE - Qorvo Tech Forum

Since other DLLs or devices can trigger hypothetical calls, and this EMI receiver requires heavy computation, @physicboy noted that executing this code during a hypothetical call increases simulation time. Therefore, he used if(*ForKeeps == 0) return; to skip the execution of this code during hypothetical calls.

In general, we don’t do that because if the code is part of the circuit, skipping it entirely during a hypothetical call will alter the circuit simulation results in hypothetical call and mess up the timestep estimation (I guess it will… :rofl:). However, because this EMI receiver just receives signal, skipping the code won’t mess up the hypothetical state.

Since this situation is less common, that is why I didn’t initially understand the need for it. But it is a very interesting idea to speed up simulations by not wasting time on hypothetical calls if:

  • The code will not alter the circuit’s behavior
  • The code computation is heavy (I guess you simulation time difference is negligible for simple code)

I think the most common use case for *ForKeeps is to help identify when a transient simulation step truly begins, or to skip writing to an external file by identifying that the call is not in a hypothetical state. In these cases, the goal is not to skip the entire code block.

Actually majority of my code doesn’t use Trunc() at all. As we all agree, Trunc() is used to find non predetermined timing edge.

For digital control + PWM, I can predetermined the exact timing edge. Then, I actively aim to hit the sampling point and PWM timing edge using MaxTimeStep() only. Skipping Trunc() also help speeding up the runtime significantly.

So, in that control design case, I can also use *ForKeeps to skip my eval_func() as well. Though, the math for digital control is comparatively a lot less heavy than EMI receiver (FFT, and those repetitive spectrum magnitude, intermediate filter, and the final detectors) . Thus, adding *ForKeeps will be negligible.

1 Like