Inline S-Functions with TLC

timesN Tutorial Overview

Objective: To understand how TLC works with an S-function.

Folder: matlabroot/toolbox/rtw/rtwdemos/tlctutorial/timesN (open)

In this tutorial, you generate versions of C code for existing S-function timesN.

The tutorial includes these steps:

  1. Noninlined Code Generation — Via SimStructs and generic API

  2. Why Use TLC to Inline S-Functions? — Benefits of inlining

  3. Create an Inlined S-Function — Via custom TLC code

A later tutorial provides information and practice with “wrapping” S-functions.

Noninlined Code Generation

The tutorial folder tlctutorial/timesN in your working folder contains Simulink® S-function timesN.c.

In this exercise, you generate noninlined code from the model sfun_xN.

  1. Find the file rename_timesN.tlc in tlctutorial/timesN. Rename this file to timesN.tlc. This allows you to generate code.

  2. In the MATLAB® Command Window, create a MEX-file for the S-function:

    mex timesN.c

    This avoids picking up the version shipped with Simulink.

  3. Open the model sfun_xN, which uses the timesN S-function. The block diagram looks like this.

  4. Open the Configuration Parameters dialog box and select the Solver pane.

  5. Set Stop time to 10.0.

  6. Set the Solver Options.

    • Type to Fixed-step

    • Solver to Discrete (no continuous states)

    • Fixed-step size to 0.01

  7. Select the Optimization pane, and make sure that Default parameter behavior is set to Tunable.

  8. Select the Code Generation > Comments pane, and notice that Include comments is checked by default.

  9. Select the Code Generation pane and check Generate code only.

    Click Apply.

  10. Press Ctrl+B to generate C code for the model.

  11. Open the resulting file sfun_xN_grt_rtw/sfun_xN.c and view the sfun_xN_output portion, shown below.

/* Model output function */
static void sfun_xN_output(int_T tid)
{
  /* Sin: '<Root>/Sin' */
  sfun_xN_B.Sin = sin(sfun_xN_M->Timing.t[0] * sfun_xN_P.Sin_Freq +
                      sfun_xN_P.Sin_Phase) * sfun_xN_P.Sin_Amp +
    sfun_xN_P.Sin_Bias;

  /* S-Function Block: <Root>/S-Function */
  /* Multiply input by 3.0 */
  sfun_xN_B.timesN_output = sfun_xN_B.Sin * 3.0;

  /* Outport: '<Root>/Out' */
  sfun_xN_Y.Out = sfun_xN_B.timesN_output;
  UNUSED_PARAMETER(tid);
}

Comments appear in the code because, in the Code Generation > Comments pane of the Configuration Parameters dialog box, Include comments is selected by default.

Why Use TLC to Inline S-Functions?

The code generator includes a generic API that you can use to invoke user-written algorithms and drivers. The API includes a variety of callback functions — for initialization, output, derivatives, termination, and so on — as well as data structures. Once coded, these are instantiated in memory and invoked during execution via indirect function calls. Each invocation involves stack frames and other overhead that adds to execution time.

In a real-time environment, especially when many solution steps are involved, generic API calls can be unacceptably slow. The code generator can speed up S-functions in standalone applications that it generates by embedding user-written algorithms within auto-generated functions, rather than indirectly calling S-functions via the generic API. This form of optimization is called inlining. TLC inlines S-functions, resulting in faster, optimized code.

You should understand that TLC is not a substitute for writing C code S-functions. To invoke custom blocks within Simulink, you still have to write S-functions in C (or as MATLAB files), since simulations do not make use of TLC files. You can, however, prepare TLC files that inline specified S-functions to make your target code much more efficient.

Create an Inlined S-Function

TLC creates an inlined S-function whenever it detects a .tlc file with the same name as an S-function. Assuming the .tlc file has the expected form, it directs construction of code that functionally duplicates the external S-function without incurring API overhead. See how this process works by completing the following steps:

  1. If you have not done so already, find the file rename_timesN.tlc in tlctutorial/timesN. Rename this file to timesN.tlc, so you can use it to generate code. The executable portion of the file is

    %implements "timesN" "C"
    
    %% Function: Outputs ===========================================================
    %%
    %function Outputs(block, system) Output
      %assign gain =SFcnParamSettings.myGain
      /* %<Type> Block: %<Name> */
      %%
      /* Multiply input by %<gain> */
      %assign rollVars = ["U", "Y"]
      %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
        %<LibBlockOutputSignal(0, "", lcv, idx)> = \
        %<LibBlockInputSignal(0, "", lcv, idx)> * %<gain>;
      %endroll
    
    %endfunction
  2. Create the inline version of the S-function.

    1. On the Optimization pane of the Configuration Parameters dialog box, set Default parameter behavior to Inlined, and click Apply.

    2. Change the diagram’s label from model: sfun_xN to model: sfun_xN_ilp.

    3. Save the model as sfun_x2_ilp.

    4. Press Ctrl+B. Source files are created in a new subfolder called sfun_xN_ilp_grt_rtw.

    5. Inspect the code in generated file sfun_xN_ilp.c:

      /* Model output function */
      static void sfun_xN_ilp_output(int_T tid)
      {
        /* Sin: '<Root>/Sin' */
        sfun_xN_ilp_B.Sin = sin(sfun_xN_ilp_M->Timing.t[0]);
      
        /* S-Function Block: <Root>/S-Function */
        /* Multiply input by 3.0 */
        sfun_xN_ilp_B.timesN_output = sfun_xN_ilp_B.Sin * 3.0;
      
        /* Outport: '<Root>/Out' */
        sfun_xN_ilp_Y.Out = sfun_xN_ilp_B.timesN_output;
        UNUSED_PARAMETER(tid);
      }

      Note

      When the code generator produces code and builds executables, it creates or uses a specific subfolder (called the build folder) to hold source, object, and make files. By default, the build folder is named model_grt_rtw.

      Notice that setting Default parameter behavior to Inlined did not change the code. This is because TLC inlines S-functions.

  3. Continue the exercise by creating a standalone simulation.

    1. In the Code Generation pane of the Configuration Parameters dialog box, clear Generate code only and click Apply.

    2. In the Data Import/Export pane of the Configuration Parameters dialog box, check Output.

      This specification causes the model’s output data to be logged in your MATLAB workspace.

    3. Press Ctrl+B to generate code, compile, and link the model into an executable, named sfun_xN_ilp.exe (or, on UNIX® systems, sfun_xN_ilp).

    4. Confirm that the timesN.tlc file produces expected output by running the standalone executable. To run it, in the MATLAB Command Window, type

      !sfun_xN_ilp

      The following response appears:

      ** starting the model **
      ** created sfun_xN_ilp.mat **
    5. View or plot the contents of the sfun_xN_ilp.mat file to verify that the standalone model generated sine output ranging from -3 to +3. In the MATLAB Command Window, type

      load sfun_xN_ilp.mat
      plot (rt_yout)

Tip

For UNIX platforms, run the executable program in the Command Window with the syntax !./executable_name. If preferred, run the executable program from an OS shell with the syntax ./executable_name. For more information, see Run External Commands, Scripts, and Programs.

Related Topics