Call Reusable External Algorithm Code for Simulation and Code Generation

Code reuse offers business and technological advantages. From a business perspective, code reuse saves time and resources. From a technological perspective, code reuse promotes consistency and reduces memory requirements. Other considerations include:

  • Modularizing an application

  • Reusing an optimized algorithm

  • Interfacing with a predefined dataset

  • Developing application variants

Examples of reusable hardware-independent algorithmic code to consider importing into the Simulink® environment for simulation and code generation include:

  • Utility functions

  • Lookup tables

  • Digital filters

  • Specialized integrators

  • Proportional-integral-derivative (PID) control modules

Workflow

To call reusable external algorithm code for simulation and code generation, iterate through the tasks listed in this table.

TaskActionMore Information
1Review your assessment of external code characteristics and integration requirements.Choose an External Code Integration Workflow (Embedded Coder)
2Based on the programming language of the external code, choose an integration approach to add the external code to a Simulink model.Choose an Integration Approach (Embedded Coder)
3Verify algorithm behavior and performance by simulating the model.Simulation
4Define the representation of model data for code generation.Exchange Data Between External C/C++ Code and Simulink Model or Generated Code (Embedded Coder)
5Configure the model for code generation.Generate Code That Matches Appearance of External Code (Embedded Coder) and Model Configuration (Embedded Coder)
6Generate code and a code generation report.Code Generation (Embedded Coder)
7Review the generated code interface and static code metrics.Analyze the Generated Code Interface (Embedded Coder) and Static Code Metrics (Embedded Coder)
8Build an executable program from the model.Build Integrated Code Within the Simulink Environment (Embedded Coder)
9Verify that executable program behaves as expected.Numerical Equivalence Testing (Embedded Coder)
10Verify that executable program performs as expected.Code Execution Profiling (Embedded Coder)

Choose an Integration Approach

Several approaches are available for integrating reusable algorithmic code into the Simulink environment for code generation. Some approaches integrate external code directly. Other approaches convert the external code to Simulink or Stateflow® modeling elements for simulation, and later for code generation from the modeled design. The integration approach that you choose depends on:

  • Programming language of the external code — MATLAB®, C, C++, or Fortran

  • Your programming language experience and preference

  • Performance requirements

  • Whether the algorithm must model continuous time dynamics or you are integrating the algorithm into an application that uses discrete and continuous time

  • Whether you want to take advantage of Model-Based Design

  • Level of control required over the code that the code generator produces

To choose an approach for a reusable algorithm, see the subsection that matches the programming language of your external algorithm code.

Integration Approaches for External MATLAB Code

Multiple approaches are available for integrating external MATLAB code into the Simulink environment. The following diagram and table help you choose the best integration approach for your application based on integration requirements.

 Condition or RequirementActionMore Information
1The algorithm must model continuous state dynamics.Write a MATLAB S-function and, for generating code, a corresponding TLC file for the algorithm. Add the S-function to your model.
2External code complies with the MATLAB code for code generation subset and you want to call MATLAB code from a Simulink model.Add a MATLAB Function block to the model. Embed the MATLAB code in that block.
3External code complies with the MATLAB code for code generation subset, you want to call MATLAB code from a Simulink model, and your algorithm includes iterative computations that process large streams of data.Add a MATLAB System block to the model. Embed the MATLAB code in that block as a System object™.
4External code complies with the MATLAB code for code generation subset, you want to call MATLAB code from a Simulink model, and your algorithm includes design logic that is based on state machines and flow charts.Add a Stateflow chart to the model. Call the external code from the chart, using MATLAB as the action language.
5You want to use the parfor function for parallel computing or interface data types that are available to MATLAB Coder™, Simulink Coder, and Embedded Coder®. To use parfor, Parallel Computing Toolbox™ must be installed.Use software to generate C code. Then, call that generated code as external C code.
6You have C or C++ programming experience and the external MATLAB code is compact and primarily uses C or C++ constructs.Manually convert the MATLAB code to C or C++ code. Choose an integration approach for C or C++ code.

Integration Approaches for External C or C++ Code (Embedded Coder)

7Sections of the external MATLAB code map to built-in blocks.Develop the algorithm in the context of a model, using the applicable built-in blocks.

To embed external MATLAB code in a MATLAB Function block or generate C or C++ code from MATLAB code with the MATLAB Coder software, the MATLAB code must use functions and classes supported for C/C++ code generation.

Integration Approaches for External C or C++ Code

Under most circumstances, you can integrate external code written in C or C++ into the Simulink environment by generating S-functions and TLC files with the Legacy Code Tool. This tool uses specifications that you supply as MATLAB code to transform existing MATLAB functions into C MEX S-functions that you can include in Simulink models and call from generated code. For details, see Implement Algorithms Using Legacy Code Tool and Import Calls to External Code into Generated Code with Legacy Code Tool (Embedded Coder).

In comparison to alternative approaches, Legacy Code Tool is the most optimal choice for generating code optimized enough for embedded systems. Consider alternative approaches if one or more of the following conditions exist:

  • The external code uses global variables to exchange data.

  • Programming experience is limited.

  • The algorithm must model discrete and continuous state dynamics.

  • You want to include the integrated external code in a Stateflow chart.

  • The external code requires a fixed-point interface.

  • You want maximum flexibility for controlling what code the code generator produces.

  • You quickly want to embed a call to the external code in a call to the coder.ceval function that is embedded in the MATLAB Function block, and performance is not an issue.

This diagram and table help you choose the best integration approach based on your integration requirements.

 Condition or RequirementActionMore Information
1You want to integrate external C code with generated C++ code or converselyMatch the language choice for the generated code by modifying the language of the external code.Modify Programming Language of External Code to Match Generated Code (Embedded Coder)
2Your algorithm includes design logic that is based on state machines and flow charts. Or, a function that you want to integrate must exchange data with a model by using global variables. The function defines the global variables and uses them to write output rather than returning a value (return) or writing output to an argument.Add a Stateflow chart to the model. Call the external code from the chart, using C as the action language. In the chart, write code that calls the external function and reads from and writes to the global variables. To perform calculations with output of the external code, the model must read from the global variable during execution.Insert External Code into Stateflow Charts (Embedded Coder)
3You want to include external C or C++ code in a Stateflow chart for simulation and code generation.Configure the model that contains the chart to apply the external C or C++ code.
4You quickly want to embed a call to external C or C++ code in a model. Performance is not an issue.Call the C or C++ code with the coder.ceval function from within a MATLAB Function block.
5The application requires more entry-point functions than the code generator typically produces—for example, more than model_step, model_initialize, and model_terminate. You want maximum flexibility for controlling what code the code generator produces.Manually write an S-function and TLC file.
6You want to simulate and generate external code for a discrete time application. Optimizing generated code is essential. You want ease of use with moderate flexibility for controlling what code the code generator produces. You have C or C++ programming experience, but you prefer to generate the files for adding the code to a model.

Generate S-function and TLC files by using the Legacy Code Tool. If necessary, refine the generated code manually to meet application requirements. (If you change the generated code, you lose the changes if you regenerate the S-function and TLC files.)

For simple algorithms written in C, consider using the Simulink C Caller block.

7The algorithm must model discrete and continuous state dynamics for simulation and rapid prototyping. The external code requires a fixed-point interface. Programming experience is limited. You want ease of use with basic flexibility for controlling what code the code generator produces for rapid prototyping.Generate S-function and TLC files by using the S-Function Builder. If necessary, refine the generated code manually to meet application requirements. (If you change the generated code, you lose the changes if you regenerate the S-function and TLC files.)

Modify Programming Language of External Code to Match Generated Code

To integrate external C code with generated C++ code or conversely, modify the language of the external code to match the programming language choice for the generated code. Options for making the programming language match include:

  • Writing or rewriting the external code in the language choice for the generated code.

  • If you are generating C++ code and the external code is C code, for each C function, create a header file that prototypes the function. Use this format:

    #ifdef __cplusplus
    extern "C" {
    #endif
    int my_c_function_wrapper();
    #ifdef __cplusplus
    }
    #endif

    The prototype serves as a function wrapper. If your compiler supports C++ code, the value __cplusplus is defined. The linkage specification extern "C" specifies C linkage without name mangling.

  • If you are generating C code and the external code is C++ code, include an extern "C" linkage specification in each .cpp file. For example, the following example shows C++ code in the file my_func.cpp:

    extern "C" {
    
    int my_cpp_function()
    {
      ...
    }
    }

Integration Approaches for External Fortran Code

To integrate external Fortran code, write an S-function and corresponding TLC file.

See C/C++ S-Function Basics, Implement Algorithms Using Fortran Code, S-Functions and Code Generation (Embedded Coder), andFortran S-Function Examples.

Insert External Code into Stateflow Charts

Integrate External Code for Library Charts

To integrate external code that applies only to Stateflow library charts for code generation, for each library model that contributes a chart to your main model, complete these steps. Then, generate code.

  1. In the Stateflow Editor, open the Model Configuration Parameters dialog box. Select parameter Use local custom code settings (do not inherit from main model),

    The library model retains its own custom code settings during code generation.

  2. Specify your custom code in the subpanes.

    Follow the guidelines in Specify Relative Paths to Your Custom Code (Stateflow).

    If you specified custom code settings for simulation, you can apply these settings to code generation. To avoid entering the same information twice, select Use the same custom code settings as Simulation Target.

  3. Click OK.

After completing these steps for each library model, generate code.

Integrate External Code for All Charts

To integrate external code that applies to all charts for code generation:

  1. Specify custom code options for code generation of your main model.

    1. In the Model Configuration Parameters dialog box, select Code Generation > Custom Code.

    2. In the custom code text fields, specify your custom code.

      Follow the guidelines in Specify Relative Paths to Your Custom Code (Stateflow).

      If you specified custom code settings for simulation, you can apply these settings to code generation. To avoid entering the same information twice, select Use the same custom code settings as Simulation Target.

  2. Configure code generation for each library model that contributes a chart to your main model. In the Stateflow Editor, open the Model Configuration Parameters dialog box. Clear parameter Use local custom code settings (do not inherit from main model). The library charts inherit the custom code settings of your main model. Click OK.

  3. Generate code.

Call External C Code from Model and Generated Code

Call existing, external functions from a simulation or from the generated code by using the Legacy Code Tool.

Learn how to:

  • Evaluate a C function as part of a Simulink® model simulation.

  • Call a C function from the code that you generate from a model.

For information about the example model, see Prepare a Control Algorithm Model for C Code Generation (Embedded Coder).

Replacement Process

Open the example model, rtwdemo_PCG_Eval_P4.

For many Model-Based Design applications, in addition to Simulink® models, a design includes a set of existing C functions that have been tested and validated. You can integrate these functions into a Simulink® model and generate code that uses the functions.

In this example, you create a custom Simulink® block that calls an existing C function. You then include the block in a model and test the overall system through model simulation in Simulink®.

In the example model, you can replace the Lookup blocks (lookup tables) in the PI controllers with calls to an existing C function. The function is defined in files SimpleTable.c and SimpleTable.h.

View SimpleTable.c.

View SimpleTable.h.

Create Block That Calls C Function

To specify a call to an existing C function, use an S-Function block. You can automate the creation of the S-Function block by using the Legacy Code Tool. In the tool, you first specify an interface for your existing C function. The tool then uses that interface to create an S-Function block.

Use the Legacy Code Tool to create an S-Function block for the existing C function in SimpleTable.c.

1. Create a structure to contain the definition of the function interface.

def = legacy_code('initialize')

You can use the structure def to define the function interface to the existing C code.

2. Populate the fields of the structure.

3. Create the S-function.

legacy_code('sfcn_cmex_generate',def)

4. Compile the S-function.

legacy_code('compile',def)

5. Create the S-Function block.

legacy_code('slblock_generate',def)

The generated S-Function block calls the C function in SimpleTable.c. You can now use this S-Function block in models.

6. Create the TLC file.

legacy_code('sfcn_tlc_generate',def)

This command creates a TLC file, which is the component of an S-Function that specifies how to generate code for the block.

Validate External Code Through Simulation

When you integrate existing C code in a Simulink® model, validate the generated S-Function block.

To validate the replacement of the Lookup blocks, compare the simulation results produced by the Lookup blocks with the results produced by the new S-Function block.

1. Open the validation model.

  • The Sine Wave block produces output values from [-2 : 2].

  • The input range of the lookup table is from [-1 : 1].

  • The lookup table outputs the absolute value of the input.

  • The lookup table clips the output at the input limits.

2. Run the validation model.

The figure shows the validation results. The existing C code and the Simulink® table block produce the same output values.

Validate C Code as Part of Simulink® Model

After validating the existing C function code as a standalone component, validate the S-function in the model. To complete the validation, use a test harness model.

1. Open the test harness.

2. Run the test harness.

The simulation results match the golden values.

Call C Function from the Generated Code

The code generator uses the TLC file to process the S-Function block like any other block. The code generator can implement expression folding with the S-Function block, an operation that combines multiple computations into a single output calculation.

1. Build the full model.

2. Examine the generated code in PI_Control_Reusable.c.

The generated code now calls the SimpleTable C function.

The figures show the generated code before and after the C code integration. Before the integration, the code calls a generated lookup routine. After the integration, the generated code calls the C function SimpleTable.

Related Topics