MATLAB Examples

Optimize Generated Code By Passing Reusable Subsystem Outputs as Individual Arguments

This example shows how passing reusable subsystem outputs as individual arguments instead of as a pointer to a structure stored in global memory optimizes the generated code. This optimization conserves RAM consumption and increases code execution speed by reducing global memory usage and eliminating data copies from local variables back to global block I/O structures.

Contents

Example Model

Consider the model rtwdemo_reusable_sys_outputs. In this model, the reusable subsystem outputs feed the root outputs of the model.

model = 'rtwdemo_reusable_sys_outputs';
open_system(model);

Generate Code Without This Optimization

Generate code for this model while passing subsystem outputs as a structure reference. Create a temporary folder for the build and inspection process.

currentDir = pwd;
[~,cgDir] = rtwdemodir();

Build the model.

rtwbuild(model)
### Starting build procedure for model: rtwdemo_reusable_sys_outputs
### Successful completion of build procedure for model: rtwdemo_reusable_sys_outputs

The code snippet shows portions of rtwdemo_reusable_sys_outputs.c. Notice the global block I/O structure and in the model step function a data copy from this structure.

cfile = fullfile(cgDir,'rtwdemo_reusable_sys_outputs_ert_rtw',...
'rtwdemo_reusable_sys_outputs.c');
rtwdemodbtype(cfile,'/* Output and update for atomic system',...
'/* Model initialize', 1, 0);
/* Output and update for atomic system: '<Root>/ReusableSubsystem' */
static void ReusableSubsystem(real_T rtu_In1, real_T rtu_In2, real_T rtu_In3,
  DW_ReusableSubsystem *localDW)
{
  /* Gain: '<S1>/Gain' */
  localDW->Gain = 5.0 * rtu_In1;

  /* Gain: '<S1>/Gain1' */
  localDW->Gain1 = 6.0 * rtu_In2;

  /* Gain: '<S1>/Gain2' */
  localDW->Gain2 = 7.0 * rtu_In3;
}

/* Model step function */
void rtwdemo_reusable_sys_outputs_step(void)
{
  /* Outputs for Atomic SubSystem: '<Root>/ReusableSubsystem' */

  /* Inport: '<Root>/In1' incorporates:
   *  Inport: '<Root>/In2'
   *  Inport: '<Root>/In3'
   */
  ReusableSubsystem(rtU.In1, rtU.In2, rtU.In3, &rtDW.ReusableSubsystem_d);

  /* End of Outputs for SubSystem: '<Root>/ReusableSubsystem' */

  /* Outport: '<Root>/Out1' */
  rtY.Out1 = rtDW.ReusableSubsystem_d.Gain;

  /* Outport: '<Root>/Out2' */
  rtY.Out2 = rtDW.ReusableSubsystem_d.Gain1;

  /* Outport: '<Root>/Out3' */
  rtY.Out3 = rtDW.ReusableSubsystem_d.Gain2;
}

Enable This Optimization

  1. Open the Configuration Parameters dialog box.
  2. On the Optimization > Signals and Parameters pane, set Pass reusable subsystem outputs as to Individual arguments.

Alternatively, you can use the command-line API to enable the optimization:

set_param(model, 'PassReuseOutputArgsAs', 'Individual arguments');

Generate Code With This Optimization

With this optimization, the ReusableSubsystem function has three output arguments, which are direct references to the external outputs. The rtDW global structure no longer exists, and the data copies from this structure to the rtY (external outputs) structure are not in the generated code.

Build the model.

rtwbuild(model)
### Starting build procedure for model: rtwdemo_reusable_sys_outputs
### Successful completion of build procedure for model: rtwdemo_reusable_sys_outputs

The code snippet below is a portion of rtwdemo_reusable_sys_outputs.c. Observe the optimized code.

rtwdemodbtype(cfile,'/* Output and update for atomic system',...
'/* Model initialize', 1, 0);
/* Output and update for atomic system: '<Root>/ReusableSubsystem' */
static void ReusableSubsystem(real_T rtu_In1, real_T rtu_In2, real_T rtu_In3,
  real_T *rty_Out1, real_T *rty_Out2, real_T *rty_Out3)
{
  /* Gain: '<S1>/Gain' */
  *rty_Out1 = 5.0 * rtu_In1;

  /* Gain: '<S1>/Gain1' */
  *rty_Out2 = 6.0 * rtu_In2;

  /* Gain: '<S1>/Gain2' */
  *rty_Out3 = 7.0 * rtu_In3;
}

/* Model step function */
void rtwdemo_reusable_sys_outputs_step(void)
{
  /* Outputs for Atomic SubSystem: '<Root>/ReusableSubsystem' */

  /* Inport: '<Root>/In1' incorporates:
   *  Inport: '<Root>/In2'
   *  Inport: '<Root>/In3'
   *  Outport: '<Root>/Out1'
   *  Outport: '<Root>/Out2'
   *  Outport: '<Root>/Out3'
   */
  ReusableSubsystem(rtU.In1, rtU.In2, rtU.In3, &rtY.Out1, &rtY.Out2, &rtY.Out3);

  /* End of Outputs for SubSystem: '<Root>/ReusableSubsystem' */
}

Close the model and cleanup.

bdclose(model)
rtwdemoclean;
cd(currentDir)