Block Replacements for Unsupported Blocks
This example shows how to use Simulink® Design Verifier™ functions to replace unsupported blocks and how to customize test vector generation for specific requirements.
Model with an Unsupported Block
The example model includes a Switch block whose output is controlled by a Sqrt block. For each switch position, the output of the model is calculated by a 1-D Lookup Table block. For this model, the example concentrates on generating test cases that satisfy the following:
1. Achieve 100% lookup table coverage.
2. Test vectors demonstrate each Switch block position when the values of its first and third input ports differ.
open_system('sldvdemo_sqrt_blockrep');
Checking Model Compatibility
Since the sqrt
function is not supported, this model is partially compatible with Simulink Design Verifier.
sldvcompat('sldvdemo_sqrt_blockrep');
20-Jul-2024 19:46:10 Checking compatibility for test generation: model 'sldvdemo_sqrt_blockrep' Compiling model...done Building model representation...done 20-Jul-2024 19:46:13 'sldvdemo_sqrt_blockrep' is compatible for test generation with Simulink Design Verifier.
Creating a Custom Block Replacement Rule to Work Around the Incompatibility
This model can be analyzed for test generation by automatically stubbing the unsupported Sqrt block. However, test cases cannot be generated for the Switch block positions because Simulink Design Verifier does not understand the Sqrt block and the output of this block is effecting the Switch block. Since you want test cases for the Switch block, you need to replace the Sqrt block with a supported block that is functionally equivalent. The library block sldvdemo_custom_blockreplib
shown below constrains the input signal to the range [0 10000]
and approximates the sqrt
function by using a 1-D Lookup Table block.
The table data was calculated to match the values of sqrt
, with a maximum error of 0.2
in the range [0 10000]
. Refer to the mask initialization pane of the block Sqrt_Approx
in the library sldvdemo_custom_blockreplib
for the values of the lookup table data.
The replacement rule is in defined the MATLAB-file sldvdemo_custom_blkrep_rule_sqrt.m
. Since the replacement block sldvdemo_custom_blockreplib
for the Sqrt block is only valid for double or single types, this rule ensures that these conditions are satisfied before allowing a block replacement.
function rule = sldvdemo_custom_blkrep_rule_sqrt
rule = SldvBlockReplacement.blockreprule; rule.fileName = mfilename;
rule.blockType = 'Sqrt';
rule.replacementPath = sprintf('sldvdemo_custom_blockreplib/Sqrt_Approx');
rule.replacementMode = 'Normal';
parameter.OutMin = '$original.OutMin$'; parameter.OutMax = '$original.OutMax$'; parameter.OutDataTypeStr = '$original.OutDataTypeStr$'; rule.parameterMap = parameter;
rule.isReplaceableCallBack = @replacementTestFunction;
end
function out = replacementTestFunction(blockH)
out = false; acceptedOutDataTypeStr = {'double','single',... 'Inherit: Inherit via back propagation',... 'Inherit: Same as input'}; I = strmatch(get_param(blockH,'OutDataTypeStr'),acceptedOutDataTypeStr,'exact'); if ~isempty(I)
portDataTypes = get_param(blockH,'CompiledPortDataTypes');
out = any(strcmp(portDataTypes.Inport,{'double','single'})) && ... strcmp(portDataTypes.Inport,portDataTypes.Outport); end end
open_system('sldvdemo_custom_blockreplib'); open_system('sldvdemo_custom_blockreplib/Sqrt_Approx/1-D Lookup Table');
Configuring Simulink® Design Verifier™ Options for Block Replacement
You will run Simulink Design Verifier in test generation mode with block replacements enabled. In order to generate test cases for positions of Switch block, you must use the custom replacement rule sldvdemo_custom_blkrep_rule_sqrt.m
.
Since you are also interested in lookup table coverage, you need the built-in block replacement blkrep_rule_lookup_normal.m
, which inserts test objectives for each interval and breakpoint value for a 1-D Lookup Table block. Moreover, you need the built-in rule blkrep_rule_switch_normal.m
, which requires that each switch position be exercised when the values of the first and third input ports differ.
The analysis will run for a maximum of 30 seconds and produce a harness model. Report generation is also enabled. Other Simulink Design Verifier options are set to their default values.
opts = sldvoptions; opts.Mode = 'TestGeneration'; opts.MaxProcessTime = 80; opts.BlockReplacement = 'on'; opts.BlockReplacementRulesList = ['sldvdemo_custom_blkrep_rule_sqrt.m,' ... 'blkrep_rule_lookup_normal.m,'... 'blkrep_rule_switch_normal.m']; opts.SaveHarnessModel = 'on'; opts.ModelReferenceHarness = 'on'; opts.SaveReport = 'on';
Executing Test Generation with Block Replacements
The sldvrun
function analyzes the model using the settings defined in a sldvoptions
object opts
. The generated report includes a chapter summarizing block replacements performed on the model. Set the warning off from Coverage Tool:
warning('off','Simulink:blocks:WarnTuningWhenCoverage') [status,fileNames] = sldvrun('sldvdemo_sqrt_blockrep', opts, true);
Executing Tests in the Harness Model
Enable the lookup table coverage metric and then run the test cases using the harness model. You can also execute the suite of tests by clicking the "Run all" button on the Signal Editor dialog box after enabling lookup table coverage from the Configuration Parameters dialog. In the Coverage tab, select Enable coverage analysis and then select Coverage metrics > Other metrics > Lookup table.
The coverage report shown below indicates that you can reach 100% lookup table coverage with the test vectors that Simulink Design Verifier generated.
[harnessModelPath,harnessModel] = fileparts(fileNames.HarnessModel); set_param(harnessModel,'covMetricSettings','dcmte'); sldvdemo_playall(harnessModel);
Clean Up
To complete the example, close all models and remove the files that Simulink Design Verifier generated.
close_system('sldvdemo_custom_blockreplib'); close_system(fileNames.HarnessModel,0); close_system(fileNames.BlockReplacementModel,0); close_system('sldvdemo_sqrt_blockrep',0); delete(fileNames.HarnessModel); delete(fileNames.BlockReplacementModel); delete(fileNames.DataFile);