主要内容

本页采用了机器翻译。点击此处可查看英文原文。

通过编程方式检测和替换子系统克隆

克隆是将具有相同模块类型和连接的模型模式。您可以通过从子系统克隆创建库块,并将克隆替换为指向这些库块的链接来重构您的模型,这样您就可以重用组件。有关克隆的更多信息,请参阅使用克隆检测启用组件重用

在模型提交过程中以编程方式检查克隆,有助于在模型部署到主产品分支之前,发现重用子系统的机会。更新模型时,您可以同时使用 克隆件检测器 应用和克隆检测器 API。当您使用克隆检测器 API 时,检测到的克隆会出现在 Simulink® 编辑器中。

本示例展示了如何使用克隆检测 API 来识别和替换单个模型中的克隆,方法是创建一个包含子系统模块的库文件,并将克隆替换为指向库文件中模块的链接。

在这个示例中,您将学习如何使用:

通过编程方式识别模型中的克隆体

  1. 打开模型 ex_detect_clones_B

    openExample('ex_detect_clones_B');

    将模型保存到当前工作目录。

  2. 要查找子系统克隆,请使用函数 Simulink.CloneDetection.findClones()。该函数创建一个名为 cloneResults 的对象。

     cloneResults = Simulink.CloneDetection.findClones('ex_detect_clones_B')
    
    cloneResults = 
      Results with properties:
            Clones: [1×1 struct]
      ExceptionLog: ''

    cloneResults 对象具有 Clones,这是一个包含两个字段 SummaryCloneGroups 的结构体。

     cloneResults.Clones
    
    ans = 
      struct with fields:
            Summary: [1×1 struct]
        CloneGroups: [1×2 struct]
    
  3. 查看 Summary 字段。

     cloneResults.Clones.Summary
    
    ans = 
      struct with fields:
                     CloneGroups: 2
                   SimilarClones: 5
                     ExactClones: 0
                          Clones: 5
        PotentialReusePercentage: [1×1 struct]
    

    在这个示例中,模型有两个具有匹配子系统模式的 CloneGroups,五个 SimilarClones,零个 ExactClones,以及五个子系统 Clones

  4. 查看 CloneGroups 字段。

     cloneResults.Clones.CloneGroups
    
    ans = 
      1×2 struct array with fields:
        Name
        Summary
        CloneList
    

    本例中的模型返回一个包含两个 CloneGroups 的数组。每个数组都包含 NameSummaryCloneList

  5. 查看第一个克隆组的详细信息。

     cloneResults.Clones.CloneGroups(1)
    
    ans = 
      struct with fields:
             Name: 'Similar Clone Group 1'
          Summary: [1×1 struct]
        CloneList: {3×1 cell}
    
  6. 查看 Summary

     cloneResults.Clones.CloneGroups(1).Summary
    
    ans = 
      struct with fields:
        ParameterDifferences: [1×1 struct]
                      Clones: 3
              BlocksPerClone: 8
                   CloneType: 'Similar'
             BlockDifference: 1
    
  7. 查看第一个 CloneGroupCloneList

     cloneResults.Clones.CloneGroups(1).CloneList
    
    ans =
      3×1 cell array
        {'ex_detect_clones_B/Subsystem1'}
        {'ex_detect_clones_B/Subsystem2'}
        {'ex_detect_clones_B/Subsystem3'}
    

    同样地,您可以使用上述步骤找到其他 CloneGroups 的结果。

通过编程方式替换模型中的克隆体

  1. 要替换模型中的克隆体,请使用函数 Simulink.CloneDetection.replaceClones()。此函数使用来自 findClones 函数的 cloneResults 对象。

     cloneReplacementResults = Simulink.CloneDetection.replaceClones(cloneResults)
    
    cloneReplacementResults = 
      ReplacementResults with properties:
        ReplacedClones: [1×5 struct]
        ExcludedClones: {}
    

    cloneReplacementResults 对象包含两个属性,ReplacedClonesExcludedClones

  2. 查看 ReplacedClones 属性的内容。

    cloneReplacementResults.ReplacedClones
    
    ans = 
      1×5 struct array with fields:
        Name
        ReferenceSubsystem
    

    1×5 数组表示该函数替换了模型中的五个子系统克隆。

  3. 查看已替换子系统克隆的列表。

     struct2table(cloneReplacementResults.ReplacedClones)
    
    ans =
      5×2 table
                       Name                         ReferenceSubsystem      
        ___________________________________    _____________________________
        {'ex_detect_clones_B/Subsystem1'}    {'newLibraryFile/Subsystem1'}
        {'ex_detect_clones_B/Subsystem2'}    {'newLibraryFile/Subsystem1'}
        {'ex_detect_clones_B/Subsystem3'}    {'newLibraryFile/Subsystem1'}
        {'ex_detect_clones_B/SS3'       }    {'newLibraryFile/SS1'       }
        {'ex_detect_clones_B/SS4'       }    {'newLibraryFile/SS1'       }
    

利用库引用块识别克隆

  1. 将模型和库文件保存到当前工作目录。

    ex_detect_clones_E
    clones_library
  2. 使用 Simulink.CloneDetection.Settings() 类创建一个对象,该对象指定在模型中查找克隆的某些条件。

     cloneDetectionSettings = Simulink.CloneDetection.Settings()
    
    cloneDetectionSettings = 
    
      Settings with properties:                            
                                IgnoreSignalName: 0
                             IgnoreBlockProperty: 0
                          ExcludeModelReferences: 0
                             ExcludeLibraryLinks: 0
                          ExcludeInactiveRegions: 0
                          SelectedSystemBoundary: ''
                         DetectClonesAcrossModel: 0
                  FindClonesRecursivelyInFolders: 1
                        ParamDifferenceThreshold: 50
        ReplaceExactClonesWithSubsystemReference: 0
                                       Libraries: {}
                                         Folders: {}
  3. 设置 ParamDifferenceThreshold 参数。此参数指定子系统必须存在多少差异才能被视为克隆。

     cloneDetectionSettings.ParamDifferenceThreshold = 0
    
    cloneDetectionSettings = 
    
      Settings with properties:                            
                                IgnoreSignalName: 0
                             IgnoreBlockProperty: 0
                          ExcludeModelReferences: 0
                             ExcludeLibraryLinks: 0
                          ExcludeInactiveRegions: 0
                          SelectedSystemBoundary: ''
                         DetectClonesAcrossModel: 0
                  FindClonesRecursivelyInFolders: 1
                        ParamDifferenceThreshold: 0
        ReplaceExactClonesWithSubsystemReference: 0
                                       Libraries: {}
                                         Folders: {}

    值为 0 表示子系统必须完全相同。

  4. 添加一个参考库文件,用于匹配 cloneDetectionSettings 对象中的克隆模式。在这个示例中,SSL1SSL2 是库 clones_library 中的子系统模式。

    cloneDetectionSettings = cloneDetectionSettings.addLibraries('clones_library')
    
    cloneDetectionSettings = 
    
      Settings with properties:                            
                                IgnoreSignalName: 1
                             IgnoreBlockProperty: 0
                          ExcludeModelReferences: 0
                             ExcludeLibraryLinks: 0
                          ExcludeInactiveRegions: 0
                          SelectedSystemBoundary: ''
                         DetectClonesAcrossModel: 0
                  FindClonesRecursivelyInFolders: 1
                        ParamDifferenceThreshold: 50
        ReplaceExactClonesWithSubsystemReference: 0
                                       Libraries: {'C:\Users\Examples\clones_library.slx'}
                                         Folders: {}
  5. 要查找克隆,请使用模型名称和 cloneDetectionSettings 对象执行函数 Simulink.CloneDetection.findClones()

     cloneResults = Simulink.CloneDetection.findClones('ex_detect_clones_E', cloneDetectionSettings)
    
    cloneResults = 
      Results with properties:
        Clones: [1×1 struct]
    
     cloneResults.Clones.Summary
    
    ans = 
      struct with fields:
                     CloneGroups: 2
                   SimilarClones: 5
                     ExactClones: 0
                          Clones: 5
        PotentialReusePercentage: [1×1 struct]
    

    在这个示例中,该模型有两个 CloneGroups,五个 SimilarClones,零个 ExactClones,以及五个子系统 Clones

  6. 查看第一个 CloneGroup 的详细信息。

     cloneResults.Clones.CloneGroups(1)
    
    ans = 
      struct with fields:
             Name: 'clones_library/SSL1'
          Summary: [1×1 struct]
        CloneList: {3×1 cell}
    

用条件替换克隆

  1. 1.要为 replaceClones 函数指定条件,请使用 Simulink.CloneDetection.ReplacementConfig() 类创建一个句柄:

     cloneReplacementConfig = Simulink.CloneDetection.ReplacementConfig()
    
    cloneReplacementConfig = 
      ReplacementConfig with properties:
        LibraryNameToAddSubsystemsTo: 'newLibraryFile'
                       IgnoredClones: {}
    
  2. 将子系统添加到 IgnoredClones 列表中。在这个示例中,忽略 Subsystem1,以避免将其替换为克隆体。

    cloneReplacementConfig.addCloneToIgnoreList('ex_detect_clones_E/Subsystem1')
    
    ans = 
      ReplacementConfig with properties:
        LibraryNameToAddSubsystemsTo: 'newLibraryFile'
                       IgnoredClones: {'ex_detect_clones_E/Subsystem1'}
    
  3. 要替换克隆,请使用 replaceClones 函数,并将 cloneResultscloneReplacementConfig 作为输入参量。

    cloneReplacementResults = Simulink.CloneDetection.replaceClones(cloneResults, cloneReplacementConfig)
    
    cloneReplacementResults = 
      ReplacementResults with properties:
        ReplacedClones: [1×4 struct]
        ExcludedClones: [1×1 struct]
    
  4. 查看 ReplacedClones 属性。

    struct2table(cloneReplacementResults.ReplacedClones)
    
    ans =
      4×2 table
                       Name                    ReferenceSubsystem
        ___________________________________    __________________
        {'ex_detect_clones_E/SS3'       }     {'clones_library/SSL1'} 
        {'ex_detect_clones_E/SS4'       }     {'clones_library/SSL1'} 
        {'ex_detect_clones_E/Subsystem1'}     {'clones_library/SSL2'} 
        {'ex_detect_clones_E/Subsystem2'}     {'clones_library/SSL2'} 
    

    参考库中的 SSL1SSL2 参考 Subsystem 模块替换了模型中的子系统克隆。

  5. 查看 ExcludedClones 属性。

    struct2table(cloneReplacementResults.ExcludedClones)
    
    ans =
      1×2 table
                       Name                    ReferenceSubsystem
        ___________________________________    __________________
        {'ex_detect_clones_E/Subsystem1'}     {'unselected'} 
    

检查模型的等效性

您可以使用 Simulink.CloneDetection.checkEquivalency() 函数检查更新后的模型是否与原始模型等效。该函数使用 Simulink Test 管理器将已保存的原始模型的仿真结果与更新后的模型进行比较,并将结果保存在 checkEquiResults 句柄中。

 checkEquiResults = Simulink.CloneDetection.checkEquivalency(cloneReplacementResults)
[21-Dec-2020 16:35:13] Running simulations...
[21-Dec-2020 16:35:32] Completed 1 of 2 simulation runs
[21-Dec-2020 16:35:33] Completed 2 of 2 simulation runs

checkEquiResults = 
  EquivalencyCheckResults with properties:
    List: [1×1 struct]

查看等效性检查结果。

 checkEquiResults.List
ans = 
  struct with fields:
    IsEquivalencyCheckPassed: 1
               OriginalModel: 'm2m_ex_detect_clones_E/snapshot_2020_12_21_16_35_06_ex_detect_clones_E.slx'
                UpdatedModel: 'ex_detect_clones_E.slx'

属性 IsEquivalencyCheckPassed 为 1,这表明这些模型是等价的。OriginalModelUpdatedModel 属性显示了函数检查的模型。

另请参阅

主题