Programmatically Resolve Unexpected Behavior in a Model with Model Slicer
In this example, you evaluate a Simulink® model, detect unexpected behavior, and use Model Slicer to programmatically isolate and resolve the unexpected behavior. When you plan to reuse your API commands and extend their use to other models, a programmatic approach is useful.
Be familiar with the behavior and purpose of Model Slicer and the functionality of the Model Slicer API. Highlight Functional Dependencies outlines how to use Model Slicer user interface to explore models. The slslicer, slsliceroptions, and slslicertrace function reference pages contain the Model Slicer API command help.
Find the Area of the Model Responsible for Unexpected Behavior
The sldvSliceCruiseControlHarness test harness model contains a cruise controller subsystem sldvSliceCruiseControl and a block, TestCases, containing a test case for this subsystem. You first simulate the model to execute the test case. You then evaluate the behavior of the model to find and isolate areas of the model responsible for unexpected behavior.
Open the sldvSliceCruiseControlHarness test harness for the cruise control model.
Note: The Assertion block is set to Stop simulation when assertion fails when the actual operation mode is not the same as the expected operation mode.
You receive an error during the ResumeWO test case.
The Assertion block halted simulation at 27 seconds, because the actual operation mode was not the same as the expected operation mode. Click OK to close this error message. In the Assertion block, disable Enable assertion.
Set the Active Group of the TestCases Signal Builder block to the test case containing the error and run the simulation again.
signalbuilder('sldvSliceCruiseControlHarness/TestCases', 'ACTIVEGROUP', 12) sim('sldvSliceCruiseControlHarness')
The Scope block in the model contains three signals:
- operation_mode - displays the actual operation mode of the subsystem.
- expected_mode - displays the expected operation mode of the subsystem that the test case provides.
- verify - displays a Boolean value comparing the operation mode and the expected mode.
The scope shows a disparity between the expected operation mode and the actual operation mode beginning at time 27. Now that you know the outport displaying the unexpected behavior and the time window containing the unexpected behavior, use Model Slicer to isolate and analyze the unexpected behavior.
Isolate the Area of the Model Responsible for Unexpected Behavior
Create a Model Slicer configuration object for the model using slslicer. The Command Window displays the slice properties for this Model Slicer configuration.
obj = slslicer('sldvSliceCruiseControlHarness')
obj = SLSlicer with properties: Configuration: [1x1 SLSlicerAPI.SLSlicerConfig] ActiveConfig: 1 DisplayedConfig:  StorageOptions: [1x1 struct] AnalysisOptions: [1x1 struct] SliceOptions: [1x1 struct] InlineOptions: [1x1 struct] Contents of active configuration: Name: 'untitled' Description: '' Color: [0 1 1] SignalPropagation: 'upstream' StartingPoint: [1x0 struct] ExclusionPoint: [1x0 struct] Constraint: [1x0 struct] SliceComponent: [1x0 struct] UseTimeWindow: 0 CoverageFile: '' UseDeadLogic: 0 DeadLogicFile: ''
Activate the slice highlighting mode of Model Slicer to compile the model and prepare it for dependency analysis.
Add the operation_mode outport block as a starting point and highlight it.
The area of the model upstream of the starting point and active during simulation is highlighted. Simulate the model within a restricted simulation time window (maximum 30 seconds) to highlight only the area of the model upstream of the starting point and active during the time window of interest.
Only the portion of the model upstream of the starting point and active during the simulation time window is highlighted.
You can further narrow the simulation time window by changing the start time to 20 seconds.
Create a sliced model sldvSliceCruiseControlHarness_sliced containing only the area of interest.
slicedModel = slice(obj,'sldvSliceCruiseControlHarness_sliced'); open_system('sldvSliceCruiseControlHarness_sliced')
The sliced model sldvSliceCruiseControlHarness_sliced now contains a simplified version of the source model sldvSliceCruiseControlHarness. The simplified standalone model contains only those parts of the model that are upstream of the specified starting point and active during the time window of interest.
Investigate the Sliced Model and Debug the Source Model
You can now debug the unexpected behavior in the simplified standalone model and then apply changes to the source model.
To enable editing the model again, terminate the model slicer mode.
Navigate to the area of the sliced model that contains the unexpected behavior.
The AND Logical Operator block in this subsystem has a truncated true constant attached to its second input port. This true constant indicates that the second input port is always true during the restricted time window for this sliced model, causing the cruise control system not to enter the "has canceled" state. Navigate to the equivalent AND Logical Operator block in the source system by using slslicertrace to view the blocks connected to the second input port.
h = slslicertrace('SOURCE', 'sldvSliceCruiseControlHarness_sliced/Model/CruiseControlMode/opMode/resumeCondition/hasCanceled/LogicOp1'); hilite_system(h)
The OR Logical Operator block in this subsystem is always true in the current configuration. Changing the OR Logical Operator block to an AND Logical Operator block rectifies this error.
Before making edits, create new copies of the cruise control model and the test harness model.
Update the model reference in the test harness to refer to the newly saved model.
Use the block path of the erroneous Logical Operator block to fix the error.
Simulate the test harness with the fixed model to confirm the corrected behavior.
The scope now shows that the expected operation mode is the same as the actual operation mode.
To complete the demo, save and close all models and remove the Model Slicer configuration object.
save_system('sldvSliceCruiseControl_fixed') save_system('sldvSliceCruiseControlHarness_fixed') close_system('sldvSliceCruiseControl_fixed') close_system('sldvSliceCruiseControlHarness_fixed') close_system('sldvSliceCruiseControlHarness_sliced') clear obj