You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
Using non reusable functions for referenced models
12 views (last 30 days)
Show older comments
Hi,
I'm using a Simulink model which contains referenced models and I would like to generate non-reusable functions for all models. It seems like it only works on the "top level". I have the settings "nonreusable function" for all models, but the generated code will be something like the following:
ert_main.c: my_model_step();
my_model.c: my_model_step() { ref_model_f(...); }
ref_model.c: ref_model_f(...) { ... }
Is there any settings which allows the referenced model to have a function declaration without any parameters, i.e., to make them non-reusable?
Answers (1)
Jesús Zambrano
on 7 Feb 2020
Hi Caroline,
I suggest you work with atomic subsystems. With them, you will have the option of setting the function packaging to Reusable or Nonreusable.
21 Comments
Bogdan Bodnarescu
on 21 Jan 2022
I have a similar question, using referenced models as I want for my software to be modular, but it is generating non reusable function for some models, and reusable function for other models, even if the Configuration Reference file that I use for all the models is set to non reusable functions.
Why doesn't Embeded Coder take into account this and it makes the code as it wants?
Jesús Zambrano
on 21 Jan 2022
Thanks for reaching out.
For example, aassume a ModelA which has a reference model RefModelA used twice. The Reusable/Nonreusable choice in the configuration parameters of RefModelA will have an impact if one open RefModelA as a top model and needs (or not) reentrant code from it.
If one generates code from ModelA, the top model's model_step function passes inputs and outputs to the referenced models function as pointers arguments. Each instance has its own internal data structure.
Here I inlcude relevant content from documentation to check:
Bogdan Bodnarescu
on 24 Jan 2022
I want to develop modular software were each Model has its code generated separately, but also to have a top model were all the models are integrated.
I find Referenced Models very good for this purpose, as I can also reference them in a Harness Model for doing the SIL/MIL testing.
But I would really like to have non reusable functions for the referenced models, and the variables declared inside each of them, not outside in the top model.
Now I understand from your answer that this is impossible with referenced models?
Can I use Atomic Subsystems for my purpose or is it simply impossible?
Jesús Zambrano
on 24 Jan 2022
Hi Bogdan,
Reference models are desgined to be reusable, to be called several times as part of a top-level model. However, you also mention to have the variables declared inside each of them, which I understand as instance specific. This can be done by "masking" a reference model, please check this link:
Then you will have reusable functions, but each of them with instance-specific parameters.
If this still cannot solve the problem, you cna try with atomic subsystem, whic you can define them to be reusable functions or not, and you can also masked them so to have parameters instance-specific.
Hope it helps!
Bogdan Bodnarescu
on 24 Jan 2022
Edited: Bogdan Bodnarescu
on 24 Jan 2022
Actually for my system for which I want to develop Modular Code that I can completely test according to Automotive Standards (Unit Test MIL/SIL/PIL, Code Coverage), I really don't have Referenced Models which are reused, but what I want is that each software unit generated from a Model is independent, as I want to integrate later the files in a separate compilation project.
So I want to be able to generate the files from a Top Model, but each file should have all its variables independent from the Top Model, so I can use the files for compilation later, without any dependences in the top model if possible.
I really like the Model Reference because it has so many features for Code Generation, like separate workspace, possibility to customize each block for the code generation as I want it, but it is very dissapointing that I can't generate void f (void) functions from each of the referenced models, and all the variables are defined in the top_model which is calling the referenced models.
After reading your comment todaym I also tried Atomic Subsystems and also Reference Subsystems, but they seem to have several disadvantages compared to Referenced Models.
Looking forward to your answer, as this is a big stopping block at the moment.
Jesús Zambrano
on 24 Jan 2022
Edited: Jesús Zambrano
on 24 Jan 2022
With a model incluing referenced models, you can do model testing of the entire model and/or each of the referenced models in SIL/PIL mode, using the SIL/PIL Manager: Verify generated code - MATLAB - MathWorks Nordic
About "all the variables are defined in the top_model which is calling the referenced models." --> You can modify this, look at masking reference models link:
If the referenced model is opened as a top-model, you can define is as reusable or non reusable. But as part of a top-level model, the top model's model_step function passes inputs and outputs to the referenced models function as pointers argument.The code generator places the code for the top model in a hierarchy in the code generation folder and places the code for referenced models in an slprj folder. Subfolders in slprj are separate places for different types of files. More about it can be found in this link to the documentation: Generate Code for Model Reference Hierarchy - MATLAB & Simulink - MathWorks Nordic
Bogdan Bodnarescu
on 24 Jan 2022
Edited: Bogdan Bodnarescu
on 24 Jan 2022
I read both topics, for me at the moment having a Harness Model where I have the same referenced Model as in the Top Model on which I can do the MIL/SIL testing with the SIL/PIL manager is a very good way to be able to split the development of the models to more developers for example, where each can work on its own model.
But the fact that I can't configure for the output of a Referenced Model to be Global Variables which are declared and defined in the .c and .h for that model is hindering this modularisation.
Perhaps I am doing something wrong in my Code Generation Settings?
Currently I am using the same Configuration File that I store in a Simulink Data Dictionary and then in both the Top Model and the Referenced Models I reference to this Configuration.
But even if in this configuration it is explicitly set that the functions are not reusable, Embbeded Coder generates functions with arguments for all the referenced models, and the Outputs of the models are variables defined in the Top Model .c and h., even if I use Exported Global class for them and I set them to be defined in the .c file for that model.
So what I want is:
top_model.c:
model_ref1();
model_ref2();
model_ref1.c:
uint8 out_ref1;
model_ref2.c;
uint8_out_ref2;
And what I get is:
top_model.c:
uint8 out_ref1;
uint8 out_ref2;
model_ref1(&out_ref1);
model_ref2(&out_ref2);
model_ref1.c:
model_ref2.c;
Which makes my referenced models not to be modular for the compilation, as I always need to compile them together with the top_model.c, otherwise the output variables will not be defined.
I don't exclude the possibility that I am doing maybe something wrong, this is the first time that I am using Embedded Coder, I have experience with Targetlink.
Jesús Zambrano
on 26 Jan 2022
Hi Bogdan,
Thanks for keeping this discussion.
Here I include a couple of pages from documentation that might help with the final code you want to get.
specially the section saying:
- “Configure Referenced Model Inputs and Outputs as Global Variables (void-void)
By default, for a nonreentrant referenced model, the generated code passes root-level input and output through function arguments. A nonreentrant referenced model is one in which you set model configuration parameter Total number of instances allowed per top model to One.
To pass this data through global variables instead (for a void-void interface), in the referenced model, apply storage classes such as ExportedGlobal and ExportToFile to root-level Inport and Outport blocks."
- To apply a default storage class to such blocks, use the Code Mapping Editor. With this technique, as you add such blocks to the model, the blocks acquire the default storage class, preserving the void-void interface. For more information, see Configure Default Code Generation for Data.
- To override the default storage class, apply storage classes directly to individual blocks by using the Code Mapping editor. See C Code Generation Configuration for Model Interface Elements.
- For an example that requires Embedded Coder, see Establish Data Ownership in a Model Hierarchy.
With this, you should get a code like you mentioned above. The only difference is that inputs and outputs of each ref model are in model_ref1.h (for ExportedGlobal storage class) or any other .h you define if you set them as ExportToFile storage class.
The other link is: Establish Data Ownership in a Model Hierarchy - MATLAB & Simulink - MathWorks Nordic
specially the section saying:
"To establish ownership of a global variable by placing the definition with the code generated from the relevant model, apply a storage class such as ExportToFile and specify the Owner custom attribute. Alternatively, for parameter objects such as Simulink.Parameter that you use in only one model, you can establish ownership by storing the object in a model workspace instead of the base workspace or a data dictionary."
Hope it helps!
Bogdan Bodnarescu
on 26 Jan 2022
Hello @Jesús Zambrano, I already did all the steps that are mentioned above, and I already tried the examples but for me even if I made a Custom Storage Class derived from Exported Global, still the variables are defined in the Top Model and they are passed as arguments to the step functions from the Referenced Models.
Like I said, I am using a Referenced Configuration File for the Code Generations Settings that I store as External Data in a Simulink Data Dictionary, could this be the reason why all the Global Variables are declared in the Top Model?
I really tried everything from the Examples you mentioned, but for my structure it doesn't seem to work for some reason.
Jesús Zambrano
on 26 Jan 2022
I've tried to set up what you just described: Using a Data Dictionary with Confiration Set as reference to all the hierarchy. The results are as described above, and here I also include screenshots. So, that should not be the reason for discrepancies.
Did you set those storage classes from inside the Reference Model? (you can set them by open the reference model as top-model or go inside the reference model from the top-model. In both ways you can use the Code Mapping table).
If discrepancies persist, I sugget to request support via the Request Support button in the home tab, describing the discrepancies you get with your model, and if possible, attach the model (or a simple version of it) so technical support can look at the files and settings in details.
Bogdan Bodnarescu
on 26 Jan 2022
This is really strange indeed that it refuses to work for me.
In your case is the Configuration File stored outside the Top Model in the Data Dictionary and then you reference it from both your Top Model and Referenced Models, or just from referenced models?
Anyhow thanks for the effort to try this on your system, I based my structure on an example model that I received from the supplier of the Hardware Package, so it is a little difficult to share the structure.
I will try to dereference the Configuration File and then generate the code, as my feeling is that something goes wrong when the same Configuration File is referenced both by the Top Model and the Referenced Model, and if this still doesn't work than I will make a Technical Support Ticket as you suggested.
Jesús Zambrano
on 26 Jan 2022
No worries! Indeed, strange!
Here I attach a zip file with the models I used: A top model with a reference model and a data dictionary. The data dictionary is used in both models. Otherwise, if you have differences config sets, keep in mind that the "total numer of instances...." equal to "One" is crucial to be set in the reference model, and the ExportedGlobal or ExpotToFile storage classes also defined inside the reference model.
Hope it helps!
Best,
Jesús
Bogdan Bodnarescu
on 26 Jan 2022
Edited: Bogdan Bodnarescu
on 26 Jan 2022
I think I have been able to reproduce my problem.
I attach the Archive with my modification as I also have it now.
Basically inside the referenced models I reference also the Configuration File, in your archive you have a Configuration File that is stored in that model.
In the attached zip I also added a Reference to the Extern Config File, and then the problem appears that all the globals are in the Top Model.
I have many referenced models, and I don't want to Copy Paste the Same Config File to each Model, but I already tried to Reference a Configuration File from the Referenced Models but it still generated the globals outside?
Maybe you can give it a try and tell me if this is a feature or a bug?
Anyway thanks a lot for providing the models, I think my problem is close to a solution now!
P.S.: I copied ModelReferencing to the SLDD and added a Reference to it and then the globals are still generated in the Top Model, so this is definitely my Problem.
Jesús Zambrano
on 26 Jan 2022
With the files I gto from you I got MyModel.c with:
#include "MyModel.h"
#include "MyModel_private.h"
/* Exported block signals */
real32_T in1; /* '<Root>/in1' */
real32_T in2; /* '<Root>/in2' */
real32_T out1; /* '<Root>/Subsystem' */
/* Model step function */
void MyModel_step(void)
{
/* ModelReference: '<Root>/Subsystem' incorporates:
* Inport: '<Root>/in1'
* Inport: '<Root>/in2'
*/
MyRefSubsystem();
}
where In/Out at top-level are as Auto. However, the MyRefSubsystem.h should also have:
extern real32_T in1; /* '<Root>/In1' */
extern real32_T in2; /* '<Root>/In2' */
extern real32_T out1; /* '<Root>/Sum' */
extern void MyRefSubsystem(void);
where In/Out are as ExportedGlobal.
Another last thing that might save you some time, specially when having multiple reference models and donät want to do any Copy/Paste manually, is to "propagate" referenced config set downstream:
Sorry if I can't help you more at this point.
Best,
Jesús
Bogdan Bodnarescu
on 26 Jan 2022
Edited: Bogdan Bodnarescu
on 26 Jan 2022
So can you confirm that if I Reference the Configuration File from the Reference Models then the global will be defined in the Top Model, but if I Copy/Paste the Configuration File in the Models then the global will be defined in the Referenced Models?
Or did I understand this wrongly?
What I want is to have totally independent files generated for the referenced modules, so each of them should have the global variables declared inside.
Jesús Zambrano
on 26 Jan 2022
I didn't mean that by doing copy/paste you get different results. It's just to show you how to propagete referenced config set downstream to all the referenced models withoud doing a manual copy/past.
From the files and screenshots I sent, you will get a referenced model with its own in/outs in the modelref.h. Also, you will have those in/outs in the toplevel model. You might get conflict if you change the toplevel in/out storage classes with the current settings in the reference model in/out storage classes.
Hope is more clear now.
Bogdan Bodnarescu
on 1 Feb 2022
Hello @Jesús Zambrano, I'm coming back with my problem and an updated model, very similar to what I want to use.
So as I said, I want the variables to be defined in the model where they are produced, not in the top model.
How can I do that?
In your examples they are always defined in the top model and declared with extern in the referenced model.
See my archive for the example.
How can I force Embedded Coder to define them in the referenced model when I use Exported Global as a class?
Actually I have been able to define them all in the referenced models, but only if I use for all the interface variables the class ExportToFile, but then I have to create one additional .h file as it doesn't like when I put the model .h file...
So I attach the .zip with Exported Global set for the interface variables, maybe you can tell me how can I move them to the modules, this should be very basic setting in Embedded Coder. From a compilation point of view, there is no problem if I move them manually to the modules .c and .h, it's only Embedded Coder that thinks that they should be defined in the top model even if they have no role there...
Bogdan Bodnarescu
on 1 Feb 2022
Edited: Bogdan Bodnarescu
on 1 Feb 2022
This is how I managed to make the variables be declared in the modules, but for this example it generated very strangely separate .c files for the modules in the folder where the top model is ... so this is also confusing and makes no sense to me.
Jesús Zambrano
on 1 Feb 2022
Hi Bordan,
Seems that your ExportToFile model is giving the result you expected. Maybe you can try to explore some other storage classes. Each storage classes will place the variables in certain .c and .h files. have a full list in this link:
Every embedded coder case problem is unique in terms of what the final code should look like, so it is an iterative process. Typically, the top-level model includes inports and outputs since the resulting code will be integrated in some other bigger model, and/or will interface with a dedicated target.
I also see that the model has specific settings in Code generation objectives (as it is now, it prioritizes Execution Efficiency and Traceability), this will affect the way you want the cood to look like. More info here:
What is the best?, it depends on the specifications or requirements of your final code.
There is no much I can help you at this moment. Don't hesitate to send you files to Technical Support. Also, for more about Embedded Coder, MathWorks has a 2-day training course in this topic, more info here: Embedded Coder for Production Code Generation | MATLAB and Simulink Training (mathworks.com)
All the best!,
Jesús
Bogdan Bodnarescu
on 2 Feb 2022
Indeed ExportToFile makes the code as I want it, but this is not the solution that I like because of the very high amount of manual work that I have to do to configure all the Inports and Outports manually.
It would have been really nice that the fields in the Property Inspector have a drow down lists from which to select, probably this could be done programatically with a script to set everything up.
Still I am not happy that a separate .c file is generated for the referenced models on the same level where the top model is, for my project this is not happenning.
Honestly I would have prefered to have all my Inports and Outports to be configured as ExportedGlobal and that they are automatically defined in the modules, or at least that there is some easy way to do this.
Could this work if I make a Custom Storage Class?
Jesús Zambrano
on 2 Feb 2022
Yes, you could try with Custom Sotrage Class.
As mentioned before, to get a full and detailed guidance of exactly the solution you want, try with tech support. Another good solution is to contact the MathWorks sales rep. assigned to your company, the IT department at your company surely has this information.
All the best,
Jesús
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)