Code generator options
Internal functions in generated code
The Engee code generator supports virtual and atomic subsystems for code generation. Virtual subsystems serve only for visual hierarchy in the model, while atomic subsystems represent a single unit of execution (or function in the generated code). The Treat as atomic unit
setting in the subsystem properties allows you to make the subsystem virtual or atomic.
All computations within virtual subsystems are embedded (inlined) directly into the code of the encompassing subsystem or model. This may improve the performance of the generated code, but degrade readability and tractability to the model.
All computations within atomic subsystems are generated into a separate function named subsystem. This function is then called automatically in the code of the encompassing subsystem or model. This may improve the readability and traceability of the generated code to the model, but degrade performance.
For an example, turn RollMode
from the autopilot_roll.engee
model (see Code Generation Example) into an atomic subsystem:
Save the model and generate the code again. The generated code now contains a function named RollMode
(corresponding to the name of the subsystem in the model). This function is called inside the autopilot_roll_step
function, which represents the code of the volumetric model. The RollMode
function is declared as static
and is thus an internal function of this model.
The code generator ignores disabled blocks, and no associated code is created. |
Parameters in the generated code
Parameters in model blocks
Parameters can be set in model blocks:
-
As numbers (e.g.,
0.2
); -
As expressions (e.g.
0.2 + 0.7
); -
As variable names from the Engee workspace (e.g.
Kp
).
In the generated code parameters are embedded (inlined) with the values specified in the model:
-
Simple numerical values are added to the code "as is" and no additional actions are required;
-
Expressions can be simplified and only the final calculated value will appear in the code;
Customisable parameters
Some block parameters can be made customisable (tunable) so that they can be changed after code generation. Such parameters are stored in the modelname_P
structure, which looks like this:
-
If a parameter is specified via a variable name (e.g.,
Kp
), its name is stored in the structure:struct P_modelname_T_ { double Kp; };
-
If the parameter is specified as an expression (e.g.
Kp + 1
), the name of the parameters is used (e.g.Amplitude
):struct P_modelname_T_ { double Amplitude; };
In all cases, parameters in the modelname_P
structure are filled with calculated values available from the model, e.g.:
P_modelname_T modelname_P = {
0.5 // Значение параметра
};
Using the option Default parameter behaviour in settings window
|
Generated code interfaces and integration into external development environment
Generated code interfaces
The external interfaces of the generated code can be seen in the generated modelname.h
file. The external interfaces include functions and structures to work with the generated code:
-
modelname_init
- is the model initialisation function - must be called once; -
modelname_step
- is the model entry point and contains the model algorithm - should be called periodically according to the model calculation step; -
modelname_U
- structure contains external input ports of the model; -
modelname_Y
- structure contains external output ports of the model; -
modelname_S
- structure contains internal states of the model; -
modelname_P
- structure contains customisable parameters of the model.
Integration into external development environment
To use functions and structures of the generated modelname.h
file in external code (written manually), you need to perform the following actions:
-
Connect the generated header file:
#include "modelname.h"
-
Organise a single call to the generated
init
function in yourmain
:modelname_init();
-
Organise a periodic call to the generated
step
function in itsmain
with the desired step:modelname_step();
-
Organise the transfer of input and output data to and from the
step
function:/* Устанавливаем значения входов */ modelname_U.input1 = 42; /* Вызываем функцию step */ modelname_step(); /* Можно использовать modelname_Y.output1 */
Generated files
After building a model in Engee and generating its code (using the engee.generate_code()
command or the button Generate code ), generated files are automatically created that contain the C implementation of the model. These files and their purpose are described below.
-
modelname.h
is a header file that describes external interfaces of the model. It includes functions and structures necessary for working with the model from external code (see above for details). The process of connecting these functions and structures to an external application is also described in above. -
modelname.c
- file with the implementation of the model logic. It contains definitions of all variables and implementation of key functions of the model:-
init()
- initialisation function that sets initial values of variables and model states; -
step()
- the main computational function. Performs the calculation of one simulation step and updates the output values; -
term()
- the function of model termination.
-
-
model_data.c
- file with initialisation of model parameters. It sets the values of all configurable parameters that are used in the execution of the model. For example:-
Signal amplitude and frequency;
-
Phase, offset;
-
Number of samples and other parameters.
These global parameters are customisable and can be changed while the executable code is running. This allows you to flexibly control the behaviour of the model without having to rebuild the logic or edit the basic functions.
-
-
main.c
is a file with an example usage of the model. This is the main executable file that shows how to initialise and call the model from a C program. Contains:-
init()
- model initialisation function, called once before starting; -
step()
- the main computational function that performs one step of the model calculation. It is usually called periodically, according to the specified integration step; -
term()
- the function of model completion.The
main.c
file does not contain the algorithm of the model, but only demonstrates how to correctly run and control its execution in a C code supported application.main.c
should be used as a template for integrating the model into user projects.
-
Supported data types
The data types in the generated code correspond to the data types in the Engee model.
If the user has not specified a data type in the model, the double-precision floating-point data type corresponding to the double
type in C is used. For logical operations or calculations that generate boolean results (true (1)
or false (0)
), the boolean
data type is used, corresponding to the eight-bit unsigned data type in C.
To display data types in the model, in settings window ![]() |
Vectorisation
The code generator supports vector data types in models, including vectors and matrices. Standard for
loops are generated for vector operations in the code without calling specific BLAS or LAPACK functions.
Complex numbers
The code generator supports complex data types in models. For complex types, types from the standard <complex.h>
header file are used.
Multi-frequency models
Engee models can be multi-frequency, i.e. contain several different sampling frequencies. By applying the blocks Rate Transition, and by setting the Sample Time
parameters of the blocks and subsystems, the user can control at what calculation step the blocks or groups of blocks operate.
The Engee code generator supports code generation for multi-frequency models. For this purpose, blocks are grouped by frequency and the user can control how these different frequencies are represented in the generated code.
Customisation Multirate code generation allows you to control the mode of operation of the generated code for a multi-frequency model. "Single-task" code allows a single step
function to be generated for the model. "Multi-task" code allows to generate several step
functions for the model, each corresponding to a specific sampling frequency in the model.
Single-tasking code contains conditions (in the form of if
) within the generated step
function that bypass calls to slower frequencies in the model. The step
function contains blocks running at the base frequency of the model (the fastest frequency). It is sufficient to provide a call to the step
function from the user pipelining, while scheduling calls to slower frequencies and exchanging information between frequencies is done automatically in the generated code itself.
The Multi-task code contains several step_N
functions in the generated code, each corresponding to a different frequency in the model. The step_0
function corresponds to the fastest frequency in the model (the base frequency), the step_1
function to the second slower frequency, and so on. From the user pipelining it is required to provide calls to step_N
functions with the required calculation steps. Data interactions between different frequencies are provided automatically in the generated code itself.
Comments in the generated code
By default, the generated code contains comments that allow the code to be traced back to blocks in the model.
Customisation Include comments in the panel Code generation allows to control comments in generated code and if necessary to switch them off completely.
Code verification
Verification means generation of a verification model with the block C Function, whose simulation results should coincide with the simulation results of the original model with the same input data.
The C Function block can be created automatically to verify the generated code. To do this, tick the checkbox Generate C Function block in the settings window :
At the next code generation (via the interface, context menu or the command generate_code) the file modelname_verification.jl
will appear in the ouput_dir
directory (if the directory does not exist - it will be created automatically). This file will contain a script that can be executed in the script editor (double-click) or command line
:
include("path/to/verification.jl")
The script will create a Engee model named modelname_verification.engee
and a block C Function, which uses the generated code:
Verilog code generation is also available in Engee, see Verilog (HDL) code generation for details .
Code generation based on custom templates
Engee supports code generation based on custom templates (see the article Code generation based on custom templates for details).
Signal Name Management
The code generator uses the signal names defined by the user in the model to make the generated code more understandable and easier to match to the model. For example:
If a signal (block output) has a name, the generated code will use the same variable name for that signal. This is possible only if the signal has not been optimised and does not contain characters that are not supported in C code.