Main Content

Separate Rate Transition Block Code and Data from Algorithm Code and Data

You can specify whether the code generator inlines code and data it produces for Rate Transition blocks with model code or places the code and data in separate functions that the model code calls. You control this by selecting the Rate Transition block code parameter. Separating Rate Transition block code and data from algorithm code and data enables you to independently analyze, optimize, and test Rate Transition block and algorithm code. By default, Rate Transition block code is set inline with algorithm code and data. You can separate the code and data so that the generated code contains separate get and set functions that the model_step functions call and a dedicated structure for state data. The generated code also contains separate start and initialize functions that the model_initialize function calls.

Example Model

Open the example model MultirateMultitaskingRateTransitions. This multirate, multitasking model contains several Rate Transition blocks operating at different modes.

model = 'MultirateMultitaskingRateTransitions';
open_system(model);

set_param(model,'SystemTargetFile','ert.tlc');
set_param(model,'GenerateComments', 'Off');

Separate Code for Rate Transition blocks

In the Configuration Parameters dialog box, the Rate Transition block code parameter is set to Function. Generate code for the model. The code is in the files MultirateMultitaskingRateTransitions.c and MultirateMultitaskingRateTransitions.h.

slbuild(model);
### Starting build procedure for: MultirateMultitaskingRateTransitions
### Successful completion of build procedure for: MultirateMultitaskingRateTransitions

Build Summary

Top model targets:

Model                                 Build Reason                                         Status                        Build Duration
=======================================================================================================================================
MultirateMultitaskingRateTransitions  Information cache folder or artifacts were missing.  Code generated and compiled.  0h 0m 13.636s 

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 14.567s
currentDir = pwd;
hfile=fullfile(currentDir, 'MultirateMultitaskingRateTransitions_ert_rtw','MultirateMultitaskingRateTransitions.h');
coder.example.extractLines(hfile,'typedef struct {','} DW;', 1, 1);
typedef struct {
  real_T OutportBufferForOut3[20];
  real_T Integrator1_DSTATE[20];
  real_T Integrator2_DSTATE[20];
  real_T Integrator3_DSTATE[20];
  real_T Integrator1_PREV_U[20];
  real_T Integrator2_PREV_U[20];
  real_T Integrator3_PREV_U[20];
  uint32_T Algorithm_PREV_T;
  struct {
    uint_T Algorithm_RESET_ELAPS_T:1;
  } bitsForTID1;

  uint8_T Integrator1_SYSTEM_ENABLE;
  uint8_T Integrator2_SYSTEM_ENABLE;
  uint8_T Integrator3_SYSTEM_ENABLE;
} DW;

For Rate Transition blocks, the state data is not in the global state structure, DW_MultirateMultitaskingRateTransitions_T. This data is in its own structure in the file MultirateMultitaskingRateTransitions_rtb.h.

This code is in the file MultirateMultitaskingRateTransitions.c.

cfile=fullfile(currentDir, 'MultirateMultitaskingRateTransitions_ert_rtw','MultirateMultitaskingRateTransitions.c');
coder.example.extractLines(cfile,'void MultirateMultitaskingRateTransitions_step0',...)
    'void MultirateMultitaskingRateTransitions_terminate(void)',1,0);
void MultirateMultitaskingRateTransitions_step0(void)
{
  (rtM->Timing.RateInteraction.TID0_1)++;
  if ((rtM->Timing.RateInteraction.TID0_1) > 1) {
    rtM->Timing.RateInteraction.TID0_1 = 0;
  }

  MultirateMul_DetAndIntegS2F_get(rtY.Out1);
  MultirateMulti_IntegOnlyS2F_get(rtY.Out2);
  memcpy(&rtY.Out3[0], &rtDW.OutportBufferForOut3[0], 20U * sizeof(real_T));
  MultirateMul_DetAndIntegF2S_set(rtU.In1);
  MultirateMulti_IntegOnlyF2S_set(rtU.In2);
}

void MultirateMultitaskingRateTransitions_step1(void)
{
  real_T rtb_DetAndIntegF2S[20];
  real_T rtb_IntegOnlyF2S[20];
  real_T Integrator3_DSTATE;
  real_T tmp;
  int32_T i;
  uint32_T Algorithm_ELAPS_T;
  MultirateMul_DetAndIntegF2S_get(rtb_DetAndIntegF2S);
  MultirateMulti_IntegOnlyF2S_get(rtb_IntegOnlyF2S);
  if (rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T) {
    Algorithm_ELAPS_T = 0U;
  } else {
    Algorithm_ELAPS_T = rtM->Timing.clockTick1 - rtDW.Algorithm_PREV_T;
  }

  rtDW.Algorithm_PREV_T = rtM->Timing.clockTick1;
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = false;
  tmp = 0.001 * (real_T)Algorithm_ELAPS_T;
  for (i = 0; i < 20; i++) {
    if (rtDW.Integrator1_SYSTEM_ENABLE == 0) {
      rtDW.Integrator1_DSTATE[i] += tmp * rtDW.Integrator1_PREV_U[i];
    }

    if (rtDW.Integrator2_SYSTEM_ENABLE == 0) {
      rtDW.Integrator2_DSTATE[i] += tmp * rtDW.Integrator2_PREV_U[i];
    }

    Integrator3_DSTATE = rtDW.Integrator3_DSTATE[i];
    if (rtDW.Integrator3_SYSTEM_ENABLE == 0) {
      Integrator3_DSTATE += tmp * rtDW.Integrator3_PREV_U[i];
    }

    rtDW.Integrator3_DSTATE[i] = Integrator3_DSTATE;
    rtDW.OutportBufferForOut3[i] = Integrator3_DSTATE;
    rtDW.Integrator1_PREV_U[i] = rtb_DetAndIntegF2S[i];
    rtDW.Integrator2_PREV_U[i] = rtb_IntegOnlyF2S[i];
    rtDW.Integrator3_PREV_U[i] = rtU.In3[i];
  }

  rtDW.Integrator1_SYSTEM_ENABLE = 0U;
  rtDW.Integrator2_SYSTEM_ENABLE = 0U;
  rtDW.Integrator3_SYSTEM_ENABLE = 0U;
  MultirateMul_DetAndIntegS2F_set(rtDW.Integrator1_DSTATE);
  MultirateMulti_IntegOnlyS2F_set(rtDW.Integrator2_DSTATE);
  rtM->Timing.clockTick1++;
}

void MultirateMultitaskingRateTransitions_initialize(void)
{
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = true;
  rtDW.Integrator1_SYSTEM_ENABLE = 1U;
  rtDW.Integrator2_SYSTEM_ENABLE = 1U;
  rtDW.Integrator3_SYSTEM_ENABLE = 1U;
}

The MultirateMultitaskingRateTransitions_step0 and MultirateMultitaskingRateTransitions_step1 functions contain calls to get and set functions. These functions contain the Rate Transition block code. These function definitions are in the file MultirateMultitaskingRateTransitions_rtb.c.

Generate Inlined Code for Rate Transition blocks

In the Configuration Parameters dialog box, set the Rate Transition block code parameter to Inline. Generate code for the model. The code is in the files MultirateMultitaskingRateTransitions.c and MultirateMultitaskingRateTransitions.h.

set_param(model,'RateTransitionBlockCode','Inline');
slbuild(model)
### Starting build procedure for: MultirateMultitaskingRateTransitions
### Successful completion of build procedure for: MultirateMultitaskingRateTransitions

Build Summary

Top model targets:

Model                                 Build Reason                     Status                        Build Duration
===================================================================================================================
MultirateMultitaskingRateTransitions  Generated code was out of date.  Code generated and compiled.  0h 0m 11.116s 

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 11.927s

This code is now in the file MultirateMultitaskingRateTransitions.h.

hfile=fullfile(currentDir, 'MultirateMultitaskingRateTransitions_ert_rtw','MultirateMultitaskingRateTransitions.h');
coder.example.extractLines(hfile, 'typedef struct {', '} DW;', 1, 1);
typedef struct {
  real_T Integrator1_DSTATE[20];
  real_T Integrator2_DSTATE[20];
  real_T Integrator3_DSTATE[20];
  real_T DetAndIntegS2F_Buffer0[20];
  volatile real_T IntegOnlyS2F_Buffer[40];
  real_T DetAndIntegF2S_Buffer[20];
  volatile real_T IntegOnlyF2S_Buffer0[20];
  real_T Integrator1_PREV_U[20];
  real_T Integrator2_PREV_U[20];
  real_T Integrator3_PREV_U[20];
  uint32_T Algorithm_PREV_T;
  struct {
    uint_T Algorithm_RESET_ELAPS_T:1;
  } bitsForTID1;

  volatile int8_T IntegOnlyS2F_ActiveBufIdx;
  volatile int8_T IntegOnlyF2S_semaphoreTaken;
  uint8_T Integrator1_SYSTEM_ENABLE;
  uint8_T Integrator2_SYSTEM_ENABLE;
  uint8_T Integrator3_SYSTEM_ENABLE;
} DW;

For Rate Transition blocks, the state data is not in the global state structure, DW_MultirateMultitaskingRateTransitions_T. This data is in its own structure in the file MultirateMultitaskingRateTransitions_rtb.h.

This code is now in the file MultirateMultitaskingRateTransitions.c.

cfile=fullfile(currentDir, 'MultirateMultitaskingRateTransitions_ert_rtw','MultirateMultitaskingRateTransitions.c');
coder.example.extractLines(cfile,'void MultirateMultitaskingRateTransitions_step0','void MultirateMultitaskingRateTransitions_terminate(void)', 1, 0);
void MultirateMultitaskingRateTransitions_step0(void)
{
  int32_T i;
  int32_T i_0;
  boolean_T tmp;
  (rtM->Timing.RateInteraction.TID0_1)++;
  if ((rtM->Timing.RateInteraction.TID0_1) > 1) {
    rtM->Timing.RateInteraction.TID0_1 = 0;
  }

  tmp = (rtM->Timing.RateInteraction.TID0_1 == 1);
  if (tmp) {
    memcpy(&rtY.Out1[0], &rtDW.DetAndIntegS2F_Buffer0[0], 20U * sizeof(real_T));
  }

  i = rtDW.IntegOnlyS2F_ActiveBufIdx * 20;
  for (i_0 = 0; i_0 < 20; i_0++) {
    rtY.Out2[i_0] = rtDW.IntegOnlyS2F_Buffer[i_0 + i];
  }

  if (tmp) {
    memcpy(&rtDW.DetAndIntegF2S_Buffer[0], &rtU.In1[0], 20U * sizeof(real_T));
  }

  if (rtDW.IntegOnlyF2S_semaphoreTaken == 0) {
    for (i = 0; i < 20; i++) {
      rtDW.IntegOnlyF2S_Buffer0[i] = rtU.In2[i];
    }
  }
}

void MultirateMultitaskingRateTransitions_step1(void)
{
  real_T rtb_IntegOnlyF2S[20];
  real_T Integrator1_DSTATE;
  real_T Out3;
  real_T tmp;
  int32_T i;
  uint32_T Algorithm_ELAPS_T;
  rtDW.IntegOnlyF2S_semaphoreTaken = 1;
  for (i = 0; i < 20; i++) {
    rtb_IntegOnlyF2S[i] = rtDW.IntegOnlyF2S_Buffer0[i];
  }

  rtDW.IntegOnlyF2S_semaphoreTaken = 0;
  if (rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T) {
    Algorithm_ELAPS_T = 0U;
  } else {
    Algorithm_ELAPS_T = rtM->Timing.clockTick1 - rtDW.Algorithm_PREV_T;
  }

  rtDW.Algorithm_PREV_T = rtM->Timing.clockTick1;
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = false;
  tmp = 0.001 * (real_T)Algorithm_ELAPS_T;
  for (i = 0; i < 20; i++) {
    Integrator1_DSTATE = rtDW.Integrator1_DSTATE[i];
    if (rtDW.Integrator1_SYSTEM_ENABLE == 0) {
      Integrator1_DSTATE += tmp * rtDW.Integrator1_PREV_U[i];
    }

    rtDW.Integrator1_DSTATE[i] = Integrator1_DSTATE;
    if (rtDW.Integrator2_SYSTEM_ENABLE == 0) {
      rtDW.Integrator2_DSTATE[i] += tmp * rtDW.Integrator2_PREV_U[i];
    }

    if (rtDW.Integrator3_SYSTEM_ENABLE != 0) {
      Out3 = rtDW.Integrator3_DSTATE[i];
    } else {
      Out3 = tmp * rtDW.Integrator3_PREV_U[i] + rtDW.Integrator3_DSTATE[i];
    }

    rtY.Out3[i] = Out3;
    rtDW.Integrator1_PREV_U[i] = rtDW.DetAndIntegF2S_Buffer[i];
    rtDW.Integrator2_PREV_U[i] = rtb_IntegOnlyF2S[i];
    rtDW.Integrator3_DSTATE[i] = Out3;
    rtDW.Integrator3_PREV_U[i] = rtU.In3[i];
    rtDW.DetAndIntegS2F_Buffer0[i] = Integrator1_DSTATE;
  }

  rtDW.Integrator1_SYSTEM_ENABLE = 0U;
  rtDW.Integrator2_SYSTEM_ENABLE = 0U;
  rtDW.Integrator3_SYSTEM_ENABLE = 0U;
  for (i = 0; i < 20; i++) {
    rtDW.IntegOnlyS2F_Buffer[i + (rtDW.IntegOnlyS2F_ActiveBufIdx == 0) * 20] =
      rtDW.Integrator2_DSTATE[i];
  }

  rtDW.IntegOnlyS2F_ActiveBufIdx = (int8_T)(rtDW.IntegOnlyS2F_ActiveBufIdx == 0);
  rtM->Timing.clockTick1++;
}

void MultirateMultitaskingRateTransitions_initialize(void)
{
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = true;
  rtDW.Integrator1_SYSTEM_ENABLE = 1U;
  rtDW.Integrator2_SYSTEM_ENABLE = 1U;
  rtDW.Integrator3_SYSTEM_ENABLE = 1U;
}

The code is inlined in functions MultirateMultitaskingRateTransitions_step0 and MultirateMultitaskingRateTransitions_step1.

Close Model

bdclose(model);

Limitation

The code generator does not separate the code and data for Rate Transition blocks that have variable-size signals or are inside of a For Each Subsystem block.

See Also