Engee documentation

Code Generator Features

Internal functions in the generated code

The Engee code generator supports virtual and atomic subsystems for code generation. Virtual subsystems serve only for the visual hierarchy in the model, while atomic subsystems represent a single execution unit (or function in the generated code). Configuration in subsystem properties Treat as atomic unit allows you to make a subsystem virtual or atomic.

All calculations inside virtual subsystems are embedded (inline) directly into the code of the enclosing subsystem or model. This can improve the performance of the generated code, but degrade readability and traceability to the model.

All calculations inside atomic subsystems are generated in a separate function with the subsystem name. This function is then called automatically in the code of the underlying subsystem or model. This can improve the readability and traceability of the generated code to the model, but degrade performance.

For example, turn RollMode from the model autopilot_roll.engee (see Code generation example) to the atomic subsystem:

gs atomic vs virtual en

Save the model and generate the code again. The generated code now has a function named RollMode (corresponding to the subsystem name in the model). This function is called inside the function autopilot_roll_step, which represents the code of the enclosing model. Function RollMode declared as static and, thus, is an internal function of this model.

The code generator ignores disabled blocks, and the associated code is not created.

comment out 1 en

Parameters in the generated code

Parameters in the model blocks

In the model blocks, the parameters can be set:

  • In the form of numbers (for example, 0.2);

  • In the form of expressions (for example, 0.2 + 0.7);

  • In the form of variable names from the Engee workspace (for example, Kp).

In the generated code, the parameters are embedded (inline) with the values specified in the model.:

  • Simple numerical values are added to the code "as is", and no additional actions are required.;

  • Expressions consisting only of numbers can be simplified (constant folding), and the calculated numeric value will get into the code.;

  • Values specified by the variable name (for example, Kp), as well as expressions containing variables (for example, Kp + 1), are considered as Tunable and fall into the structure modelname_P — even if the "Embedded" mode is selected.

Configurable parameters

By default, the rule applies: any reference to a variable (for example, Kp) or an expression containing a variable (for example, Kp + 1) makes the parameter configurable and puts it in modelname_P — regardless of the setting Built-in/Customizable. In the "Configurable" mode in modelname_P all parameters are included, including numeric literals.

Some block parameters can be made configurable (tunable) so that they can be changed after code generation. These parameters are stored in the structure modelname_P which looks like this:

  • If the parameter is set via a variable name (for example, Kp), then its name is saved in the structure:

    struct P_modelname_T_ {
        double Kp;
    };
  • If the parameter is set as an expression with a variable (for example, Kp + 1), then the name of the parameter in the block is used (for example, Amplitude):

    struct P_modelname_T_ {
        double Amplitude;
    };

In all cases, the parameters in the structure are modelname_P they are filled with calculated values available from the model, for example:

P_modelname_T modelname_P = {
    0.5 // Parameter value
};

Using the option Default parameter behaviour in settings window debug article icon 1 you can control which parameters will remain configurable in the generated code.:

behavior setting 1 en

  • Inline — only numeric literals and expressions of the same numbers are inserted directly into the code and do not get into modelname_P. Any parameters specified by the variable name or the variable expression remain configurable and fall into modelname_P.

  • Tunable — all parameters, including numeric ones, are placed in modelname_P; numeric values are not inline.

example: Built-in mode, the amplitude is set by a variable `a`

When selecting "Embedded" and the block parameter Amplitude = a:

  • The field in will appear in the code. modelname_P (for example, double a; or the name of the field by the parameter label, if the expression is used with a);

  • File model_data.c gets the original value a from the workspace;

  • The * value itself will not be fixed, it can be changed without reassembling.

This is the expected behavior: a reference to a variable is treated as "configurable".

Interfaces of the generated code and integration into the external development environment

Interfaces of the generated code

The external interfaces of the generated code can be seen in the generated file. modelname.h. External interfaces include functions and structures for working with generated code.:

  • modelname_init — is a model initialization function — must be called once;

  • modelname_step — is the entry point to the model and contains the algorithm of the model — must be called periodically in accordance with the step of calculating the model;

  • modelname_U — the structure contains the external input ports of the model;

  • modelname_Y — the structure contains the external output ports of the model;

  • modelname_S — the structure contains the internal states of the model;

  • modelname_P — the structure contains configurable model parameters.

Integration into an external development environment

To use the functions and structures of the generated file modelname.h in the external code (written manually), you need to do the following:

  1. Attach the generated header file:

    #include "modelname.h"
  2. Organize a single call to the generated function init in your main:

    modelname_init();
  3. Organize a periodic call to the generated function step in your main with the right step:

    modelname_step();
  4. Organize the transfer of input and output data to and from the function step:

    /* Setting the values of the inputs */
    modelname_U.input1 = 42;
    /* Calling the step function */
    modelname_step();
    /* You can use modelname_Y.output1 */

Generated files

After building the model in Engee and generating its code (using the command engee.generate_code() or buttons Generate code codegen icon 1) automatically generated files are created that contain the implementation of the model in the C language. Below is a description of these files and their purpose.

codegen all generated files en

  • modelname.h — a header file that describes the external interfaces of the model. It includes the functions and structures necessary to work with the model from external code (for more information, see above). The process of connecting these functions and structures to an external application is also described in the section above.

  • modelname.c — a file with the implementation of the logic of the model. It contains definitions of all variables and the implementation of key functions of the model.:

    • init() — initialization function that sets the 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 shutdown function of the model.

  • model_data.c — a file with the initial initialization of the model parameters. It sets the values of all the configurable parameters that are used when executing the model. For example:

    • Signal amplitude and frequency;

    • Phase, offset;

    • The number of samples and other parameters.

      These global parameters are configurable and can be changed while the executable code is running. This allows you to flexibly control the behavior of the model without having to reassemble the logic or edit the main functions.

      In the "Embedded" mode in model_data.c only parameters specified through variables or expressions with variables are included; numeric literals and purely numeric expressions are not written there (they are embedded in the code).
  • main.c — a file with an example of using the model. This is the main executable file that shows how to initialize and invoke a model from a C program. Contains:

    • init() — the initialization function of the model, called once before starting work;

    • step() — the main computational function that performs one step of calculating the model. It is usually called periodically, according to the specified integration step.;

    • term() — the shutdown function of the model.

      File main.c It does not contain an algorithm for the operation of the model, but only demonstrates how to correctly launch and manage its execution in an application with C code support. main.c It 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, then a double-precision floating-point data type corresponding to the type is used. double in C. For logical operations or calculations that generate Boolean results (true (1) or false (0)), the data type is used boolean, corresponding to an eight-bit unsigned data type in Si.

To display data types in the model, in settings window debug article icon 1 in the "Debugging parameter" tab, enable the option Data types.

Vectorization

The code generator supports vector data types in models, including vectors and matrices. Standard loops are generated in the code for vector operations. for without calling specific BLAS or LAPACK functions.

Complex numbers

The code generator supports complex data types in models. For complex types, the types from the standard header file are used. <complex.h>.

Multi-frequency models

Engee models can be multi-frequency, that is, they contain several different sampling rates. Applying blocks Rate Transition, as well as by setting the parameter Sample Time blocks and subsystems, the user can control which calculation step blocks or groups of blocks work with.

The Engee code generator supports code generation for multi-frequency models. To do this, the blocks are grouped by frequency, and the user can control how these different frequencies are represented in the generated code.

Customization Multirate code generation allows you to control the mode of operation of the generated code for a multi-frequency model. The "single-tasking" code allows you to generate a single function step for the model. The "multitasking" code allows you to generate multiple functions. step for the model, each of which corresponds to a specific sampling rate in the model.

multirate model setting en

Single-task code contains conditions (in the form of if) inside the generated function step, which wrap calls of slower frequencies in the model. Function step It contains blocks operating at the base frequency of the model (the fastest frequency). From the custom binding, it is enough to provide a function call step at the same time, the scheduling of calls of slower frequencies and the exchange of information between frequencies is carried out automatically in the generated code itself.

Multitasking code contains several functions step_N in the generated code, each of which corresponds to its frequency in the model. Function step_0 corresponds to the fastest frequency in the model (base frequency), the function step_1 the second slower frequency, and so on. It is required to provide a function call from the custom binding step_N with the necessary 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 you to trace the code to the blocks in the model.

Customization Include comments in the panel Code generation they allow you to manage comments in the generated code and, if necessary, disable them completely.

Code verification

Verification refers to the generation of a verification model with a block C Function, whose simulation results must match the simulation results of the original model with the same input data.

Block C Function it can be created automatically to verify the generated code. To do this, check the box Generate C Function block in the settings window lk 5:

c function codegen en

The next time the code is generated (via the interface, context menu, or command generate_code) in the directory ouput_dir the file will appear modelname_verification.jl (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 (by double-clicking) interactive scripts icon or the command line command line icon:

include("path/to/verification.jl")

The script will create an Engee model with the name modelname_verification.engee and a block C Function, which uses the generated code:

model generated cfunction en

Code generation in the Verilog language is also available in Engee. For more information, see the article Verilog (HDL) code generation.

Code generation based on custom templates

Engee supports code generation based on custom templates (for more information, see the article Code generation based on custom templates).

Managing signal names

The code generator uses the names of the signals specified by the user in the model to make the generated code clearer and easier to match with the model. For example:

image14 en

If the signal (block output) has a name, then the generated code will use the same variable name for this signal. This is possible only if the signal has not been optimized and does not contain characters that are not supported in the C code.