Use C Caller Block with Conditional Execution
This example shows how to use a C Caller block with conditional execution. The example model contains two C Caller blocks whose outputs are input branches into a Switch block. Each C Caller block calls one of the custom C code functions sort_ascend()
and sort_descend()
. Only one of the values from the input branches is passed to the output side of the Switch block. A C Function block with the same settings can also be used in place of a C Caller block to call these custom code functions.
This example illustrates the following concepts:
Calling custom C code from a Simulink® block in a conditional execution context.
Configuring deterministic functions by function in custom code.
Examine the Model
This model calls custom code through a C Caller block that is connected to an input branch of a Switch block.
open_system('slexCCallerConditional');
Generate Code
The custom code functions in this model have not been identified as deterministic functions. When code is generated from the model, both C functions are executed during simulation and in the generated code, even though the Switch block requires the output of only one of the functions.
slbuild(bdroot); cfile = fullfile('slexCCallerConditional_grt_rtw','slexCCallerConditional.c'); coder.example.extractLines(cfile,'/* Model step', '/* Matfile logging', 1, 0);
### Starting build procedure for: slexCCallerConditional ### Successful completion of build procedure for: slexCCallerConditional Build Summary Top model targets: Model Build Reason Status Build Duration ========================================================================================================================= slexCCallerConditional Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 21.841s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 24.348s /* Model step function */ void slexCCallerConditional_step(void) { real_T rtb_CCallerascend[6]; real_T rtb_CCallerdescend[6]; int32_T i; /* CCaller: '<Root>/C Caller (ascend)' incorporates: * Inport: '<Root>/In2' */ for (i = 0; i < 6; i++) { rtb_CCallerascend[i] = slexCCallerConditional_U.In2[i]; } sort_ascend(&rtb_CCallerascend[0], 6); /* End of CCaller: '<Root>/C Caller (ascend)' */ /* CCaller: '<Root>/C Caller (descend)' incorporates: * Inport: '<Root>/In2' */ for (i = 0; i < 6; i++) { rtb_CCallerdescend[i] = slexCCallerConditional_U.In2[i]; } sort_descend(&rtb_CCallerdescend[0], 6); /* End of CCaller: '<Root>/C Caller (descend)' */ for (i = 0; i < 6; i++) { /* Switch: '<Root>/Switch' incorporates: * Inport: '<Root>/In1' */ if (slexCCallerConditional_U.In1 > 0.0) { /* Outport: '<Root>/Out3' */ slexCCallerConditional_Y.Out3[i] = rtb_CCallerascend[i]; } else { /* Outport: '<Root>/Out3' */ slexCCallerConditional_Y.Out3[i] = rtb_CCallerdescend[i]; } /* End of Switch: '<Root>/Switch' */ }
Specify Custom Code Deterministic Functions
Open the Configuration Parameters dialog box.
In the Simulation Target pane, set Deterministic functions to By Function
. Click Specify by function and add the functions sort_ascend
and sort_descend
to the list. This action tells the model that the specified custom code functions have deterministic behavior, that is, the same input values to the functions always give the same outputs. If a function is set to be deterministic, it does not need to be called if it is in the input branch corresponding to a false value of the Switch block.
configset.highlightParameter(bdroot,'DefaultCustomCodeDeterministicFunctions'); set_param(bdroot,'DefaultCustomCodeDeterministicFunctions','ByFunction'); set_param(bdroot,'CustomCodeDeterministicFunctions','sort_ascend,sort_descend');
Generate Code Again
Now that you have specified the deterministic functions, the generated code is more efficient because only the C Caller block in the true branch of the Switch block is executed. The same efficiency applies when you simulate the model in Simulink.
slbuild(bdroot); cfile = fullfile('slexCCallerConditional_grt_rtw','slexCCallerConditional.c'); coder.example.extractLines(cfile,'/* Model step', '/* Matfile logging', 1, 0); close_system(bdroot, 0);
### Starting build procedure for: slexCCallerConditional ### Successful completion of build procedure for: slexCCallerConditional Build Summary Top model targets: Model Build Reason Status Build Duration ===================================================================================================== slexCCallerConditional Generated code was out of date. Code generated and compiled. 0h 0m 14.177s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 15.201s /* Model step function */ void slexCCallerConditional_step(void) { real_T rtb_CCallerascend[6]; int32_T i; /* Switch: '<Root>/Switch' incorporates: * Inport: '<Root>/In1' */ if (slexCCallerConditional_U.In1 > 0.0) { /* CCaller: '<Root>/C Caller (ascend)' incorporates: * Inport: '<Root>/In2' */ for (i = 0; i < 6; i++) { rtb_CCallerascend[i] = slexCCallerConditional_U.In2[i]; } sort_ascend(&rtb_CCallerascend[0], 6); /* End of CCaller: '<Root>/C Caller (ascend)' */ } else { /* CCaller: '<Root>/C Caller (descend)' incorporates: * Inport: '<Root>/In2' */ for (i = 0; i < 6; i++) { rtb_CCallerascend[i] = slexCCallerConditional_U.In2[i]; } sort_descend(&rtb_CCallerascend[0], 6); /* End of CCaller: '<Root>/C Caller (descend)' */ } /* End of Switch: '<Root>/Switch' */ /* Outport: '<Root>/Out3' */ for (i = 0; i < 6; i++) { slexCCallerConditional_Y.Out3[i] = rtb_CCallerascend[i]; } /* End of Outport: '<Root>/Out3' */
See Also
Deterministic functions | Specify by function | C Function | C Caller