Generate Local Variables with Localizable
Storage Class
For signals, if possible, generate variables that are local to functions rather than in global storage. Generating local variables prevents the code generator from implementing optimizations that remove these variables from the generated code. Local variables improve observability, readability, and are helpful in debugging the generated code.
Minimizing the use of global variables by using local variables interacts with stack usage control. For example, stack size can determine the number of local and global variables that the code generator can allocate in the generated code. For more information, see Customize Stack Space Allocation.
Explore Example Model
This example shows how to generate local variables for signals and compares it to generating global variables for the same signals.
Open model LocalizableStorageClass
.
open_system('LocalizableStorageClass')
The model LocalizableStorageclass
contains two signals that have a Localizable
storage class. In the Latching
subsystem, the signal with the label Latch
has a Localizable
storage class. In the Debug
subsystem, the signal with the label Debug
has a Localizable
storage class.
Generate Code with Localizable
Storage Class
To observe the specification, open the Code Mappings editor. On the C Code tab, select Code Interface > Individual Element Code Mappings.
On the Signals/States tab, expand Signals. The storage class for signals Latch and Debug is set to
Localizable
.Generate and view the code. The
Debug_b
function contains this code:static void Debug_b(const real_T rtu_In1[6], const real_T rtu_In2[6], real_T rtd_A[6]) { real_T Debug; int32_T i; for (i = 0; i < 6; i++) { Debug = rtu_In1[i] * rtu_In2[i]; rtd_A[i] += Debug; } }
The
Latching
function contains this code:static void Latching(const real_T rtu_In1[36], real_T rty_Out1[6], real_T rty_Out2[6], real_T rtd_A[6]) { real_T Latch[6]; int32_T i; int32_T i_0; for (i = 0; i < 6; i++) { Latch[i] = rtd_A[i]; rty_Out2[i] = -Latch[i]; } for (i = 0; i < 6; i++) { rty_Out1[i] = 0.0; for (i_0 = 0; i_0 < 6; i_0++) { rty_Out1[i] += rtu_In1[6 * i_0 + i] * Latch[i_0]; } } }
Both functions contain variables for holding intermediate values. The
Debug_b
function contains the variableDebug
. TheLatching
function contains the variableLatch
.
Generate Code Without Localizable Storage Class
Change the signal storage class from
Localizable
toExportToFile
. In the Code Mappings editor, for each signal, set the storage class toExportToFile
.Generate and view the code. The
LocalizableStorageClass.c
file contains these two global variable declarations:real_T Debug[6]; real_T Latch[6];
The
Debug_b
function contains this code:static void Debug_b(const real_T rtu_In1[6], const real_T rtu_In2[6], real_T rtd_A[6]) { int32_T i; for (i = 0; i < 6; i++) { Debug[i] = rtu_In1[i] * rtu_In2[i]; rtd_A[i] += Debug[i]; } }
The
Latching
function contains this code:static void Latching(const real_T rtu_In1[36], real_T rty_Out1[6], real_T rty_Out2[6], real_T rtd_A[6]) { int32_T i; int32_T i_0; for (i = 0; i < 6; i++) { Latch[i] = rtd_A[i]; rty_Out2[i] = -Latch[i]; } for (i = 0; i < 6; i++) { rty_Out1[i] = 0.0; for (i_0 = 0; i_0 < 6; i_0++) { rty_Out1[i] += rtu_In1[6 * i_0 + i] * Latch[i_0]; } } }
The code readability and observability is the same as with the
Localizable
storage class specification except the labeled signals are global variables.Remove the
Debug
andLatch
signals from the code mappings. In the Code Mappings editor, select each signal and click the Remove Signal button.Save the model.
Generate and review the code. The
Debug_b
function contains this code:static void Debug(const real_T rtu_In1[6], const real_T rtu_In2[6], real_T rtd_A[6]) { int32_T i; for (i = 0; i < 6; i++) { rtd_A[i] += rtu_In1[i] * rtu_In2[i]; } }
The
Latching
function contains this code:static void Latching(const real_T rtu_In1[36], real_T rty_Out1[6], real_T rty_Out2[6], real_T rtd_A[6]) { int32_T i; int32_T i_0; for (i = 0; i < 6; i++) { rty_Out2[i] = -rtd_A[i]; rty_Out1[i] = 0.0; for (i_0 = 0; i_0 < 6; i_0++) { rty_Out1[i] += rtu_In1[6 * i_0 + i] * rtd_A[i_0]; } } }
Without the
Localizable
orExportToFile
storage classes, the code generator removes theDebug
andLatch
variables. Without these variables, the readability and observability of the generated code decreases.
Additional Information
For the code generator to localize signals with the
Localizable
storage class specification, select model configuration parameter Enable Local Block Outputs. This parameter is on by default.You can specify the same
Localizable
storage class on two signals that are in different reusable subsystems. Therefore, you can create a library block from a reusable subsystem with aLocalizable
storage class specification.The code generator does not create a local variable for a signal that must stay global. A few cases in which the code generator cannot localize a signal are:
Input and output signals of a nonreusable subsystem even when the Function interface parameter is set to
Allow arguments (Optimized)
.Signal is holding a state because its receiver and drive blocks execute at different rates.
Localizable
specification is on a signal that crosses the boundary of a conditionally executed subsystem.