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 20.189s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 21.809s
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 13.48s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 14.801s
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.