Main Content

Filter Coverage Results Using a Script

This example shows how to programmatically filter objects and outcomes from coverage results.

Open the Model and Enable Coverage Analysis

First, load the model into memory.

modelName = 'slvnvdemo_covfilt';
load_system(modelName);

Configure the coverage settings for the model by using a Simulink.SimulationInput object.

simIn = Simulink.SimulationInput(modelName);
simIn = simIn.setModelParameter('CovEnable','on');
simIn = simIn.setModelParameter('CovMetricStructuralLevel','MCDC');
simIn = simIn.setModelParameter('StopTime','20');
simIn = simIn.setModelParameter('CovSaveSingleToWorkspaceVar','on');
simIn = simIn.setModelParameter('CovSaveName','covData');

Simulate the model using the SimulationInput object as the input.

simOut = sim(simIn);

View Decision Coverage Results

View the coverage results before applying a filter. You can access the decision coverage results using decisioninfo.

saturationInitial = decisioninfo(covData,'slvnvdemo_covfilt/Saturation');
percentSaturationCov = 100 * saturationInitial(1)/saturationInitial(2)
percentSaturationCov =

    50

The Saturation block has 50% decision coverage. If you do not intend for this block to be satisfied, you can filter a missing objective outcome so that it is no longer reported as missing coverage. First, you need a selector for the unsatisfied objective outcome that you want to filter.

Create a Selector

You can directly create a selector using the appropriate constructor. In this case, you would use slcoverage.MetricSelector.

Because the objective being justified is a decision outcome, the first input to the metric selector constructor is slcoverage.MetricSelectorType.DecisionOutcome. The second input is the block handle. The last two are the index of the objective to justify and the index of the outcome of that objective, respectively. Because the input > lower limit decision objective is the first objective for the Saturation block, its objective index is 1. Because the false outcome of this objective is the first outcome, its outcome index is also 1.

metricSel = slcoverage.MetricSelector(...
                  slcoverage.MetricSelectorType.DecisionOutcome,...
                  'slvnvdemo_covfilt/Saturation',1,1)
metricSel = 

  MetricSelector with properties:

     ObjectiveIndex: 1
       OutcomeIndex: 1
        Description: 'N/A'
               Type: DecisionOutcome
                 Id: 'slvnvdemo_covfilt:5'
    ConstructorCode: 'slcoverage.MetricSelector(slcoverage.MetricSelectorType.DecisionOutcome, 'slvnvdemo_covfilt:5', 1, 1)'

You can also use slcoverage.Selector.allSelectors to see the available selectors for the Saturation block.

saturationAllSels = ...
    slcoverage.Selector.allSelectors('slvnvdemo_covfilt/Saturation')
saturationAllSels = 

  1x6 heterogeneous Selector (BlockSelector, MetricSelector) array with properties:

    Description
    Type
    Id
    ConstructorCode

You can also see the objective and outcome indices by using the allSelectors method. Use the Description name-value pair to search for F.

falseSelectors = ...
    slcoverage.Selector.allSelectors('slvnvdemo_covfilt/Saturation',...
               'Description','F')
falseSelectors = 

  1x2 MetricSelector array with properties:

    ObjectiveIndex
    OutcomeIndex
    Description
    Type
    Id
    ConstructorCode

There are two false case selectors in the Saturation block. The first selector is F outcome of input > lower limit.

falseSel = falseSelectors(1)
falseSel = 

  MetricSelector with properties:

     ObjectiveIndex: 1
       OutcomeIndex: 1
        Description: 'F outcome of input >= lower limit in Saturate block "Saturation"'
               Type: DecisionOutcome
                 Id: 'slvnvdemo_covfilt:5'
    ConstructorCode: 'slcoverage.MetricSelector(slcoverage.MetricSelectorType.DecisionOutcome, 'slvnvdemo_covfilt:5', 1, 1)'

The falseSel selector is the same one we constructed manually using slcoverage.MetricSelector. The objective and outcome indices are properties of the resulting selector object.

Create a Justification Rule

Create a filter object by using slcoverage.Filter. You can set the filter file name and filter description by using the methods setFilterName and setFilterDescription, respectively.

filt = slcoverage.Filter;
setFilterName(filt,'slcoverage_filter');
setFilterDescription(filt,'Example Filter');

Create a filter rule by using slcoverage.FilterRule. The first input to FilterRule is the selector for the block or outcome you want to filter. This can be a selector you create, or one you retrieve from allSelectors.

The second input is the rationale for filtering the outcome or block. This is specified as a character array.

The third input is the filter mode you want to use. The two coverage filter modes are justify and exclude. Use justify mode to filter individual coverage objective outcomes such as F outcome of input > lower limit. Use exclude mode to filter entire model elements or blocks, which means that the block and its descendants, if applicable, are ignored. In this example, use justify mode to specify that you want to filter a specific outcome.

rule = slcoverage.FilterRule(...
    metricSel,'rate > 0',slcoverage.FilterMode.Justify);

Add the rule to the filter using addRule.

filt.addRule(rule);

Save the filter to a filter file using the save method. Then apply the filter file to the cvdata object by assigning the filter property to the new filter file.

filt.save('covfilter');
covData.filter = 'covfilter';

Re-generate the coverage results for the Saturation block using the filtered cvdata object.

filteredSaturation = decisioninfo(covData,'slvnvdemo_covfilt/Saturation');
percentSaturationFilt = 100 * filteredSaturation(1)/filteredSaturation(2)
percentSaturationFilt =

    75

Decision coverage for the Saturation block is now 75%.

Justify an MCDC Objective in a Stateflow® Chart

You can apply the same workflow to justify a specific Stateflow action. In this example, we want to justify the tick MCDC objective that is part of the after(4, tick) transition.

First, get the Stateflow root object by using sfroot (Stateflow).

chartID = sfroot;

Get the 'after(4, tick)' transition ID by using the find (Stateflow) method. You can use find to search for transitions by using the '-isa' flag with 'Stateflow.Transition'. You can further specify the exact transition by using searching for the label string using additional inputs.

transitionID = chartID.find('-isa','Stateflow.Transition',...
                            'LabelString','after(4, tick)');

Get the selector for the MCDC objective outcome that we want to filter by using allSelectors. Pass the Simulink ID of the Stateflow transition as the first input. Because we want to justify a tick outcome, search for "tick" in the description.

sfSelectors = slcoverage.Selector.allSelectors(transitionID,...
                                  'Description','"tick"')
sfSelectors = 

  1x3 MetricSelector array with properties:

    ObjectiveIndex
    OutcomeIndex
    Description
    Type
    Id
    ConstructorCode

allSelectors returns three possible selectors. The transition we want to filter is the third selector returned.

sfSel = sfSelectors(3)
sfSel = 

  MetricSelector with properties:

     ObjectiveIndex: 1
       OutcomeIndex: 1
        Description: 'Condition 1, "tick" outcome of Transition trigger expression in Transition "after(4, tick)" from "Clipped" to "Full"'
               Type: MCDCOutcome
                 Id: 'slvnvdemo_covfilt:6:5'
    ConstructorCode: 'slcoverage.MetricSelector(slcoverage.MetricSelectorType.MCDCOutcome, 'slvnvdemo_covfilt:6:5', 1, 1)'

Create the rule, add it to the filter, and save it. The filter file is already applied to the cvdata object.

rule2 = slcoverage.FilterRule(sfSel,'tick never false');
filt.addRule(rule2);
filt.save('covfilter');

For more information about the Stateflow programmatic API, see Overview of the Stateflow API (Stateflow).

Exclude a Block Using Block Selector

You can filter a block using slcoverage.BlockSelector. In this case, we want to exclude the Switchable config subsystem, so we use the SubsystemAllContent selector type and the slcoverage.FilterMode.Exclude filter mode.

subsysSel = slcoverage.BlockSelector(...
                      slcoverage.BlockSelectorType.SubsystemAllContent,...
                      'slvnvdemo_covfilt/Switchable config');

Create the filter rule by passing the selector, rationale, and the exclude filter mode as inputs.

rule3 = slcoverage.FilterRule(subsysSel,...
                       'Unused configuration',...
                        slcoverage.FilterMode.Exclude);

Add the rule to the filter and save it.

filt.addRule(rule3);
filt.save('covfilter');

Finally, you can view the coverage report by using cvhtml. The Objects Filtered from Coverage Analysis section shows a summary of the filtered model objects and the rationales. The '-sRT=0' flag can be used to generate the coverage report but not open the report automatically.

cvhtml('filteredCovReport',covData,'-sRT=0');

See Also

| | | | | | |

Related Topics