Generate Reusable Code from For Each Subsystems
In the model-based design, to convert inefficient repetitive algorithms into compact forms, use For Each subsystems. For Each subsystems repeat execution during a simulation time step on each element or subarray of an input signal or mask parameter array. In addition, to reduce model complexity, you can also generate reusable code for identical For Each subsystems by configuring them as reusable functions. You must configure mask and block parameters of the identical subsystems the same way. The code generator performs a checksum to determine whether subsystems are identical and the code is reusable. If the code is reusable, the code generator produces a single instance of reusable code which is shared by the identical subsystems.
This example shows how you can generate reusable code for For Each subsystems that perform the same processing on their respective inputs.
Example Model
This example generates code from the ForEachReuse
model designed in in Improved Code Reuse Using For-Each Subsystems.
model = 'ForEachReuse';
open_system(model)
The model contains three For Each subsystems Vector SS1
, Vector SS2
, and Vector SS3
that apply the same processing to each scalar element of the vector signal at their respective inputs. For example, the Vector SS3
subsystem contains these blocks.
open_system('ForEachReuse/Vector SS3');
To generate a single shared function for the three subsystems, the input signal dimension of the subsystems must be the same. For Vector SS1
and Vector SS3
, set the partition dimension and width to 1
. For Vector SS2
to also set the input signal dimension 1
, insert a Math Function block to transpose the 1-by-8 row vector into an 8-by-1 column vector. To convert the output of the subsystem back to a 1-by-8 row vector, use a second Math Function block.
The remaining For Each subsystem Matrix SS1
and Matrix SS2
process matrix signals using the same algorithm and have the same input signal dimension setting.
Generate and Inspect Code
To configure the subsystems as reusable functions, open the Block Parameters dialog box. On the Code Generation tab, set Function packaging to
Reusable function
.Generate code.
slbuild(model);
### Starting build procedure for: ForEachReuse ### Successful completion of build procedure for: ForEachReuse Build Summary Top model targets: Model Build Reason Status Build Duration =============================================================================================================== ForEachReuse Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 13.473s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 14.51s
The code generator generates a single output function VectorProcessing
in VectorProcessing.c
.
file = fullfile('ForEachReuse_grt_rtw','VectorProcessing.c'); coder.example.extractLines(file,'* Output and update for iterator system:','/* Outputs for Iterator SubSystem:',1,1);
* Output and update for iterator system: * '<Root>/Vector SS1' * '<Root>/Vector SS2' * '<Root>/Vector SS3' */ void VectorProcessing(int32_T NumIters, const real_T rtu_In1[10], real_T rty_Out1[10], DW_VectorProcessing_T localDW[10]) { /* local scratch DWork variables */ int32_T ForEach_itr; real_T rtb_Out1_CoreSubsysCanOut;
The function has an input parameter NumIters
that indicates the number of independent scalars that each For Each Subsystem block processes. This function is called three times in the ForEachReuse.c
with the parameter NumIters
set to 10
, 8
, and 7
respectively.
The code generator also generates a single output function for Matrix SS1
and Matrix SS2
subsystem in MatrixProcessing.c
which is called twice in the ForEachReuse.c
.
file = fullfile('ForEachReuse_grt_rtw','MatrixProcessing.c'); coder.example.extractLines(file,'* Output and update for iterator system:','/* Outputs for Iterator SubSystem:',1,1); bdclose(model) bdclose('ForEachReuse/Vector SS3')
* Output and update for iterator system: * '<Root>/Matrix SS1' * '<Root>/Matrix SS2' */ void MatrixProcessing(int32_T NumIters, const real_T rtu_In1[32], real_T rty_Out1[32], DW_MatrixProcessing_T localDW[2]) { /* local scratch DWork variables */ int32_T ForEach_itr; real_T rtb_MathFunction_h_0; int32_T i; int32_T rtb_MathFunction_h_tmp; int32_T tmp;