C-Block Coding Basics

Based on many forum posts, the C-Block code stuff is confusing. If you’re a beginning C/C++ coder, there’s lots of difficult stuff in the templates. Even if you’re a great coder, there’s the mysterious Trunc() function.

Here’s what I understand (or think that I understand) on those topics. This is an early release on the dev branch of my GitHub page. See the CBlock_Doc folder.

I’m sticking my neck out here, pretending that I know stuff. Do correct me and we’ll eventually have a reliable document.

–robert

7 Likes

Hi Rob,

I have been reading your Cblock doc, which is fantastic.

However, do you have any comment on:

  1. the purpose of data stored in the struct template?
    In my guess, it seems to be used in conjuction with bzero to ensure that all those variable in the struct are cleared when the code is called for the first time.
  2. How does Trunc work? any clue on what these comments are supposed to mean?
    // limit the timestep to a tolerance if the circuit causes a change in struct sSTUDY2_X1
    // if(tmp != *inst) // implement a meaningful way to detect if the state has changed
    // *timestep = ttol;

Regards,
Arief,

Hi, Arief.

I’m not sure that I can briefly explain any better than in the “Per-Instance Data” and “Trunc()” sections of the lengthy PDF. An explanation of why and example of using the struct is in the first section. The Trunc() stuff is highly dependent on what you are trying to do.

–robert

Hi Robert,

Thanks for your answer.

  1. I still cant understand what you meant with Per-Instance Data. In one SCH file, I made two C-block and I dont see any interaction between the two C-block.

So, is it just for a good coding practice?

study3_x1.cpp (1.1 KB)
study3_x2.cpp (1.1 KB)



Sorry, I tried to just upload the .qsch but cant, so please refer to the picture above

  1. for Trunc(). still no clue…

If you are interested, we can connect via chat for better interaction, you may find my profile in LinkedIn (Arief Noor Rahman).

Thanks,
Arief,

Hi, Arief.

Ok, your example has a single instance each of two components (the DLLs). Each DLL has it’s own copy of the sum and previous clock variables. No problem.

The problem is when you have multiple instances (schematic hierarchical blocks) that call a single component (DLL). For example, if X1 & X2 both call Study3_X1.dll you’d see the problem. Since the variables are in the DLL, both instances would be incrementing the same sum variable.

Did that clear it up?

–robert

Hi Robert,

Ah…its crystal clear now…

Thanks for your patience

No worries. I see it as valuable feedback for future document revisions. Thanks.

–robert

I supposed for most control or signal processing application, Trunc and data struct are completely unnecessary.

The only reasonable case for using Trunc is when we need to have multiple C-block accessing one .dll file. Something like multiple PWM comparator or multiple ADC (though I still think to use only one block with multiple channels will be easier).

Forcing the user to access the variables (as in the case of using Trunc) will make the code a bit longer and less readable.

Do you happened to have good suggestion on when to use this Trunc()?

Thanks
Arief

I try to simulate a 3Phase inverter circuit.
I created a PWM generator in C DLL and it works fine.
However when I add 2 more instances (See shaded here)
No PWM is getting out of the Pins.
I assume that there is some interaction (Unwanted) between the sub circuits X1, X2 X3 which I’m not aware of? Any idea how can this be solved or done correctly?

Hi, RL007.

Without seeing the code I’d guess that you’re using global variables. Post the *.cpp & *.qsch if you’d like more than a guess.

–robert

Hi Robert,
Here is the .CPP and the .qsch
Let me know what am I doing wrong and how to solve it :slight_smile:

Half Bridge Inverter.qsch (31.8 KB)

digital_pwm_gen.cpp (6.0 KB)

Just like Robert said, global variables mess thing up when calling DLL from multiple blocks.
When you create C++ template, select “Include a struct XXX template:”. And you can refer to this example what modification is required in your code to eliminate the use of global variables.
But the concept behind that, may be better to be explained by @RDunn as I am not that familiar with C++.

digital_pwm_gen.cpp (7.4 KB)

image

Hi KSKelvin,
It did the trick and now it works. :slight_smile:
Is there any document you know about where Qorvo give explanations about the templates and their uses?
The code looks much more complicated now…
I thought that I can come around it by generating each of the instances by itself (create it the default template assign pins etc) so that each has its own DLL, but still use the same variable names inside the code (instead of having to change the names on each). I guess it should work too but will certainly take more time to make it rather then just reusing an existing instance and duplicating it on the schematics…
Any way, many thanks for your help!

I just prepared this slide to explain global and instance/member variable in C++ DLL block
[update : correct variable type to instance/member variable]

Great it is more clear now!

I never see official detail description, but community members likes Robert, Arief shared their work.
I explains DLL block in my Device Guide, and you can find in this link.
There are two sections about Ø-Device, and you can search these sections to get more information. Again, I am not expert in C++, and forgive me if I explain anything wrong in that section.
[I will update this guide later today to include this global/local variable discussion, and how to initialize local variable based on my study from Arief C++ code, therefore, you can revisit this link later today to get a newer version]

Qspice/Guideline/Qspice - Device Reference Guide by KSKelvin.pdf at main · KSKelvin-Github/Qspice

Arief here…

  1. the definition of global variable is correct
  2. local variable is the variable that is declared inside a function,
  3. the variables inside the struct are not local variables from the conventional definition (you can see that the data is passed into the function evaluation). Instead, it is a variable that is belong to each Cblock specifically. that’s why its also called as per-instance variables. The reason for having this per-instance variable is for the Qspice to maintain the data between each timestep for every block.

Thats all from my limited understanding…

Hasta la vista

1 Like

I just checked this with ChatGPT then saw your reply, ChatGPT corrected me that the variable should be called member variable. I will correct that slide later.

@RL007

If you don’t already have the issue sorted, you might want to check out the CBlock Basics documents & code examples in my GitHub QSpice repository.

–robert