Does a C block have knowledge of what step is being run?

I’m creating a C block to be used with a multi-step sim.

The C Block will be more useful if I can tell what step is being processed in the .cpp code.

Is the current step number being passed or exposed to the block?

Len

I think you can pass the step value into the input of the C-block

As @physicboy noted, you can pass the step value into the c-block as an attribute.

–robert

Thanks to @physicboy and @RDunn .

Yes I can pass the step VALUE. That has no benefit to me. I need to pass the step # being processed.

For example, if step #1 is passed or exposed in the C code, I can initialize structures, file access … etc.

Len

Gee, Len. I’m truly curious what you’re trying to do. Please do share.

In the meantime, let’s consider possible solutions to this dire problem.

  1. Define separate values for the step parameters. Use them in the .step command and also pass them as individual attributes to the C-Block. In the C-Block, calculate which step was invoked calculating backwards from the passed attributes.
  2. Define the .step command with integral values. Use a user-defined function to pre-calculate the component value to step or define it in the component value.

The latter look like this:

  1. Let’s say that you’re trying to create a separate file from your C-Bock for each step. You want each file to be named differently. Within the C-Block, just test to see if file1.txt exists. If so, test for file2.txt. And so on.

The problem with #3 is that, AFAIK, there is no guarantee that QSpice will execute the steps serially and sequentially. While I’m pretty sure that it does execute steps serially/sequentially, I see no reason that it might not run all steps “simultaneously” or in arbitrary order on multiple CPUs.

I can imagine much more complicated solutions. Again, maybe share what you’re trying to do and why the C-Block code needs to know what step it’s evaluating.

–robert

Robert,

What I’m trying to do is create a “logger” C-block that takes three data inputs and a trigger input.

It would take the values of the three inputs on the rising trigger and dump them as comma-delimited values to a file.

The issue with knowing if the first step is being executed is to delete the “old” file and create the new of the same name. If this is not done, the csv data of the new sim run is appended to the old file data even if you modified the sim netlist.

I’ve got this C block working however without the old-file-delete-new-file-create sequence.

Len

You can add timestamp on the file name…

log_20231116_1234.txt

@physicboy ,

I don’t see where placing a timestamp on the file has value.

Knowing when the first step of a multi-dimensional step sim is run, I then can delete the file the previously existed.

Len

What call are you making to open the file? fopen() using “w” overwrites the existing data which sounds like what you need.

If you aren’t using fopen(), all of the library file I/O stuff has open with overwrite feature.

–robert

I am totally at lost with your goal.

Can you give example on what kind of output you really want?

If you truly must delete, try remove() in cstdio. link

–robert

Robert,

I’m using fopen(, “a”). // Append writes on open

Because I’m using stepping, each step starts time (t) at 0.0000s. If I used “w” instead of “a”, it would overwrite the previous step data with the current step data. Therefore, only the last step data is logged.

This is why I use “a”. The file is retained with the previous step data accumulated.

However, if I restart the entire sim, the log file data that I created from the previous sim run is retained and the new sim data steps are just appended to the end of the file. Not good. This is why I’m trying to determine the step number current being run. If you look at the “Output” window on a stepped sim, Mike details the " of steps: .step <step_param1>=<step_param1_val> <step_param2>=<step_param2_val> <step_param3>=<step_param3_val>.

Therefore the sim has knowledge of which step is being executed .

My end goal is to share a “logger” C-block with all users. The logger can be triggered to store data from the sim into a csv file AS THE SIMULATION IS RUNNING,

You’re wondering why don’t I use plot data on the standard plotting window? I can, However you have to visually detect the PASS/FAIL criteria. If you’ve ever worked with multi-dimensional stepping, this can become very cumbersome. I’ve used .meas statements and .plot meas statements to visually see the PASS/FAIL based on the .meas criteria. Note: I’ve run sims that have 40K steps.

Now, you’re wondering why I don’t use the .meas and .plot meas statement. I can. However there is a reason why this is not practical in many cases.

When I’m running my multi-dimensional step sims to “brute force” calculate my “what if” design tests, I get large .qraw files. I’ve generated 4G+ .qraw files that took 20 minutes just to go through the simulation phase. If I have .meas statements, they get processed in the post-processing phase. With a 4G_ .qraw file to parse, it can easily take 3 times the sim phase time to parse for EACH .meas statement listed. With 3 .meas statements I’ve seen post-processing times of sim_phase time * 10. I’ve have post-processing times of over 3 hours. Therefore you add the sim_phase time + the pos-process_time (>3 hours 20mins)

If I use my early pre-release version of the logger C-block to in-line logging of desired data into a .csv file, I can eliminate the .meas statements. The time added to the sim_phase is virtually negligible.
Therefore in the above sim example, my time to achieve the needed data is slightly longer than 20mins.

I think you can see the strategic reason for an in-line logger C-block.

@physicboy, Hopefully this answers your latest question.

Len

Robert,

I know of remove().
The issue is KNOWING when to remove the older file. That is the reason for knowing when the very first step is being executed.

Knowing that the first step is being executed means the sim has been restarted. Then I need to delete the file or use fopen(, “w”) for this step.

Len

Ok, I thought that you wanted each step to have a separate log file. But you want only a single log file that contains data from all steps for a single sim run, right?

–robert

Robert,

Correct. In my current multi-dim step sim, I’m capturing 3 pieces of data on a single trigger. In this case, I’m also Aborting the sim step (AbortSim()) to speed up the total sim with smaller .qraw files.

When I open the collected multi-step data, each line is the desired data along with the step values. This lets me evaluate the “what if” sim test for the best results.

Len

Len,

OK, there’s no documented step # parameter passed to C-Blocks AFAIK. Unless Mike decides to add one, then my prior suggestion, simplified below, is worth trying. (Note that I’m assuming that steps are processed sequentially by QSpice. Seems to be true – not guaranteed by documented QSpice.)

In the C-Block code, if startVal == currVal, this is the first pass. Works for me.


Since you are expecting long runs, maybe a better approach is to run the sim in batch. That removes GUI overhead and might save some few seconds on a long run. @KSKelvin helped me work out the key batch bit so, in batch, you’d simply delete the file before the sim runs. Let me know if that’s of interest.

–robert

Ah its clear…

*I dont have computer now, so cant make the sim to demo

So, I think you can do this:
When you detect that the step is step 1, then you use fopen “w” else use fopen “a”

How to detect if the step is step 1, perhaps you can two inputs in C code to indicate this. One input is the step value, and one input is the expected first step value.

For example

.step param RES 100 1000 50

You can feed your Cblock with the minimum in that step 100, and the actual step value

@RDunn and @physicboy ,

Thanks for your feedback.

I was trying to avoid another input that validates the first step values. For example I would add a “init” or “reset” input that would take a Behavioral Voltage Source. The Equation of the BV would be V=(data0==<data0_1st_step>) & (data1==<data1_1st_step>) & (data2==<data2_1st_step>). [Yes, I’m using a 3–dimensional step sim.]

However if I have too many places to change values it would be too easy to neglect a parameter value needed to changed when I change the step parameters for the next sim run. Hence, having a step # as a variable available to the C-block would be advantageous.

Robert, You mentioned about a batch method available. This might be of interest. I’d like to learn more about it. I’d like to try a batch version of my current sim as it stands and compare how much sim time savings I can get by ditching the GUI interface.

Having said that, I think it safe to say, most users of this tool will probably “visual” people. The GUI is extremely useful for detecting issues quickly.

Len

I don’t know if this will work for you since you’re doing parameter stepping – but maybe you could try it.
I use the fact that all the variables initialize to zero at the start in order to identify the first step of a simulation & initialize my circuit.

switch( inst->state ) {
      case 0: // Initialization state
         // init your stuff here
         inst->state = 1;
         break;
      case 1: // Operating state
         // Do nothing?
         break;
      default:
         break;
   }

Hi, Emrys.

Where in the code do you put this switch statement?

–robert