Simulink Subsystem Semantics
This set of examples shows different types of Simulink® Subsystems and what semantics are used when simulating these subsystems. Each example provides a description of the model and the subtleties governing how the model is executed.
Examples are provided for subsystem types.
Virtual and nonvirtual subsystems
Function-Call subsystems
Triggered subsystems
Enabled subsystems
Enabled and Triggered subsystems
If Action and Switch Case Action subsystems
While Iterator subsystems
For Each subsystems
For Iterator subsystems
Open the models.
open('SimulinkSubsystemSemantics.prj'); open_system('sl_subsys_semantics');
Virtual and Nonvirtual Subsystems Overview
Simulink software has two classes of subsystems.
Virtual subsystems provide graphical hierarchy in models. Virtual subsystems do not impact model execution. During model execution, the Simulink engine flattens all virtual subsystems.
Nonvirtual subsystems provide execution and graphical hierarchy in models. Nonvirtual subsystems are executed as a single unit, known as atomic execution. All nonvirtual subsystems appear with a bold border in the Simulink canvas.
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/Virtual and nonvirtual subsystem overview');
To create a nonvirtual subsystem, right-click the Subsystem block and select Block Parameters (Subsystem). In the Block Parameters dialog box, select Treat as atomic unit and click Apply.
The virtual subsystem results in a flat execution list, whereas the nonvirtual subsystem includes execution hierarchy. To display the execution order, in the Simulink Editor, on the Debug tab, select Information Overlays and click Execution order.
The Execution Order Block List that appears on the Simulink canvas displays the execution order.
The Execution Order Block List shows that the nonvirtual subsystem Subsystem2
executed as a single unit.
A nonvirtual subsystem results in an algebraic loop within the execution hierarchy. When you update the diagram, the software issues the warning for the algebraic loop.
set_param(gcs,'SimulationCommand','Update')
Warning: Model 'sl_subsys_overview' contains 1 algebraic loops.
Function-Call Subsystems
A Function-Call Subsystem block contains a conditionally executed subsystem that runs each time the control port receives a function-call event. Function-call subsystems implement callable functions using Simulink blocks. A Stateflow® Chart (Stateflow), Function-Call Generator block, MATLAB Function block, S-Function block, or Hit Crossing block can provide function-call events.
For more information, see Function-Call Subsystem.
These examples show valid and invalid uses of function-call subsystems.
close_system('sl_subsys_overview',0) open_system('s_Function_call_subsystems')
Nested Function Call
In this model, the Chart is a function-call initiator that executes the function, [d1,d2]=f()
. The function f
, in turn, executes the function g
. After invoking f
and g
, the Chart uses the values d1
and d2
computed by f
and g
.
open_system('sl_subsys_fcncall1')
close_system('sl_subsys_fcncall1')
Nested Function Call with Data Sharing
The Chart block executes the function, [d1,d2]=f()
, and f
in turn executes g
. After invoking f
, the Chart uses the values d1
and d2
computed by f
and g
. The functions f
and g
share data via the signal s(f/Out2 feeds g/In1)
. Simulink treats the signal s
as if the signal were a datastore.
open_system ('sl_subsys_fcncall2')
In general, the inputs to a function-call subsystem must be executed before the function-call initiator (Chart), except when the signal comes from a block executed by a common function-call initiator. In this example, f()
is a function-call initiator of g()
. However, the Chart is a function-call initiator of f()
, which makes the Chart a common function-call initiator of both f()
and g()
.
In that sense, the signal s
below can be thought of as a datastore that f()
and g()
read from and write to in any given order defined by the Chart.
close_system('sl_subsys_fcncall2')
Data Sharing Between Two Function-Call Subsystems with Common Initiator
In this model, d1
and d2
are computed using g()
and f()
, respectively. The Chart uses d1
and d2
as input and invokes g()
and f()
. The functions f
and g
share data via the signal s
, in other words, (f/Out1)
feeds (g/In1)
. The model treats the signal s
as if the signal is a data store.
open_system ('sl_subsys_fcncall3')
In general, the inputs to a function-call subsystem must be executed before the function-call initiator (Chart), except when the signal comes from a block executed by a common function-call initiator. In this example, the Chart is a common function-call initiator of both f()
and g()
. Therefore, the signal s
can be thought of as a data store.
close_system('sl_subsys_fcncall3')
Enabled Subsystem Containing Function-Call Initiator with Data Sharing
This enabled subsystem contains a Stateflow chart that invokes the functions f()
and g()
. The enabled subsystem in the model sl_subsys_fcncall4
is a common function-call initiator of both f()
and g()
, so the software treats the signal s
as a datastore.
open_system ('sl_subsys_fcncall4')
close_system('sl_subsys_fcncall4')
Function-Call Subsystem with Merge Blocks
This model contains a chart that executes two function-calls. The model uses Merge blocks to map multiple signals onto a single memory location. The signals f/d1_out
and g/d1_out
are merged into a single memory location and fed back to the Chart as d1
. The signals f/k_out
and g/k_out
are merged into a single memory location and fed back to f/k_in
. Merging signals into a single memory location and feeding them back to the Chart allows the Chart to make complex decisions about how to compute values.
open_system ('sl_subsys_fcncall5')
close_system('sl_subsys_fcncall5')
Multiple Initiators of Function-Call Subsystem
This function-call subsystem is called by two different function-call initiators, Chart1
and Chart2
. The data connection between Chart1/out1
and Chart2/d1
guarantees that Chart1
executes before Chart2
. You must be careful when creating function-call subsystems with multiple callers.
For example, if you remove the data connection between Chart1
and Chart2
, then you need to add priorities to Chart1
and Chart2
to specify the relative execution order of these blocks. Failure to do so results in ambiguous execution order.
However, the software does not give an error for this condition because the condition may be valid for specific cases. As an example, if you remove all states from f()
and you delete the line connecting Chart1/out1
to Chart2/d1
, then the order in which Chart1
and Chart2
execute does not matter.
open_system ('sl_subsys_fcncall6')
close_system('sl_subsys_fcncall6')
Enabled Subsystem Containing Function-Call Subsystems That Specify Reset Behavior
This enabled subsystem contains two function-call subsystems. The left function-call subsystem is configured to hold the value of its states when it is enabled and to hold the value of its output when it is disabled. The right function-call subsystem is configured to reset the value of its states when it is enabled, and to reset the value of its output when it is disabled.
open_system ('sl_subsys_fcncall7')
close_system('sl_subsys_fcncall7')
Function-Call Subsystems Specify Periodic Execution
This Stateflow chart schedules the execution order of function-call subsystems in the model. However, the function-call subsystems are executed exactly once every time step. The function calls do not specify conditional execution but rather control the relative order of execution of the subsystems. This setting can be useful when data is transferred between the subsystems using datastores to ensure the proper sequence for reading from and writing to the datastores. Since the function-call subsystems are intended to be executed unconditionally, you should specify that they have a periodic sample time using the Sample time parameter of the Trigger blocks in the subsystems. As a consequence, during simulation, the Simulink engine verifies that the periodic function-call subsystems are executed exactly once per time step.
In addition, when code is generated, elapsed time inside the function-call subsystems is represented by a literal value (the specified, constant sample time) instead of being maintained and computed from timers, as is standard for a function-call subsystem. Therefore, the generated code is significantly more efficient.
To view the sample time of subsystems, in the Simulink Editor, on the Debug tab, select Information Overlays and click Colors.
open_system ('sl_subsys_fcncall8')
The sample time color of the function-call subsystems is red rather than cyan, indicating a periodic rather than triggered sample time. If the function-call connections are interchanged, the result is delayed one time step due to the modified interaction between the Data Store Read and Data Store Write blocks in the subsystems.
close_system('sl_subsys_fcncall8')
Function-Call Initiator Issues Active and Inactive Events
This Stateflow chart specifies that the event activate
is bound to the state ON
. When the state ON
transitions to being active, the function-call subsystem Integrate
, initiated by that event, is enabled. In addition, when the state transitions to inactive, the function-call subsystem initiated by that event is disabled. If the function-call subsystem is configured to reset states on being enabled or outputs on being disabled, such actions will occur. In this example, the subsystem resets its states and outputs upon being enabled and disabled, respectively.
open_system ('sl_subsys_fcncall9')
close_system('sl_subsys_fcncall9')
Interpreting Outputs of Function-Call Subsystems
1) The return value of the function call is the direct connection from the output of a function-call subsystem to its function-call initiator. For example, the Stateflow chart Chart1
below is a function-call initiator that executes the function d1=f1()
. After invoking f1
, the chart uses the return-value d1
computed by f1
within the same time-step.
2) In the second example, the execution of the Unit Delay block is not triggered by Chart2
. Therefore, during the execution of Chart2
, the signal d2
maintains its value from the previous time step at which the Unit Delay was invoked.
open_system ('sl_subsys_fcncall10')
close_system('sl_subsys_fcncall10')
Branching of Function-Call Signals
This Stateflow chart initiates a periodic function-call signal with a period of 1 during the time interval when its input signal u
is 1. For every function-call invocation, the subsystems execute in the order f
followed by h
followed by g
. This execution order is a result of the order specified on the function-call split blocks, where the port annotated with a dot executes first.
Exporting this model to releases earlier than R2015b results in an error because the signal b
is treated as a data dependency violation.
open_system ('sl_subsys_fcncall11')
This Stateflow Chart initiates a periodic function-call signal with a period of 1 during the time interval when its input signal u
is 1.
For each function-call invocation, the subsystem f1
executes before the subsystem g1
. This execution order is a result of the order specified on the function-call split block, where the port annotated with a dot executes first.
Exporting this model to releases earlier than R2015b results in an error because the signal b
is treated as a data dependency violation when the Latch input for feedback signals of function-call subsystem outputs parameter on the Inport block of subsystem f1
is cleared.
close_system('sl_subsys_fcncall11')
Illegal Function-Call Subsystems
This list identifies illegal function-call subsystems listed. The fixes are explained in the corresponding model subsystem.
open_system('s_Function_call_subsystems')
Ambiguous execution order error
Data dependency violation involving block driven by the function-call initiator
Data dependency violation involving block between two function-call subsystems
Ambiguous execution order error due to feedback of modified function-call output
Ambiguous execution order error due to feedback of modified function-call output between two subsystems
Data dependency violation involving a merge block and a Stateflow chart
Data dependency violation involving atomic subsystem and gain block
Function-call subsystem cycle data dependency violation
Indirect data dependency violation
Nested data dependency violation
Function-call subsystems incorrectly specify periodic execution
Function-call subsystems inputs computed within called context
Data dependency violation involving branched function-call signal and block connecting function-call subsystems
close_system('s_Function_call_subsystems',0)
If Action and Switch Case Action Subsystems
If action subsystems execute at each time step when a logical condition is true. Switch case action subsystems execute when a signal has one of a specified set of values.
For more information, see If Action Subsystem and Switch Case Action Subsystem.
These examples show how to use If Action and Switch Case Action subsystems.
open_system('sl_subsys_semantics') open_system('sl_subsys_semantics/If Action and Switch Case Action subsystems')
close_system('sl_subsys_semantics/If Action and Switch Case Action subsystems')
Triggered Subsystems
Triggered subsystems enable you to implement software triggering, hardware triggering or a combination of the two. You can add the Triggered Subsystem block from the Simulink Library Browser. Alternatively, you can create this subsystem by placing the Trigger block inside a Subsystem block.
For more information, see Triggered Subsystem.
These examples show how to use triggered subsystems.
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/Triggered subsystems')
Software triggering is defined in this code:
if (trigger_signal_edge_detected) {
out(t) = f(in(t));
}
Hardware triggering is defined in this code:
if (trigger_signal_edge_detected) {
out(t) = f(in(t-h)); // h == last step size
}
Each input port of a triggered subsystem configures whether or not the input should be latched. A latched input provides the hardware triggering semantics for that input port. The software marks a latched input port with the symbol <L>
.
close_system('sl_subsys_semantics/Triggered subsystems')
Enabled Subsystems
Enabled subsystems let you create conditionally executed subsystems that are only executed when the enabling signal is greater than zero. Enabled subsystems give you control over the initial value of the output signals and whether or not to reset states each time the subsystem is enabled.
You can add the Enabled Subsystem block from the Simulink Library Browser. Alternatively, you can create this subsystem by placing the Enable block inside a Subsystem block.
For more information, see Enabled Subsystem.
The following examples show how to use enabled subsystems.
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/Enabled subsystems')
close_system('sl_subsys_semantics/Enabled subsystems')
Enabled and Triggered Subsystem
These subsystems below illustrate the option for states and outport resetting. The enabled and triggered subsystem executes when both the enable and trigger conditions occur.
You can add the Enabled and Triggered Subsystem block from the Simulink Library Browser. Alternatively, you can create this subsystem by placing both the Enable block and the Trigger block inside a Subsystem block.
For more information, see Enabled and Triggered Subsystem.
This example shows how to use enabled and triggered subsystems.
open_system('sl_subsys_semantics') open_system('sl_subsys_enabtrig1.slx')
close_system('sl_subsys_enabtrig1.slx')
Resettable Subsystems
Resettable subsystems let you reset the states of blocks within the subsystem based on the reset signal. You can add the Resettable Subsystem block from the Simulink Library Browser.
For more information, see Resettable Subsystem.
These examples show how to use resettable subsystems.
open_system('sl_subsys_semantics') open_system('sl_subsys_semantics/Resettable subsystems')
close_system('sl_subsys_semantics/Resettable subsystems')
For Each Subsystem
The for each subsystem repeats execution during a simulation time step on each element or subarray of an input signal or mask parameter array. You can add the For Each Subsystem block from the Simulink Library Browser. Alternatively, you can create this block by placing a For Each block inside a Subsystem block. A for each subsystem repeats the algorithm on individual elements or subarrays of an input signal. A for each subsystem keeps block states separate for each element or subarray that the subsystem processes.
For more information, see For Each Subsystem.
These examples show how to use for each subsystems.
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/For Each subsystems')
close_system('sl_subsys_semantics/For Each subsystems')
While Iterator Subsystem
The while iterator subsystem repeats execution during a simulation time step while a logical condition is true
. You can add the While Iterator Subsystem block from the Simulink Library Browser. Alternatively, you can create this subsystem by placing a While Iterator block inside a Subsystem block. A while iterator subsystem runs multiple iterations on each model time step. The number of iterations is controlled by the while iterator condition.
The while iterator subsystem is similar to a function-call subsystem in that it can run for any number of iterations on a given time step.
The while iterator subsystem differs from a function-call subsystem in that it contains no separate initiator, such as a Stateflow Chart. In addition, the while iterator subsystem has access to the current iteration number optionally produced by the While Iterator block.
For more information, see While Iterator Subsystem.
These examples show how to use while iterator subsystems.
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/While Iterator subsystems')
close_system('sl_subsys_semantics/While Iterator subsystems')
For Iterator Subsystem
The for iterator subsystem repeats execution during a simulation time step for a specified number of iterations. You can add the For Iterator Subsystem block from the Simulink Library Browser. Alternatively, you can create this subsystem by placing a For Iterator block inside a Subsystem block. A for iterator subsystem runs a fixed number of iterations on each model time step. The number of iterations can be an external input to the for subsystem or specified internally on the For Iterator block.
A for iterator subsystem is very similar to a while iterator subsystem with the restriction that the number of iterations on any given time step is fixed.
For more information, see For Iterator Subsystem.
These following examples show how to use for iterator subsystems.
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/For Iterator subsystems')
close_system('sl_subsys_semantics/For Iterator subsystems')