Main Content

S-Function 和代码生成

您可以使用 S-Function 扩展 Simulink® 对仿真和代码生成的支持。例如,您可以使用它们:

  • 表示自定义算法

  • 将现有外部代码对接到 Simulink 模型和生成的代码中

  • 表示与硬件对接的设备驱动程序

  • 为嵌入式系统生成高度优化的代码

  • 在 Simulink 仿真过程中验证为子系统生成的代码

通过 S-Function 的应用程序编程接口 (API),您可以非常灵活地在 Simulink 环境中实现通用算法。如果您打算在模型中将 S-Function 用于代码生成,灵活度可能会有所不同。例如,需要生成代码的 S-Function 不能访问 MATLAB® 工作区。本主题介绍使用 S-Function 需要注意的条件。但是,利用本主题介绍的技巧,可为大多数使用生成代码的应用程序创建 S-Function。

虽然 S-Function 提供了通用且灵活的解决方案,可在模型中实现复杂的算法,但基础 API 会在内存和计算资源方面产生一定的开销。通常,额外增加的资源开销对实时快速原型系统来说是可以接受的。不过,通常情况下实时嵌入式应用程序中并没有额外的可用资源。通过使用代码生成器附带的目标语言编译器技术来内联 S-Function,可最大程度降低内存和计算要求。如果您为现有的外部代码生成 S-Function,可以考虑使用代码继承工具生成 S-Function 和相关的 TLC 文件。

本主题假设您已理解以下概念:

  • 2 级 S-Function

  • 目标语言编译器 (TLC) 脚本编写

  • 代码生成器如何生成和编译 C/C++ 代码

注释

此信息适用于代码生成器用户。即使您当前没有使用代码生成器,编写 S-Function 时也可以采用这些做法,尤其是在创建通用 S-Function 时。

S-Function 的类型

以下情形适合用 S-Function 来实现仿真和代码生成:

  1. “我不关心效率,我只想让我的算法能够自动在 Simulink 和代码生成器产品中工作。”

  2. “我想在 Simulink 和代码生成器产品中实现一种高度优化的算法,它看起来就像是一个内置模块,并且能生成高效的代码。”

  3. “我有很多人工代码需要集成。我希望高效地从 Simulink 和代码生成器产品中调用我的函数。”

上述情况分别对应于以下 MathWorks® 术语:

  1. 非内联 S-Function

  2. 内联 S-Function

  3. 为外部代码自动生成的 S-Function

非内联 S-Function

非内联 S-Function 是 C 或 C++ MEX S-Function,Simulink 引擎和生成的代码以相同的方式处理这种函数。一般情况下,您只需根据 S-Function API 实现一次算法即可。Simulink 引擎和生成的代码将在模型执行过程中调用 S-Function 例程(例如 mdlOutputs)。

非内联 S-Function 模块的每个实例都需要一些额外的内存和计算资源。但是,这种在模型和代码生成应用程序中嵌入算法的例程通常发生在工程的原型构建阶段,此时效率并不重要。牺牲效率所获得的好处是能够快速更改模型参数和结构。

编写非内联 S-Function 不涉及 TLC 编码。您在模型中内建一个 MEX S-Function 后,便可以直接按下 Ctrl+B 开始编译模型,而无需进行其他准备工作,从这个意义上讲,非内联 S-Function 是编译过程的默认情形。

生成联编文件时,关于非内联 S-Function 文件的名称和位置有一些限制。请参阅编写非内联 S-Function

内联 S-Function

要使 S-Function 能够在 Simulink 环境中工作,需要生成一些开销代码。当代码生成器从包含 S-Function(不含 sfunction.tlc 文件)的模型中生成代码时,会在生成的代码中嵌入一些开销代码。如果要优化您的实时代码并消除一些开销代码,必须内联(或嵌入)您的 S-Function。这涉及到编写一个 TLC (sfunction.tlc) 文件,以便从生成的代码中消除开销代码。目标语言编译器通过处理 sfunction.tlc 文件来定义如何在生成的代码中内联您的 S-Function 算法。

注意

不要将内联一词与 C++ 语言中的 inline 关键字混淆。内联的意思是:通过指定文本来代替对通用 S-Function API 例程(如 mdlOutputs)的调用。例如,使用 TLC 文件内联 S-Function 时,生成的代码将包含通常出现在 S-Function 例程中的 C/C++ 代码,而 S-Function 本身已从编译过程中删除。

完全内联的 S-Function 采用与内置模块相同的方式将算法(模块)嵌入到生成的代码中。通常,完全内联的 S-Function 需要实现两次算法:一次针对 Simulink 模型 (C/C++ MEX S-Function),一次针对代码生成(TLC 文件)。TLC 文件的复杂程度取决于算法的复杂程度以及您要在生成的代码中实现的效率水平。TLC 文件的结构具有不同的复杂程度。请参阅内联 S-Function

为原有代码或自定义代码自动生成的 S-Function

如果您需要在模型中调用手写的 C/C++ 代码,可以考虑使用 Simulink 代码继承工具。代码继承工具可以根据您在代码继承工具数据结构体中注册的信息自动生成完全内联的 S-Function 和对应的 TLC 文件。

有关详细信息,请参阅Integrate C Functions Using Legacy Code Tool使用代码继承工具在生成的代码中导入对外部代码的调用

实现非内联和内联 S-Function 需要的文件

本主题简要介绍创建非内联和内联 S-Function 需要的文件和函数。

  • 非内联 S-Function 需要 C 或 C++ MEX S-Function 源代码(sfunction.csfunction.cpp)。

  • 完全内联的 S-Function 需要一个 sfunction.tlc 文件。完全内联的 S-Function 可为参数化 S-Function 生成最优代码。参数化 S-Function 是在特定模式下运行、依赖于固定的 S-Function 参数(这些参数在模型执行过程中不会改变)的 S-Function。对于给定的操作模式,sfunction.tlc 文件指定为该模式实现算法而生成的确切代码。例如,Write Fully Inlined S-Functions with mdlRTW Routine中的直接索引查找表 S-Function 包含两种操作模式 - 一种用于等间距 x-data,另一种用于非等间距 x-data

    注意

    为调用原有代码或自定义 C/C++ 代码而生成的完全内联的 S-Function 还需要一个 sfunction.tlc 文件,此文件由代码继承工具生成。

完全内联的 S-Function 可能需要在 S-Function MEX 文件 sfunction.csfunction.cpp 中放置 mdlRTW 例程。mdlRTW 例程允许您将信息放在 model.rtw 中。model.rtw 是用来指定模型的记录文件,生成代码时,代码生成器将在执行 sfunction.tlc 之前调用目标语言编译器来处理此文件。

当您要在 TLC 文件中引入不可调参数时,包含一个 mdlRTW 例程很有用。此类参数用于确定在 S-Function 的给定实例中,哪个操作模式处于活动状态。基于此信息,S-Function 的 TLC 文件可为该操作模式生成高效的最优代码。

编写支持代码生成的 S-Function 的规范

相关主题