I’ve created a C block that successfully stops the sim with an exit(retval) in the code. It works!!!
However, when I run the sim with multiple stepping, it exits the entire sim and not just the step that is being run.
Is there a means to stop the step but not the entire multi-step run from the C-block?
I’m not sure why you would want to use exit() absent some extraordinary condition (like file I/O failures which your code likely doesn’t do). But, you could, of course, reduce the sim time to something less than when your code would otherwise abort to allow all of the steps to complete.
Thank you for the reply and, of course, for QSpice.
Just to let you know why I’m interested in exiting a step prematurely but not the sim.
With QSpice’s ability to do multiple dimensional (parameter) stepping, it allows me to perform “what-if” experiments. I can use more than one parameter to step through.
My sim has either a “PASS” or “FAIL” bounds I am testing. Once it reaches this bounds, it doesn’t need to proceed any further on the step. However it must continue on the next step in the sequence to see if that set of parameters is a better fit.
The multi-dimensional step’d sim I was running had over 30K steps with a .tran of 4 seconds. The sim took over an hour to run and the .meas statements with plotting took at least another hour.
However, many of the steps resolved to the bounds I mentioned above in less than 1 second of .tran time. If I could have exited the step early, I could have saved many minutes of real sim execution time.
See my reply to Mike about why I’m looking for a way to exit the current step execution but continue on to the next step.
But, you could, of course, reduce the sim time to something less than when your code would otherwise abort to allow all of the steps to complete.
Humm…
Do you mean I can dynamically change the .tran runtime on the fly, let’s say, in a C block?
I know the current sim time is fed into the C block call. However, I didn’t think that I could change it to be accepted by the rest of the sim execution engine.
No, a C-block doesn’t have access to the simulation time.
I’m thinking the only way to do it is if I implement a function, say, abort(bool arg), that terminates the current .tran or .dc or .ac or .noise if arg is true. Something that is called from a Behavioral source.
It would be interesting as this feature can stop simulation after steady state is reached, and not necessary only with C-block if implementation is a function for Behavioral source. Looking forward to it.
OK, I implemented it as a behavioral source function. The new function is called AbortSim(double arg). If arg is greater then .5, then the simulation stops and goes to the next step(if any). Otherwise AbortSim() returns the argument in the interest of debugging what input it got.
From a .DLL, you have now two ways of stopping the simulation. You can output a voltage read by behavioral source and have it quit or you can implement the function double MaxExtStepSize() and have it return -1e308. Specifically -1e308. No other number. To implement the function, check the box that reads “Include a double MaxExtStepSize() template” in the Advanced C++ Template Options dialog.
These methods will flush the output files and tidy up the .qraw waveform files appropriately.
Below demonstrates the AbortSim() function for a transient analysis. The function should for .noise, .ac, .dc, as well as .tran.
I ran my multi-dimensional step sim with and without AbortSim().
Here are my results:
AbortSim()
total steps
Sim Time
Post-Process Time
.qraw size
.meas.qraw size
No
1342
53.3 s
61.7 s
474.4M
64K
Yes
1342
44.5 s
36.9 s
48.5M
64K
No
2717
103.4 s
280.0 s
703.7M
130K
Yes
2717
91.7 s
84.0 s
164.2M
130K
No
5002
199.1 s
881.3 s
1742.0 M
239K
Yes
5002
165.9 s
231.0 s
234.4M
239K
The major take-aways is that the ability to abort the sim step once the PASS or FAIL criteria is met results in significant reduction in post-processing time. In the sim used in my example, it was at least a 1/3 reduction using the AbortSim(). The major reduction was in post-processing. This is probably due to the significant reduction in .qraw file size. Aborting the sim stops collecting further data for the step being processed. A smaller file size should make it faster to process .meas commands.
The actual simulation time was only minorly reduced in my case. It would be interesting to get feedback from other’s sims to see if it can be improved upon.
Len
PS: Thanks to Mike for entertaining this feature recommendation. Helping to make this tool even more world-class than it already is.
I just tested the replacement for exit() in a DLL call within a C block. It does work!!!
As you stated, I had to pass -1e308 as a return in the MaxExtStepSize().
I used a instance variable that determined the need to stop in the module’s main dll call.
When MaxExtStepSize() gets called, I pass -1e308 when an abort from the step is need. Otherwise I pass the value needed.
This method also doesn’t require me to wait for multiples of 512 points to be collected to be available for plot data. I can abort immediately and still have plot data logged.
Here’s an example of my MaxExtStepSize() code:
/********************/
extern “C” __declspec(dllexport) double MaxExtStepSize(struct sSTOP *inst)
{
return (inst->stop_evnt != 0 ? -1e308 : 1e308); // implement a good choice of max timestep size that depends on struct sSTOP
}
There’s no attempt to simulate to the exact point where the argument of AbortSim() is just over .5. It just stops at the timestep past where AbortSim() says to stop. That’s actually faster than trying to find the point where AbortSim() becomes true for the first time.
BTW, I misspoke earlier when I said AbortSim() works for .ac and .noise. It’s only for .tran and .dc.