Simulink CG Guidelines
Simulink CG Guidelines
R2024b
How to Contact MathWorks
Phone: 508-647-7000
Introduction
1
Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2
Block Considerations
2
cgsl_0102: Evenly spaced breakpoints in lookup tables . . . . . . . . . . . . . . . 2-2
cgsl_0202: Usage of For, While, and For Each subsystems with vector
signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-6
v
Component Deployment Using Service Interface Configuration
5
cgsl_0401: Modeling styles for component deployment . . . . . . . . . . . . . . . 5-2
vi Contents
1
Introduction
Motivation
Code generation modeling guidelines provide recommendations that you can use when developing
models and generating code that is intended for use in embedded systems. The guidelines, which take
into consideration the potential impact to simulation behavior, code generation, and component
model deployment, include information about configuration settings, block usage and parameters,
and modeling patterns.
The guidelines do not address model style or compliance with industry standards. For additional
information, see:
• “MAB Modeling Guidelines” — Modeling guidelines that address model consistency, clarity, and
readability.
• “High-Integrity System Modeling” — Modeling guidelines that address compliance with industry
standards.
For information about qualifying software development and verification tools that are used to develop
embedded system for projects that must comply with an industry standard, see:
• IEC Certification Kit — Guidance on certifying your embedded systems for use in projects that
must comply with ISO 26262, IEC 61508, EN 50128, EN 50657, ISO 25119, and related
functional-safety standards such as IEC 62304.
• “DO Qualification Kit (for DO-178)” — Guidance on qualifying your software verification tools for
use in projects involving the DO-178C and DO-254 standards.
Disclaimer While adhering to the recommendations in the guidelines will reduce the risk that an
error is introduced during development and not be detected, it is not a guarantee that the system
being developed will be safe. Conversely, if some of the recommendations in the guidelines are not
followed, it does not mean that the system being developed will be unsafe.
1-2
Guideline Template
Guideline Template
Guideline descriptions are documented, using the following template. Companies that want to create
additional guidelines are encouraged to use the same template.
1-3
2
Block Considerations
For check details, see “Identify questionable fixed-point operations” (Embedded Coder).
See Also “Formulation of Evenly Spaced Breakpoints”
Last Changed R2010b
2-2
cgsl_0103: Precalculated signals and parameters
2-3
2 Block Considerations
Inlining data reduces the ability to tune model parameters. You should
define parameters that require calibration to allow calibration. For more
information, see “Create Tunable Calibration Parameter in the
Generated Code” (Simulink Coder).
2-4
3
3-2
cgsl_0201: Redundant Unit Delay and Memory blocks
For the top path in the preceding example, the equations for the blocks are:
1 Out_1(t) = UD_1(t)
2 UD_1(t) = In_1(t-1) * Cal_1
In contrast, if you add a secondary signal to the equations, the location of the Unit Delay
block impacts the result. As the following example shows, the location of the Unit Delay
block impacts the results due to the skewing of the time sample between the top and
bottom paths.
In cases with a single source and multiple destinations, the comparison is more complex.
For example, in the following model, you can refactor the two Unit Delay blocks into a
single unit delay.
3-3
3 Modeling Pattern Considerations
From a black box perspective, the two models are equivalent. However, from a memory and
computation perspective, differences exist between the two models.
{
real_T rtb_Gain4;
rtb_Gain4 = Cal_1 * Redundant;
Y.Redundant_Gain = Cal_2 * rtb_Gain4;
Y.Redundant_Int = DWork.Int_A;
Y.Redundant_Int_UD = DWork.UD_A;
Y.Redundant_Gain_UD = DWork.UD_B;
DWork.Int_A = 0.01 * rtb_Gain4 + DWork.Int_A;
DWork.UD_A = Y.Redundant_Int;
DWork.UD_B = Y.Redundant_Gain;
}
{
real_T rtb_Gain1;
real_T rtb_UD_C;
rtb_Gain1 = Cal_1 * Reduced;
rtb_UD_C = DWork.UD_C;
Y.Reduced_Gain_UD = Cal_2 * DWork.UD_C;
Y.Reduced_Gain = Cal_2 * rtb_Gain1;
Y.Reduced_Int = DWork.Int_B;
Y.Reduced_Int_UD = DWork.Int_C;
DWork.UD_C = rtb_Gain1;
DWork.Int_B = 0.01 * rtb_Gain1 + DWork.Int_B;
DWork.Int_C = 0.01 * rtb_UD_C + DWork.Int_C;
}
In this case, the original model is more efficient. In the first code example, there are three
global variables, two from the Unit Delay blocks (DWork.UD_A and DWork.UD_B) and one
from the discrete time integrator (DWork.Int_A). The second code example shows a
reduction to one global variable generated by the unit delays (Dwork.UD_C), but there are
two global variables due to the redundant Discrete Time Integrator blocks (DWork.Int_B
and DWork.Int_C). The Discrete Time Integrator block path introduces an additional local
variable (rtb_UD_C) and two additional computations.
3-4
cgsl_0201: Redundant Unit Delay and Memory blocks
{
real_T rtb_Gain4_f:
real_T rtb_Int_D;
rtb_Gain4_f = Cal_1 * U.Input;
rtb_Int_D = DWork.Int_D;
Y.R_Int_Out = DWork.UD_D;
Y.R_Gain_Out = DWork.UD_E;
DWork.Int_D = 0.01 * rtb_Gain4_f + DWork.Int_D;
DWork.UD_D = rtb_Int_D;
DWork.UD_E = Cal_2 * rtb_Gain4_f;
}
{
real_T rtb_UD_F;
rtb_UD_F = DWork.UD_F;
Y.Gain_Out = Cal_2 * DWork.UD_F;
Y.Int_Out = DWork.Int_E;
DWork.UD_F = Cal_1 * U.Input;
DWork.Int_E = 0.01 * rtb_UD_F + DWork.Int_E;
}
The code for the refactored model is more efficient because the branches from the root
signal do not have a redundant unit delay.
3-5
3 Modeling Pattern Considerations
Recommended
A common mistake is to embed basic vector operations in a For, While, or For Each
subsystem. The following example includes a simple vector gain inside a For
subsystem, which results in unnecessary nested for loops.
Not Recommended
3-6
cgsl_0204: Vector and bus signals crossing into atomic subsystems or Model blocks
3-7
3 Modeling Pattern Considerations
ID: Title cgsl_0204: Vector and bus signals crossing into atomic subsystems or
Model blocks
Last Changed R2023b
Examples Nonvirtual bus entering a model block:
There are no data copies in the code for the main model. The whole bus is passed to
the model reference function.
3-8
4
Prioritizing code efficiency objectives above safety objectives may remove initialization
or run-time protection code (for example, saturation range checking for signals out of
representable range). Review the resulting parameter configurations to verify that
safety requirements are met.
Rationale A, B, C When you use the Code Generation Advisor, configuration parameters conform
to the objectives that you want and they are consistently enforced.
See also • “Application Objectives Using Code Generation Advisor” (Simulink Coder)
• “Manage Configuration Sets for a Model”
Last Changed R2015b
4-2
5
For rate-based models, the code generator produces initialize and terminate
entry-point functions and an entry-point function for the rate of the model.
Rationale Support generation of callable entry-point functions in a component modeling
architecture.
Model Advisor Check Verify this guideline by using Model Advisor check “Check modeling style for
component deployment” (Embedded Coder)
Examples Export-Function Modeling Style
See Also
“Code Interfaces and Code Interface Specification” (Embedded Coder)
5-2
Version History
Version History
5-3
5 Component Deployment Using Service Interface Configuration
5-4
cgsl_0402: Signal interfaces for component deployment
5-5
5 Component Deployment Using Service Interface Configuration
Only the selected vector is passed to the function because the vector is
selected before the subsystem interface. The function requires a data copy of
the vector independent of the nonvirtual bus.
See Also
“Code Interfaces and Code Interface Specification” (Embedded Coder)
In Bus Element
Inport
Outport
Version History
5-6
cgsl_0404: Model startup and shutdown events by using Initialize Function and Terminate Function blocks for component deployment
ID: Title cgsl_0404: Model startup and shutdown events by using Initialize Function and
Terminate Function blocks for component deployment
Description To model startup and shutdown behavior, use Initialize Function and Terminate Function
blocks.
Notes By following this guideline, the code generator produces one initialize function and one
terminate function.
When a Terminate Function block is not needed in the model, clear model configuration
parameter Terminate function required (IncludeMdlTerminateFcn).
Rationale Decouples the execution order of component initialize and terminate functions from the
execution order across components.
Separates component startup and shutdown functionality from periodic and aperiodic
algorithm function code.
Model Advisor Verify this guideline by using Model Advisor check “Check Startup and Shutdown Event”
Check (Embedded Coder).
Examples
void CD_initialize(void)
{
.
.
.
}
void CD_terminate(void)
{
.
.
.
}
See Also
“Startup, Reset, and Shutdown Function Interfaces” (Embedded Coder)
Initialize Function
Terminate Function
5-7
5 Component Deployment Using Service Interface Configuration
Version History
5-8
cgsl_0405: Data receive for component deployment
5-9
5 Component Deployment Using Service Interface Configuration
void CD_integrator(void)
{
.
.
.
real_T tmp[10];
.
.
.
get_CD_integrator_input(&tmp[0]);
.
.
.
for (i = 0; i < 10; i++) {
5-10
Version History
void CD_integrator(void)
{
.
.
.
for (i = 0; i < 10; i++) {
.
.
.
... = CD_sig.In[i];
}
.
.
.
}
See Also
“Code Interfaces and Code Interface Specification” (Embedded Coder)
“Select Code Generation Output for Target Platform Deployment” (Embedded Coder)
Inport block
Version History
5-11
5 Component Deployment Using Service Interface Configuration
5-12
cgsl_0406: Data send for component deployment
void CD_accumulator(void)
{
.
.
.
for (i = 0; i < 10; i++) {
.
(set_CD_accumulator_out())[i] = CD_param.tunable_gain * CD_sig.delay[i];
}
}
void CD_accumulator(void)
{
real_T out[10];
.
.
.
for (i = 0; i < 10; i++) {
.
out[i] = CD_param.tunable_gain * CD_sig.delay[i];
}
set_CD_accumulator_out(&out[0]);
}
5-13
5 Component Deployment Using Service Interface Configuration
See Also
“Code Interfaces and Code Interface Specification” (Embedded Coder)
“Select Code Generation Output for Target Platform Deployment” (Embedded Coder)
Outport
Version History
5-14
cgsl_0408: Partial data send for component deployment
void Run1(void)
{
Out[1] = In + 1.0;
}
void Run2(void)
{
Out[0] = In;
}
5-15
5 Component Deployment Using Service Interface Configuration
See Also
“Code Interfaces and Code Interface Specification” (Embedded Coder)
Assignment
Version History
5-16
cgsl_0409: Data transfer for component deployment
5-17
5 Component Deployment Using Service Interface Configuration
void CD_accumulator(void)
.
.
.
tmpIrvIRead = get_CD_accumulator_DataTransfer();
.
.
.
void CD_integrator(void)
.
.
.
tmp = set_CD_integrator_DataTransfer();
.
.
.
void CD_Aperiodic2(void)
.
.
tmp = set_CD_Aperiodic2_DataTransfer();
.
.
.
See Also
“Code Interfaces and Code Interface Specification” (Embedded Coder)
“Select Code Generation Output for Target Platform Deployment” (Embedded Coder)
5-18
Version History
Version History
5-19
5 Component Deployment Using Service Interface Configuration
When using S-function to set the timer, for aperiodic functions that are driven
by an S-function that specifies the SS_OPTION_ASYNCHRONOUS option and a
clock resolution, the clock resolution that the S-function specifies overrides the
setting of the Clock resolution parameter.
Rationale Robust handling of data access by functions that execute concurrently.
Model Advisor Check A Model Advisor check is not provided for this guideline.
5-20
cgsl_0410: Timer service for component deployment
typedef struct {
real_T delay[10];
real_T dti[10];
} CD_measured_T;
.
.
.
extern void CD_integrator(void);
CD_measured_T CD_measured;
.
.
.
void CD_integrator(void)
{
real_T tmp;
real_T *tmp_0;
int32_T i;
uint32_T Integrator_ELAPS_T;
tmp_0 = set_CD_integrator_DataTransfer();
if (rtDwork.Integrator_RESET_ELAPS_T) {
Integrator_ELAPS_T = 0U;
} else {
Integrator_ELAPS_T = (uint32_T)(get_tick_outside_CD_integrator() -
rtDWork.Integrator_PREV_T);
}
rtDWork.Integrator_PREV_T = get_tick_outside_CD_integrator();
rtDwork.Integrator_RESET_ELAPS_T = false;
tmp = 1.25 * (real_T)Integrator_ELAPS_T;
for (i = 0; i < 10; i++) {
if ((int32_T)rtDWork.DiscreteTimeIntegrator_SYSTEM_E == 0) {
CD_measured.dti[i] += tmp * rtDWork.DiscreteTimeIntegrator_PREV_U[i];
}
rtDWork.DiscreteTimeIntegrator_PREV_U[i] = (get_CD_
integrator_InBus_u())[i];
}
5-21
5 Component Deployment Using Service Interface Configuration
rtDWork.DiscreteTimeIntegrator_SYSTEM_E = 0U;
memcpy(&tmp_0[0], &CD_measured.dti[0], (uint32_T)(10U * sizeof(real_T)));
}
In this source code example, the data communication method is set to During-
Execution.
void CD_integrator(void)
{
real_T tmp[10];
real_T tmp_0;
int32_T i;
uint32_T Integrator_ELAPS_T;
rtM->Timing.clockTick2 = get_tick_during_CD_integrator();
if (rtDWork.Interator_RESET_ELAPS_T) {
Integrator_ELAPS_T = 0U;
} else {
Integrator_ELAPS_T = (uint32_T)(rtM->Timing.clockTick2 -
rtDWork.Integrator_PREV_T);
}
get_CD_integrator_input_(&tmp[0]);
rtDWork.Integrator_PREV_T = rtM->Timing.clockTick2;
rtDWork.Integrator_RESET_ELAPS_T = false;
tmp_0 = 1.25 * (real_T)Integrator_ELAPS_T;
for (i = 0; i < 10; i++) {
if ((int32_T)rtDWork.DiscreteTimeIntegrator_SYSTEM_E == 0) {
CD_measured.dti[i] += tmp_0 * rtDWork.DiscreteTimeIntegrator_PREV_U[i];
}
rtDWork.discreteTimeIntegrator_PREV_U[i] = tmp[i];
}
rtDWork.DiscreteTimeIntegrator_SYSTEM_E = 0U;
set_CD_integrator_DataTransfer(CD_measured.dti);
}
See Also
“Code Interfaces and Code Interface Specification” (Embedded Coder)
“Generate C Timer Service Interface Code for Component Deployment” (Embedded Coder)
Version History
5-22
cgsl_0411: Access nonvolatile memory by using Initialize Function and Terminate Function blocks
ID: Title 0411: Access nonvolatile memory by using Initialize Function and Terminate
Function blocks
Description To model the Direct Access data communication method to target platform nonvolatile
memory:
A At the root-level of the component, use the Initialize Function block to read
data and the Terminate Function block to write data.
B Configure the root-level ports to use the Direct Access data communication
method.
Notes When accessing nonvolatile memory during function execution, see guideline “cgsl_0406:
Data send for component deployment” on page 5-12 and “cgsl_0405: Data receive for
component deployment” on page 5-9.
When you need to access nonvolatile memory by using a service provided by the target
environment, use a client-server interface approach for modeling the interface. With that
approach you represent the target environment service that provides access to nonvolatile
memory by using a Simulink Function block and access the service by using the Function
Caller block. For more information, see “Nonvolatile Memory Interfaces” (Embedded
Coder).
Rationale • Robust handling of data access by functions that execute concurrently.
• Supports multiple instances of components.
Model Advisor A Model Advisor check is not provided for this guideline.
Check
5-23
5 Component Deployment Using Service Interface Configuration
ID: Title 0411: Access nonvolatile memory by using Initialize Function and Terminate
Function blocks
Examples
void CD_initialize(void)
.
.
.
&(get_CD_initialize_input[))[0]
.
.
.
void CD_terminate(void)
{
memcpy[&(getref_CD_terminate_OutBus_NVM[))[0]...
}
See Also
“Code Interfaces and Code Interface Specification” (Embedded Coder)
Initialize Function
Terminate Function
Reset Function
5-24
Version History
Version History
5-25
5 Component Deployment Using Service Interface Configuration
ID: Title cgsl_0413: Reuse memory between component state and output for component
deployment
Description To optimize component memory usage by reusing memory for state and output data, use
one of these methods:
A Use a function loopback pattern to model the state variable as a signal.
B Use a Delay block to model the state variable explicitly. Set the state of the
Delay block and the function output port to the same literal initial condition
value.
Notes This approach is applicable for data communication methods Outside Execution and
Direct Access because these methods can access persistent memory.
For method B, the code generator makes a best effort to optimize memory usage. Under
some conditions, such as when initialization is done dynamically by using a signal rather
than a parameter, the code generator might not apply the optimization. If the optimization
does not occur, consider using method A. Regardless of whether you use approach A or B,
the code generator implements robust handling of data access by functions that execute
concurrently.
Rationale A Reuse of memory for state and output data.
5-26
cgsl_0413: Reuse memory between component state and output for component deployment
ID: Title cgsl_0413: Reuse memory between component state and output for component
deployment
Examples
void CD_accumulator(void)
{
int32_T i;
for (i=0; i<10; i++) {
Out[i] += In[i];
}
}
void CD_accumulator(void)
{
real_T tmpIrvRead[10];
int32_T i;
tmp = set_CD_accumulator_her_out_y();
for (i=0; i<10; i++) {
tmp[i] = (get_CD_accumulator_DataTransfer(tmpIrvRead))[i] + tmp[i];
}
}
See Also
“Code Interfaces and Code Interface Specification” (Embedded Coder)
5-27
5 Component Deployment Using Service Interface Configuration
Delay
Version History
5-28
cgsl_0414: Configure service interface for component model
See Also
“Code Interfaces and Code Interface Specification” (Embedded Coder)
Version History
5-29