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.
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.
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⌠). 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.