Variable arrays as instance parameters for C blocks

Hello everyone

For example: float *freq={0.0, 0.3, 0.4, 1.0}. Can be set in stone from the beginning of the simulation until the end of it (but allow changing between .steps). It’s not something mandatory but, it would certainly make things easier than having float f1=x, float f2=y, ....

The struct uData (and my tests) hint it’s not possible but, did someone manage to find a workaround, or maybe it’s planned in the future?

Vlad

Hi, Vlad.

Let’s make sure that I understand the question: You want to pass component attributes into the component that appear in the uData as an array of float values. Is that correct?

If so, I think the answer is no. However, you could pass in a char* freq=“0.0 0.3 0.4 1.0” and then parse it into an array of floats (presumably stored in the per-instance data structure) in the initialization section of the C-Block code.

Does that help?

Hello RDunn

This is one of those “technically, yes” answers. While it can be done, it makes it cumbersome for the users who want to change the value/-s, maybe as a result of calculations (that’s why I mentioned .step). There’s also some minor code bloat (freq may not be the only one) which, let’s say it’s fine, since this is a one-time deal, before the actual simulation.

Vlad

Vlad, I’m a bit confused. You asked (1) is there something like float *freq={0.0, 0.3, 0.4, 1.0} and, if not, (2) is there a workaround?

I gave you my best answers: (1) Not as far as I know and (2) a possible workaround. You then proceeded to complain that the suggested workaround isn’t as sweet as your desired implementation. It might be cumbersome for users if calculations were required. The DLL code might suffer “code bloat.”

Well, duh, Vlad. Workaround. :roll_eyes:

Anyway, here’s some code that solves all of your issues except for the pretty syntax.

  • You can pass in component attributes that resolve parameters (with math) to values.
  • You can grab parameters (calculated with math) directly from the schematic.

The code bloat is about a dozen lines.

If you really want to solve the last hurdle – simplifying for users without the pretty syntax – see how @KSKelvin creates symbols. Use that approach to make user-editable values simple and use the example DLL code to grab the symbol values from the schematic (or simply pass them as attributes).

For more information about the DLL data-passing techniques, see my Github repository (mostly in C-Block Basics #9) and Kelvin’s repository (for advanced user-friendly symbol creation).

testdll.cpp (2.7 KB)
Test.qsch (2.1 KB)

1 Like

@archbugaboo I don’t quite understand exactly what you are dealing with. Are you saying you want to run a one-dimensional step (for example, .step param LOOP 1 10 1) where in each step you have more than one parameter set to a certain value?

For example, at LOOP=1, frq1=1k, frq2=2k
at LOOP=2, frq1=3k, frq2=1k
:

Is it more like a table lookup, which is why you are looking to feed from an array?

Hello RDunn

Your example shows you can pass values into a string and concatenate them. I see you mention someone “@LPoma” for this. I have no idea who that person is but, given the way you give credit, it’s something that was discovered – it’s certainly not documented – so, not something available for all the users to know a priori.

Had you shown this example from the start, all the misunderstandings could have been avoided: I never “complained”, I pointed out why it does not fit my requirements. Yes, I think you shouldn’t make it unnecessary cumbersome for the user but, that I am willing to accept the minor code bloat if it gets the job done.

Thank you for the solution but, please, avoid marring the quality of information with sour tones. If something is not clear, asking and waiting for clarifications is always a better choice.

Hello KSKelvin

The .step was mentioned to make it clear that the array would need to be able to be automatically editable from within the schematic (think automation). Fortunately, RDunn’s example shows it’s possible with such minimal hassle that it’s not even worth mentioning.

Vlad

Here is the discussion post.
How to string concatenate in QSpice - QSPICE - Qorvo Tech Forum
It is common that advanced users may come up with ideas for usage that may surpass Mike Engelhardt’s design. @RDunn, @physicboy, and @lpoma possibly push C++ block usage to its limit.

Qspice continues the practice of LTspice, meaning that much information is available in the forum and documents created by the community instead of being written in the Help file. I have unofficial guides on Github covering entries, commands, devices, etc., and @RDunn also writes documents covering basic to advanced-level usage of C++ blocks on his Github.

In my work a few months back, I managed to store data into .json file then parse it into Cblock using cJSON. You can use it if you need to parse a lot of parameters while keeping the file human readable.

If you don’t care about your own sanity, you can parse the file as CSV which is a lot easier, but with a lot of limitation such as the data might be difficult to read and must have rectangular shape.

Then use simple parameter input in Cblock as index on the block operating point.

Hello KSKelvin

Thank you for the link. It looks like my impression was true: it was a lucky discovery. Which is a very familiar feeling after 20+ years of LTspice. If it’s a bug, I hope Mike won’t fix it.

Hello physicboy

Thank you but, I doubt it’ll get this complicated, I simply needed a way to pass a variable number of arguments in a way that is not cumbersome: having to use the frequencies as f1=..., f2=..., fn=... would mean that, not only I would have to predefine the number of fn to something large enough (which may not even be enough) but, all those parameters would have been filling up the space (even if only in the symbol’s properties). It does looks a little bit funny, a mix of char and double with both meaning double but, unless Mike changes up his mind, this is the solution.

Vlad

Since English is not my first language, I haven’t quite figured out what exactly you are looking for. It appears that you want a C++ block capable of reading a preset array of parameters, and these parameters need to be placed in the schematic (as @physicboy’s proposal of reading from a file does not meet your requirement).

Another possibility is to employ the trick of using a table, by supplying an index to retrieve the coefficient from the table in the schematic during the initialization period. However, I suspect this still may not be what you are looking for. Do you have any examples (.qsch) to share what you are doing and why other methods all seem “cumbersome”?

LoadCoefficient.qsch (3.3 KB)
loadcoefficient.cpp (5.4 KB)

Hello KSKelvin

Think of a C block in a schematic that requires a number of frequency points. Or whatever else you can think of just, there is more than one and their number is not known (the user’s requirements know no bounds). It wouldn’t be very practical to define a set of parameters for the C block as float f1, float f2, ... because you can’t know how many there will be: if you make too many parameters it’s cumbersome to change each one, or all, how do you deal with only two that are needed out of N prepared (you still have to interact with the others to set them null), the more they are predefined the more likely it is to make mistakes in setting them (“oh, I set f13 but I needed f14”), having them visible in the schematic will take real estate, etc. So having the possibility to use a variable length array would be best here: float *f={f1, f2, ...}.

Currently, this is not possible, the uData inside the template shows no possibility for any float* or double*. I’ve already tried cheating by adding a double *a to it and then using double *f={1,2,3,4} as a test but… Ignoring unknown instance parameter.... However, RDunn’s (or IPoma’s) solution works, which is why I’ve selected the answer as the solution.

1 Like