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). The setting in the properties of the subsystem Treat as atomic unit allows you to make the subsystem virtual or atomic.

All calculations within 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, transform the RollMode from the autopilot_roll.engee model (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 `autopilot_roll_step function, which represents the code of the enclosing model. The 'RollMode` function is declared as `static' and is thus 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 can be simplified, and only the final calculated value will appear in the code.;

Configurable parameters

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

  • If the parameter is set using the variable name (for example, Kp), then its name is stored in the structure.:

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

    struct P_modelname_T_ {
        double Amplitude;
    };

In all cases, the parameters in the modelname_P structure 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

  • Embedded — numeric values are directly inserted into the generated code and are not added to the structure.

  • Tunable — parameters are added to the structure even with numeric values.

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 the initialization function of the model — must be called once;

  • 'modelname_step' is the entry point to the model and contains the model’s algorithm. It should 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 modelname' file.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 init function in your main:

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

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

    /* 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 engee' command.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 is the 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' is a file with the implementation of the model logic. It contains definitions of all variables and the implementation of key functions of the model.:

    • 'init()` is an initialization function that sets the initial values of variables and model states`;

    • 'step()` is the main computational function. Performs the calculation of one simulation step and updates the output values;

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

  • `model_data.c' is a file with 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.

  • 'main.c' is 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()` is the initialization function of the model, called once before starting work.;

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

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

      The 'main.c` file does not contain the algorithm of the model, but only demonstrates how to correctly launch and manage its execution in an application with C code support. 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 the data type in the model, then 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 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. For vector operations, standard for loops are generated 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 header file <complex.h> are used.

Multi-frequency models

Engee models can be multi-frequency, that is, they contain several different sampling rates. Applying blocks Rate Transition By setting the Sample Time parameter of 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-task" code allows you to generate a single "step" function for the model. The "multitasking" code allows you to generate several "step" functions 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 'step` function that wrap calls to slower frequencies in the model. The step function contains blocks operating at the base frequency of the model (the fastest frequency). It is sufficient to provide a call to the step function from the user harness, while scheduling calls to slower frequencies and exchanging information between frequencies is carried out automatically in the generated code itself.

Multitasking code contains several step_N functions in the generated code, each of which corresponds to its frequency in the model. The function step_0' corresponds to the fastest frequency in the model (the base frequency), the function `step_1 corresponds to the second slower frequency, and so on. From the custom binding, it is required to provide a call to the step_N functions 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) the file modelname_verification.jl will appear in the directory ouput_dir (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.