Use Dynamic Memory Allocation for Unbounded Variable-Size Signals in C++ Code Generation
This example shows how to generate C++ code that uses dynamic memory allocation for unbounded variable-size signals. Unbounded variable-size signals are variable-size signals that have no finite upper bounds for at least one of the signal dimensions. Therefore, these signals can transmit data with any dimension size. Allocating memory for these signals dynamically on the heap as needed at run time is beneficial when:
You do not have a mechanism to know the upper bounds of the signal dimensions.
The estimated upper bound might be a deficit or surplus to the actual upper bound. Overestimating an upper bound results in a portion of the allocated memory going unused and underestimating the upper bound can cause stack overflow.
However, allocating memory dynamically and freeing that memory at run-time can increase the code execution time.
Example Model
This example uses the model CppDynMemAlloc
.
The model includes MATLAB code in the MATLAB Function block MFB
. The code in MFB
takes and produces variable-size signals as input and output. Consider, you do not know the accurate upper bounds of the second dimension of the input and output signals. Therefore, you specify the signals as unbounded by setting the second dimension of the signals to Inf
as follows:
The Inport block
In
passes the input signal toMBF
. To create an unbounded variable-size signal whose second dimension is unbounded, the second dimension of the Port dimensions parameter is set toInf
and the Variable-size signal parameter is set toYes
in the Block Parameters dialog box.
On the Modeling tab, click Model Explorer and select the output port of
MFB
. The second dimension of the Size parameter for the output port is set toInf
. The Support variable-size arrays parameter for the block and the Variable size parameter for the relevant port are selected.
Configure Model for Dynamic Memory Allocation
To use dynamic memory allocation for unbounded variable-size signals, open the Configuration Parameters dialog box and configure the model as follows:
1. On the Solver pane, set Solver to discrete (no continuous states)
.
2. On the Data Import/Export pane, set Format to Dataset
.
3. On the Code Generation pane, set Language to C++
.
4. On the Simulation Target pane, select Dynamic memory allocation in MATLAB functions.
Generate C++ Code
After you configure the model to use dynamic memory allocation, generate code.
1. To create a code generation report and open it automatically, in the Configuration Parameters dialog box, on the Report pane, select:
Create code generation report
Open report automatically
2. To generate code, open the Simulink Coder app and click Build. Alternatively, click Ctrl+B.
### Starting build procedure for: CppDynMemAlloc ### Successful completion of build procedure for: CppDynMemAlloc Build Summary Top model targets: Model Build Reason Status Build Duration ================================================================================================================= CppDynMemAlloc Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 11.841s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 13.051s
Inspect C++ Code
1. Because the model uses the grt.tlc
system target file, the code generator defines dynamic arrays for the unbounded variable-size signals as instances of the class template coder::array
. To view the dynamic arrays, open the CppDynMemAlloc.h
file.
/* External outputs (root outports fed by signals with default storage) */ struct ExtY_CppDynMemAlloc_T { coder::array<real_T,2> out1; /* '<Root>/out1' */ coder::array<real_T,2> Out2; /* '<Root>/Out2' */ };
2. To view the implementation of the class template, open the header file coder_array.h
generated in the build folder. The top of the header file contains details about the coder::array
class interface.
3. In coder_array.h
, the code generator also implements the set_size
method in the coder
namespace. The method uses the CODER_ALLOC
and CODER_DEALLOC
macros through ensureCapacity()
to perform memory allocation and freeing dynamically for dynamic arrays.
void set_size(Dims... dims) { coder::detail::match_dimensions<N == sizeof...(dims)>::check(); set_size_i<0>(dims...); ensureCapacity(numel());
4. To view the use of set_size
method, open the CppDynMemAlloc.cpp
file. The code calls the set_size
method to allocate and free memory dynamically for the defined dynamic arrays at run time.
/* MATLAB Function: '<Root>/MFB' incorporates: * Inport: '<Root>/In' * Outport: '<Root>/out1' */ CppDynMemAlloc_Y.out1.set_size(CppDynMemAlloc_U.In.size(0), CppDynMemAlloc_U.In.size(1)); loop_ub = CppDynMemAlloc_U.In.size(1); for (i_0 = 0; i_0 < loop_ub; i_0++) { loop_ub_0 = CppDynMemAlloc_U.In.size(0); for (i = 0; i < loop_ub_0; i++) { CppDynMemAlloc_Y.out1[i + CppDynMemAlloc_Y.out1.size(0) * i_0] = CppDynMemAlloc_U.In[CppDynMemAlloc_U.In.size(0) * i_0 + i] * 5.0; } }