Main Content

SIL 和 PIL 仿真

什么是 SIL 和 PIL 仿真?

通过 Embedded Coder®,您可以运行模型的软件在环 (SIL) 和处理器在环 (PIL) 仿真。这些仿真为顶层模型或模型的一部分生成源代码。SIL 仿真在开发计算机上编译并运行生成的代码。PIL 仿真在您的开发计算机上交叉编译源代码,然后在目标处理器或等效的指令集仿真器上下载并运行目标代码。

通过 SIL 和 PIL 仿真,您可以:

  • 测试您的模型和生成的代码在数值上是否相等。

  • 观察代码覆盖率。

  • 运行代码执行探查。

为什么使用 SIL 和 PIL

通过 SIL 和 PIL,您可以尽早测试和修复缺陷。例如,您可以在普通模式下对系统组件进行建模和测试。然后,您可以在运行编译的生成代码的 SIL 或 PIL 仿真中重用您的测试套件。要检查数值等效性,您可以比较普通仿真结果和 SIL 或 PIL 仿真结果。您不必离开 Simulink® 环境到另外一个基础架构上测试生成的代码。

下表说明了 SIL 和 PIL 的适用情形。

情形使用
通过重用为普通模式仿真开发的测试向量来验证生成(或现有)代码的数值输出,从而测试模型和生成代码之间的数值等效性。请参阅 SIL/PIL Manager Verification WorkflowTest Two Simulations for Equivalence (Simulink Test)SIL 和 PIL

为生成的代码收集度量:

SIL 和 PIL

(需要 IEC Certification Kit 许可证。)

根据 ISO 26262-6、IEC 61508-3、IEC 62304、EN 50128 和 EN 50657 功能安全标准定义的整个软件安全生命周期的要求,对生成的 C/C++ 代码执行验证和确认活动。有关 IEC Certification Kit 基于模型的设计工作流中 SIL 和 PIL 验证活动的详细信息,请参阅工件资源管理器中的嵌入式 C/C++ 应用程序的参考工作流 (certkitiec_ecoder_workflow.docx/pdf) 工件。

SIL 和 PIL

(需要 DO Qualification Kit 许可证。)

测试集成过程的输出,以满足 DO-178C 和 DO-333 安全标准中的相关目标。有关详细信息,请参阅工件资源管理器中的 Model-Based Design Workflow for DO-178C (qualkitdo_do178_workflow.pdf) 工件。

SIL 和 PIL
在没有目标硬件的情况下,获得一个方便的 PIL 替代方案。SIL

在具有目标硬件(例如评估板或指令集仿真器)的情况下,请执行以下操作:

  • 验证针对特定目标的代码(例如进行了代码替换优化)和现有代码的行为。请参阅什么是代码替换?What Is Code Replacement Customization?

  • 优化代码的执行速度和内存占用。在此表中,请参阅有关收集执行探查和堆栈探查度量的信息。

  • 调查编译器设置和优化的影响,例如,偏离 ANSI® C 溢出行为。

普通仿真方法不考虑硬件的限制和要求,例如有限的内存资源或针对特定目标优化后的代码的行为。


PIL

注意

SIL 和 PIL 仿真模式不是为了减少模型仿真时间而设计的。如果您要加快模型的仿真速度,请使用快速加速模式。有关详细信息,请参阅 What Is Acceleration?

SIL 和 PIL 仿真的工作原理

在 SIL 或 PIL 仿真中,代码是为顶层模型或模型的一部分生成的。对于 SIL,此代码针对您的开发计算机编译并在其上执行。对于 PIL,代码针对目标硬件进行交叉编译,并在目标处理器上运行。

通过通信信道,Simulink 在仿真的每个采样间隔内向您的计算机或目标处理器上的代码发送激励信号。

  • 对于顶层模型,Simulink 使用来自基础工作区或模型工作区的激励信号。

  • 如果您指定仅模型的一部分在 SIL 或 PIL 模式下进行仿真,则模型的一部分将保留在 Simulink 中,并且不会为模型的此保留部分生成代码。通常,您需要配置模型的此部分来为在硬件上执行的软件提供测试向量。模型的此部分可以表示算法的其他部分或算法运行的环境。

当您的计算机或目标处理器接收到来自 Simulink 的信号时,处理器执行 SIL 或 PIL 算法,执行时间为一个采样步长。SIL 或 PIL 算法通过通信信道将在此步长内计算的输出信号返回到 Simulink。仿真的一个采样周期完成后,Simulink 进入下一个采样间隔。此过程不断重复,仿真持续进行。SIL 和 PIL 仿真不以实时方式运行。在每个采样周期内,Simulink 和目标代码会交换 I/O 数据。

SIL 和 PIL 仿真的比较

SIL 或 PIL 仿真的类型SIL 仿真中会发生什么PIL 仿真中会发生什么

指定方式:

  • 顶层模型仿真模式

  • Model 模块的 Simulation mode 参数

  • 在开发计算机上测试生成的源代码的行为。仿真不测试针对目标硬件编译的代码,因为代码是针对开发计算机编译的(编译器和处理器架构与目标不同)。

  • 生成的生产代码作为独立进程在开发计算机上编译和执行,独立于 MATLAB® 进程。

  • 执行采用主机/主机和非实时方式。

  • 测试您打算在实际目标硬件或指令集仿真器上进行生产性部署的目标代码。

  • 在开发计算机上,生成了为目标交叉编译的生产代码。在目标处理器或指令集仿真器上下载并执行目标代码。

  • 执行采用主机/目标和非实时方式。

使用从子系统创建的 SIL 或 PIL 模块。
  • 仿真通过 S-Function 运行编译后的目标代码。S-Function 与作为独立应用程序在开发计算机上执行的目标代码进行通信。SIL 模块执行独立于 MATLAB 进程。

  • 执行采用主机/主机和非实时方式。

  • 仿真通过开发计算机上的 S-Function 运行交叉编译的目标代码。S-Function 与作为独立应用程序在目标处理器或指令集仿真器上执行的目标代码进行通信。

  • 执行采用主机/目标和非实时方式。

SIL 和 PIL 的代码接口

在您执行编译时(例如,为单个可部署组件执行顶层模型编译或右键点击子系统编译),生成独立代码。您可以编译独立代码并将其链接到独立可执行文件中,或将其与其他代码集成。有关独立代码接口的详细信息,请参阅为模型入口函数配置生成的 C 函数接口

当您为引用模型层次结构生成代码时,软件会为顶层模型生成独立可执行代码,并为每个引用模型生成名为模型引用目标的库模块。当代码执行时,独立可执行文件调用适用的模型引用目标来计算引用模型输出。有关详细信息,请参阅 Build Model Reference Targets

要将生成的代码与现有代码集成,请使用独立代码,因为独立代码接口是公开的。

注意

SIL 和 PIL 仿真不直接支持自定义代码接口。您可以将这些接口作为一个 S-Function 合并到 Simulink 中,例如,通过使用代码继承工具、S-Function Builder 或人工代码。然后,您可以使用 SIL 和 PIL 仿真来验证自定义代码。

下表提供了 SIL 和 PIL 仿真生成的接口。

SIL/PIL 仿真代码接口
顶层模型

SIL/PIL 仿真生成独立代码接口。如果代码存在,仿真将调用模型的独立代码。如果代码不存在,仿真将生成独立代码。

Model 模块

如果将代码接口模块参数设置为顶层模型,SIL/PIL 仿真将生成独立代码接口。仿真将调用模型的独立代码(如果存在)。否则,仿真将使用 slbuild('model') 命令生成独立代码。

如果将代码接口模块参数设置为模型引用,SIL/PIL 仿真将生成模型引用代码接口。仿真调用 Model 模块的模型引用目标(如果存在)。否则,仿真将使用 slbuild('model', 'ModelReferenceCoderTarget') 命令生成模型引用目标。

SIL 或 PIL 模块模块使用独立代码接口。

调度注意事项

项目信息
代数环

在 SIL 和 PIL 仿真中可能存在代数环,但在普通模式仿真中不存在:

  • 代码生成优化中的单一输出/更新函数可能引入代数环,因为该选项通过组合的输出和更新函数实现直接馈通。

    单一输出/更新函数尽量减少出现代数环不兼容(在“子系统参数”对话框和配置参数 > 模型引用窗格中)。尽量减少出现代数环允许代码生成将输出函数和更新函数的生成代码分开,从而消除代数环以避免直接馈通。

  • 如果您为虚拟子系统生成代码,代码生成会将该子系统视为原子子系统,并相应地生成代码。生成的代码可能更改模型的执行行为(例如,通过应用代数环),导致与仿真行为不一致。

    为了使模型的仿真行为和执行行为一致,请将虚拟子系统声明为原子子系统。

有关详细信息,请参阅:

反馈环中的导出函数

如果您的模型具有函数调用子系统,并且您导出了采用上下文相关输入(例如,反馈信号)的子系统,则使用生成的代码进行 SIL/PIL 仿真的结果和您的模型的普通模式仿真的结果可能有所不同。要使 SIL/PIL 仿真和普通模式仿真产生相同的结果,一种方法是在您的模型中使用 Function-Call Feedback Latch 模块。您可以使上下文相关输入变为与上下文无关。

如果您将上下文相关输入配置参数设置为警告,Embedded Coder 会产生一条警告,指出导出函数调用子系统的上下文相关输入。

有关详细信息,请参阅:

导入的数据和其他的生成代码

SIL 或 PIL 仿真不会修改从模型生成的代码。如果使用导入的数据,SIL 或 PIL 仿真会生成支持 SIL 或 PIL 目标应用程序编译和链接所需的其他代码。生成的其他代码对应于您在模型中指定的接口。

本节介绍:

  • 对于导入的数据,SIL 或 PIL 仿真什么时候定义存储,以及您什么时候必须定义存储。

  • SIL 或 PIL 仿真要为其生成其他代码的接口

SIL 或 PIL 仿真中的导入数据

在 SIL 和 PIL 仿真中,您可以使用信号、参数和数据存储,它们使用导入的数据定义来指定存储类。仿真会为与以下各项相关联的导入数据定义存储:

  • 位于组件根级的信号(在 I/O 边界上)。

  • 基础工作区或数据字典中的参数。对于模型工作区中的参数:

    • 顶层模型的 SIL/PIL 和 SIL/PIL 模块仿真定义存储。

    • Model 模块 SIL/PIL 仿真不定义存储。您必须定义存储并指定与 MATLAB 值匹配的初始值。

  • 全局数据存储。

SIL 和 PIL 仿真不会为其他导入的数据定义存储。例如,仿真不会为与以下项目相关联的导入的数据定义存储:

  • 内部信号(不在 I/O 边界上)。请注意,如果内部信号的数据位于通过使用指针导入的结构体中,则仿真会定义存储。

  • 局部数据存储。

在这些情况下,通过待测组件包含的自定义代码或通过 PIL rtw.pil.RtIOStreamApplicationFramework API 来定义存储。

另请参阅Tunable Parameters and SIL/PIL

生成其他生成代码的接口

下表说明 SIL 或 PIL 仿真为接口生成其他代码的场景。

情况详细信息
GetSet 自定义存储类

SIL 和 PIL 仿真支持 GetSet 自定义存储类。SIL/PIL 测试框架提供在仿真期间使用的 GetSet 函数的 C 定义。有关详细信息,请参阅 Access Data Through Functions with Storage Class GetSet

类型为 Other 的自定义存储类

要为类型设置为 Other 的自定义存储类启用 SIL 和 PIL 支持,请为自定义存储类创建一个自定义属性类,并将该自定义属性类与设置为 true 的布尔值属性SupportSILPIL 相关联。

classdef CSCOtherAttributes < Simulink.CustomStorageClassAttributes
  properties(PropertyType = 'logical scalar')
    SupportSILPIL = true;
  end
end

有关自定义属性的详细信息,请参阅Further Customize Generated Code by Writing TLC CodeFinely Control Data Representation by Writing TLC Code for a Storage Class

为了编译 SIL 或 PIL 应用程序接口,代码生成器调用相关联的自定义 TLC 文件中的 DataAccessClassAccess 函数来获取所需信息。代码生成器将提取的信息存储在编译文件夹的编译工件中。

对于未分组的自定义存储类:

  • 代码生成器使用请求参量值 definedeclarelayoutcontentsaddressset 调用 DataAccess

  • 如果符合以下条件之一,代码生成器将使用 DataAccess(record, "define", "", "") 返回的字符串在 SIL 或 PIL 应用程序中定义变量:

    • 信号或参数具有 Imported 数据作用域。

    • 模型使用模型引用代码接口。

    • 模型使用顶层模型代码接口,EnableDataOwnershipon,自定义存储类的 Owner 属性不为空并且不等于当前模型的名称

  • 如果符合以下条件,代码生成器将使用 DataAccess(record, "declare", "", "") 返回的字符串在 SIL 或 PIL 应用程序中声明变量:

    • 模型使用顶层模型代码接口。

    • 信号或参数使用 Exported 存储类。

    • EnableDataOwnershipoffEnableDataOwnershipon,并且自定义存储类的 Owner 属性为空或等于模型名称。

    • 代码打包配置为不在 model.hmodel.h 包含的头文件中声明变量

对于分组的自定义存储类:

  • 代码生成器使用 request 参量值 layoutaddressset 调用 DataAccess

  • 代码生成器使用 request 参量值 groupTypeDeclDefn 调用 ClassAccess

  • 如果符合以下条件之一,则您必须提供分组类型 (struct) 定义和分组变量的 extern 声明:

    • 信号或参数具有 Imported 数据作用域。

    • 模型使用模型引用代码接口。

    • 模型使用顶层模型代码接口,EnableDataOwnershipon,自定义存储类的 Owner 属性不为空并且不等于当前模型的名称

    通过使用 HeaderFile 属性或通过 model.h 文件包含的自定义代码,在与自定义存储类相关联的头文件中提供定义和声明。为了在 SIL 或 PIL 应用程序中定义变量,代码生成器使用由 ClassAccess(record, "groupTypeDeclDefn") 返回的字符串。

  • 静态初始化采用的 struct 元素的顺序可以不同于数据作用域为 Exported 时生成的顺序。当代码生成器查询 ClassAccess(record, "groupTypeDeclDefn") 时,它会用值 None 临时覆盖自定义存储类的数据初始化属性。

为了确定 SIL 或 PIL 应用程序是否可以通过地址访问代码中的变量,代码生成器使用 DataAccess(record, "layout", "", "") 返回的元素。为了在应用程序中创建在开发计算机和目标硬件之间传输输入或输出端口、可调参数或全局数据存储内存值的功能,代码生成器使用来自以下项的输出:

  • DataAccess(record, "address", idx, reim)(如果第一个返回的元素是 scalarvectorrow-matcol-mat)。

  • DataAccess(record, "contents", idx, reim)DataAccess(record, "set", idx, reim)(如果第一个返回的元素是 other)。

代码生成器假设对于 row-matcol-mat,矩阵都以行优先格式存储。该假设与模型其余部分的数组布局无关。代码生成器假设,如果自定义存储类实现的存储的数组布局不同于模型的其余部分,则与自定义存储文件相关联的 TLC 文件会执行必需的变换。

您可以构造与 Other 类型的自定义存储类相关联的自定义 TLC 文件,以在返回请求的代码片段之外执行其他函数。例如,直接写入自定义文件或调用 MATLAB 函数来更改基础工作区的状态。如果您不希望在调用 DataAccessClassAccess 时始终执行这些函数,请使用 LibIsAccessingCustomDataForSILPIL(record) TLC 函数将目标代码生成操作和用于构造 SIL 或 PIL 应用程序的代码片段请求分开。例如:

...
%case "contents"
  %if !LibIsAccessingCustomDataForSILPIL(record)
    %matlab functionWithSideEffects()
  %endif
%return LibDefaultCustomStorageContents(record, idx, reim)
...

另请参阅其他自定义存储类限制

AUTOSAR 运行时环境

您可以使用顶层模型和 Model 模块 SIL/PIL 和 SIL/PIL 模块仿真来执行 AUTOSAR 软件组件的基于模型的测试。该软件将为 AUTOSAR 软件组件生成的代码与特定于基本组件的 AUTOSAR 运行时环境 (RTE) 链接起来,以创建测试应用程序。此应用程序测试由 AUTOSAR 软件组件进行的 AUTOSAR API 调用。

对于包含引用模型的顶层 AUTOSAR 软件组件,您可以运行顶层模型或 Model 模块(代码接口设置为顶层)的 SIL 或 PIL 仿真。在仿真中,软件会执行以下操作:

  • 在编译引用模型之前,生成 AUTOSAR RTE 头文件。

  • 为引用模型编译提供 RTE 包含路径。

您也可以对顶层 AUTOSAR SWC 内的引用模型运行 Model 模块(代码接口设置为模型引用)的 SIL 或 PIL 仿真。在这种情况下,在您运行仿真之前,必须编译父组件来生成 RTE 头文件。如果不编译父组件,SIL 或 PIL 仿真将失败。

相关主题