主要内容

不受支持的模块的模块替换

此示例说明如何使用 Simulink® Design Verifier™ 函数替换不受支持的模块,以及如何根据特定需求自定义测试向量生成。

具有不受支持的模块的模型

示例模型包括一个 Switch 模块,其输出由 Sqrt 模块控制。对于每个开关位置,模型的输出由 1-D Lookup Table 模块计算。对于此模型,该示例集中于生成满足以下条件的测试用例:

1.实现 100% 的查找表覆盖率。

2.测试向量演示当 Switch 模块的第一个输入端口与第三个输入端口的值不同时 Switch 模块的每个位置。

open_system('sldvdemo_sqrt_blockrep');

检查模型兼容性

由于不支持 sqrt 函数,所以此模型与 Simulink Design Verifier 部分兼容。

sldvcompat('sldvdemo_sqrt_blockrep');
12-Aug-2025 18:05:31
Checking compatibility for test generation: model 'sldvdemo_sqrt_blockrep'
Compiling model...done
Building model representation...done

12-Aug-2025 18:05:36

'sldvdemo_sqrt_blockrep' is compatible for test generation with Simulink Design Verifier.

创建自定义模块替换规则以解决不兼容问题

可以通过自动对不受支持的 Sqrt 模块进行插桩来分析此模型以生成测试。然而,由于 Simulink Design Verifier 无法理解 Sqrt 模块,并且该模块的输出会影响 Switch 模块,因此无法针对 Switch 模块的位置生成测试用例。由于您需要 Switch 模块的测试用例,因此需要将 Sqrt 模块替换为功能等效且受支持的模块。如下所示的库模块 sldvdemo_custom_blockreplib 将输入信号限制在 [0 10000] 范围内,并使用 1-D Lookup Table 模块来逼近 sqrt 函数。

计算的表数据与 sqrt 的值相匹配,在 [0 10000] 范围内最大误差为 0.2。有关查找表数据的值,请参阅库 sldvdemo_custom_blockreplibSqrt_Approx 模块的封装初始化窗格。

替换规则在 MATLAB 文件 sldvdemo_custom_blkrep_rule_sqrt.m 中定义。由于 Sqrt 模块的替换模块 sldvdemo_custom_blockreplib 仅对双精度或单精度类型有效,所以此规则可确保在允许模块替换之前满足这些条件。

   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');

配置 Simulink® Design Verifier™ 选项以进行模块替换

您将在启用了模块替换的测试生成模式下运行 Simulink Design Verifier。为了对 Switch 模块的位置生成测试用例,您必须使用自定义替换规则 sldvdemo_custom_blkrep_rule_sqrt.m

由于您还要满足查找表覆盖率,因此需要使用内置模块替换规则 blkrep_rule_lookup_normal.m,该规则会为 1-D Lookup Table 模块的每个区间和断点值插入测试目标。此外,您还需要使用内置规则 blkrep_rule_switch_normal.m,该规则要求在第一个输入端口与第三个输入端口的值不同时测试每个开关位置。

分析的最长运行时间为 30 秒,并会生成一个框架模型。此外,还会启用报告生成。其他 Simulink Design Verifier 选项设置为其默认值。

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';

使用模块替换执行测试生成

sldvrun 函数使用 sldvoptions 对象 opts 中定义的设置来分析模型。生成的报告中有一个章节总结对模型执行的模块替换。从覆盖率工具中关闭警告:

warning('off','Simulink:blocks:WarnTuningWhenCoverage')
[status,fileNames] = sldvrun('sldvdemo_sqrt_blockrep', opts, true);

在框架模型中执行测试

启用查找表覆盖率度量,然后使用框架模型运行测试用例。您还可以先在“配置参数”对话框中启用查找表覆盖率,然后点击“信号编辑器”对话框中的“全部运行”按钮来执行测试套件。在覆盖率选项卡中,选择启用覆盖率分析,然后依次选择覆盖率度量 > 其他度量 > 查找表

下面显示的覆盖率报告表明,您可以使用 Simulink Design Verifier 生成的测试向量实现 100% 的查找表覆盖率。

[harnessModelPath,harnessModel] = fileparts(fileNames.HarnessModel);
set_param(harnessModel,'covMetricSettings','dcmte');
sldvdemo_playall(harnessModel);

清理

要完成示例,请关闭所有模型并删除 Simulink Design Verifier 生成的文件。

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);