Main Content

通过开发和使用代码替换库来优化生成的代码 - Simulink

开发和使用代码替换库来替换生成的代码中的函数和运算符。代码替换是指更改代码生成器为函数和运算符生成的代码以满足应用程序代码要求的一种方法。例如,您可以替换生成的代码以满足以下要求:

  • 针对特定运行时环境的优化,包括(但不限于)特定目标硬件。

  • 与现有应用程序代码集成。

  • 符合某种标准,例如 AUTOSAR。

  • 修改代码行为,例如启用或禁用非有限或内联支持。

  • 应用程序或工程特定的代码要求,例如使用 BLAS 或去除 math.h 和系统头文件,或调用 memcpymemset

您可以配置模型,使代码生成器使用 MathWorks® 提供的代码替换库。如果您有 Embedded Coder® 许可证,则可以使用代码替换工具以交互方式开发您自己的代码替换库,或者以编程方式开发。

此示例使用模型来展示可以编程方式定义代码替换映射的各种方法。每个模型都包含一些可用来执行以下任务的按钮:

  • 从代码替换查看器查看代码替换库表定义

  • 在编辑器中打开库表定义文件

  • 在编辑器中打开库注册文件

  • 查看模型配置

  • 生成代码

有关详细信息,请参阅Define Code Replacement Library OptimizationsRegister Code Replacement Library

开发代码替换库的步骤

  1. 根据函数或运算映射、编译版本信息和注册信息来确定代码替换要求。

  2. 为代码替换库开发做好准备(例如,确定或开发模型以测试您的库)。

  3. 定义代码替换映射。

  4. 指定替换代码的编译信息。

  5. 注册代码替换映射。

  6. 验证代码替换。

  7. 部署库。

有关详细信息,请参阅 快速向导代码替换库开发 - Simulink

数学函数替换

此示例定义和注册数学函数的代码替换映射。您可以为各种函数定义代码替换映射(请参阅Code You Can Replace From Simulink Models)。

打开模型 CRLMath 并使用模型窗口底部的按钮来浏览用于定义和注册代码替换库映射的文件。

有关详细信息,请参阅 Math Function Code Replacement

open_system("CRLMath");

加法和减法运算符替换

此示例说明如何为加法 (+) 和减法 (-) 运算定义和注册代码替换映射。定义加法和减法运算的条目时,可以指定您的库函数实现以下哪种算法 (EntryInfoAlgorithm):

  • 运算前转换 (CBO) (RTW_CAST_BEFORE_OP),默认值

  • 运算后转换 (CAO) (RTW_CAST_AFTER_OP)

1.打开模型 CRLAdditionSubtraction。该模型展示了当两个操作数的数据类型为以下内置整数数据类型队组时,如何定义和注册标量加法 (+) 和减法 (-) 运算的代码替换映射:

  • int8, uint8

  • int16, uint16

  • int32, uint32

这里假定采用默认算法 CBO。

open_system("CRLAdditionSubtraction");

2.使用模型窗口底部的按钮来浏览用于定义和注册代码替换库映射的文件。

3.打开模型 CRLCastOperations 以了解 CBO 和 CAO 算法之间的差异。该模型显示两个 SUM 模块,每个展示一种算法设置以匹配相应的代码替换条目。

  • 对于 Cast_before_operation_Sub 模块,代码生成器以 int8 作为累加器数据类型执行减法运算,该数据类型的精度小于输入数据类型 int16 的精度。这相当于 CBO,因为代码生成器在计算结果之前先将输入转换为输出数据类型。

  • 对于 Cast_after_operation_Sub 模块,代码生成器以 int32 作为累加器数据类型执行减法运算,该数据类型的精度大于输入数据类型 int16 的精度。这相当于 CAO,由于代码生成器在计算结果时没有损失任何范围或精度,因此在将结果转换为输出数据类型之后可以得到与 CAO 相同的运算结果。

open_system("CRLCastOperations");

4.使用模型窗口底部的按钮来浏览用于定义和注册代码替换库映射的文件。

有关加法和减法运算符替换的详细信息,请参阅Replace Addition and Subtraction Operator Code。有关加法和减法算法 (EntryInfoAlgorithm) 选项的详细信息,请参阅 setTflCOperationEntryParameters

内置整数的乘法和除法运算符替换

此示例定义和注册标量乘法 (*) 和除法 (/) 运算的代码替换映射。这些运算使用具有内置整数数据类型对组的两个操作数:

  • int8, uint8

  • int16, uint16

  • int32, uint32

打开模型 CRLMultiplicationDivision 并使用模型窗口底部的按钮来浏览用于定义和注册代码替换库映射的文件。

open_system("CRLMultiplicationDivision");

标量运算符替换

此示例为下列标量运算定义和注册代码替换映射:加法、减法、乘法、复共轭、转换、算术右移和算术左移。

支持的类型包括:

  • single、double

  • int8、uint8

  • int16、uint16

  • int32、uint32

  • csingle、cdouble

  • cint8、cuint8

  • cint16、cuint16

  • cint32、cuint32

  • 定点整数

  • 混合类型(每个输入中有不同的类型)

打开模型 CRLScalarOperators 并使用模型窗口底部的按钮来浏览用于定义和注册代码替换库映射的文件。

有关标量运算符替换的详细信息,请参阅Scalar Operator Code Replacement

这里假定采用加法和减法运算的默认算法 CBO。

open_system("CRLScalarOperators");

矩阵运算符替换

此示例为以下矩阵运算定义和注册代码替换映射:加法、减法、乘法、转置、共轭和埃尔米特。

支持的类型包括:

  • single, double

  • int8, uint8

  • int16, uint16

  • int32, uint32

  • csingle, cdouble

  • cint8, cuint8

  • cint16, cuint16

  • cint32, cuint32

  • 定点整数

  • 混合类型(每个输入中有不同的类型)

打开模型 CRLMatrixOperators,其中显示了上述运算符替换中的一部分。使用模型窗口底部的按钮来浏览用于定义和注册代码替换库映射的文件。

有关矩阵运算符替换的详细信息,请参阅Small Matrix Operation to Processor Code Replacement

这里假定采用加法和减法运算的默认算法 CBO。

open_system("CRLMatrixOperators");

BLAS 的矩阵乘法替换

此示例为基本线性代数子例程 (BLAS) 中的子例程 xGEMMxGEMV 定义并注册代码替换映射。您可以将以下运算映射到 BLAS 子例程:

  • 矩阵乘法

  • 对一个或两个输入进行转置的矩阵乘法

  • 对一个或两个输入进行埃尔米特运算的矩阵乘法

打开模型 CRLBLASOperations 并使用模型窗口底部的按钮来浏览用于定义和注册代码替换库映射的文件。

有关 BLAS 矩阵乘法替换的详细信息,请参阅Matrix Multiplication Operation to MathWorks BLAS Code Replacement

open_system("CRLBLASOperations");

基本运算符的定点运算符替换

此示例定义和注册标量加法 (+)、减法 (-)、乘法 (*) 和除法 (/) 运算的代码替换映射。这些运算接受具有定点数据类型的两个操作数。

您可以将代码替换定义为:

  • 匹配输入和输出的斜率/偏置定标对组

  • 匹配输入和输出的二进制小数点定标

  • 匹配输入和输出间的相对定标匹配

  • 匹配所有输入和输出的相同斜率值和零净偏

打开模型 CRLFixedPointOperators 并使用模型窗口底部的按钮来浏览用于定义和注册代码替换库映射的文件。

  • 默认情况下,对于加法和减法运算符代码替换,代码生成器会假定替换代码实现的是运算前转换 (CBO) 算法。

  • 在模型中使用定点数据类型需要 Fixed-Point Designer™ 许可证。

有关定点运算符代码替换的详细信息,请参阅Fixed-Point Operator Code Replacement

open_system("CRLFixedPointOperators");

函数的匹配和替换过程自定义

此示例定义和注册自定义条目的代码替换映射。您可以通过从 RTW.TflCFunctionEntryMLRTW.TflCOperationEntryML 创建子类来创建自己的条目。您的条目类必须实现一个 do_match 方法,用于自定义您的匹配逻辑或修改匹配的条目。该 do_match 方法必须具有固定的预设签名。

打开模型 CRLCustomEntry。该模型显示如何通过注入常量作为附加实现函数参量的方式来修改匹配的条目。DTC1Trigonometric FunctionProduct 分别展示了以下各项的自定义条目代码替换:

  • 转换运算,演示如何从类型中提取小数长度并将其传递给实现函数 - Out1 = custom_cast(In1, 2, 4)

  • 正弦运算,演示如何将一个常量值传递给实现函数 - Out2=custom_sin(In2, 1)

  • 乘法运算,演示如何计算运算的净斜率并将其传递给实现函数 - Out3=custom_multiply_shift_right(In3,In4,3)

使用模型窗口底部的按钮来浏览用于定义和注册代码替换映射的文件。

有关自定义入口函数的详细信息,请参阅Customize Match and Replacement Process

open_system("CRLCustomEntry");

MATLAB 函数替换

此示例为在 MATLAB Function 模块中指定的 MATLAB® 函数定义和注册代码替换映射。通过在函数中指定 coder.replace 可以选择该函数进行替换。此功能支持替换满足以下条件的 MATLAB 函数:

  • 具有一个或多个输入

  • 具有一个或多个输出

  • 输入和输出为标量或矩阵

打开模型 CRLMLFunctionReplacement。该模型显示了上述要求中的部分要求。支持的类型包括:

  • single, double

  • int8, uint8

  • int16, uint16

  • int32, uint32

  • csingle, cdouble

  • cint8, cuint8

  • cint16, cuint16

  • cint32, cuint32

  • 定点整数

  • 混合类型(每个输入中有不同的类型)

使用模型窗口底部的按钮来浏览用于定义和注册代码替换映射的文件。

有关 MATLAB 函数替换的详细信息,请参阅 coder.replace

open_system("CRLMLFunctionReplacement");

函数实现的数据对齐

此示例说明如何指定传入替换函数的矩阵操作数的对齐方式。某些特定于目标的函数实现需要数据对齐以优化应用程序性能。要为函数实现配置数据对齐,请执行以下操作:

  • 在表条目中指定数据对齐要求。您可以逐个或统一为实现函数参量指定对齐。

  • 指定编译器的数据对齐功能和语法。为 rtwTargetInfo.m 文件中指定的注册条目的 TargetCharacteristics 对象附加一个 AlignmentSpecification 对象。

打开模型 CRLDataAlignment。该模型显示了三种数据对齐代码替换场景:

  • Add - 导出和导入信号的对齐。您可以在“信号属性”对话框中指定对齐的确切值,或者通过将对齐值设置保留为 -1 以允许代码生成器基于使用情况确定最佳对齐。

  • Product - 虚拟和非虚拟总线类型的对齐。您可以为 Simulink.Bus 对象的对齐属性指定确切值,或者通过将对齐属性设置保留为 -1 以允许代码生成器根据使用情况确定最佳对齐方式。

  • EML_MMUL - 局部变量、全局变量和模块参数的对齐。

使用模型窗口底部的按钮来浏览用于定义和注册代码替换映射的文件。请注意,该模型配置为使用 GCC、Clang、MSVC 或 MinGW 编译器。

有关指定代码替换的数据对齐的详细信息,请参阅Data Alignment for Code Replacement

open_system("CRLDataAlignment");

代码替换库的查看与验证

此示例展示了代码替换查看器。您可以使用代码替换查看器实现以下目的:

  • 查看要使用哪个代码替换库

  • 验证库中的表列表以及每个表中的条目

  • 查看表条目设定

  • 代码替换错误故障排除

以下命令为代码替换表 crl_table_muldiv 打开代码替换查看器:

crl = crl_table_muldiv;
crviewer(crl);

有关代码替换查看器的详细信息,请参阅Verify Code Replacement Library

编译信息

对于代码替换表中的每个条目,您可以为替换函数指定如下所示的编译信息:

  • 头文件依赖项

  • 源文件依赖项

  • 其他包含路径

  • 其他源文件路径

  • 其他链接标志

此外,在代码生成前,您可以指定 RTW.copyFileToBuildDir 将生成替换代码所需的头文件、源文件或目标文件复制到编译文件夹中。您可以将 RTW.copyFileToBuildDir 指定为:

  • setTflCFunctionEntryParameterssetTflCOperationEntryParameterssetTflCSemaphoreEntryParameters 调用中 GenCallback 属性的值。

  • registerCFunctionEntryregisterCOperationEntryregisterCSemaphoreEntry 调用中 genCallback 参量的值。

注意:此示例中的模型配置仅用于代码生成,因为没有提供替换函数的实现。

有关指定编译信息的详细信息,请参阅Define Code Replacement Library Optimizations中的“指定编译信息”。

保留的标识符

由代码替换表条目定义的每个函数实现名称都会保留为一个唯一的标识符。您可以基于每个头文件使用表指定其他标识符。提供额外的保留标识符有助于防止重复符号和其他与标识符相关的编译和链接问题。

有关指定保留标识符的详细信息,请参阅Reserved Identifiers and Code Replacement

删除示例代码替换库

示例模型使用完毕后,请删除示例代码替换库,并使用以下命令关闭示例模型:

sl_refresh_customizations;

close_system("CRLMath",0)
close_system("CRLAdditionSubtraction",0)
close_system("CRLCastOperations",0)
close_system("CRLMultiplicationDivision",0)
close_system("CRLScalarOperators",0)
close_system("CRLMatrixOperators",0)
close_system("CRLBLASOperations",0)
close_system("CRLFixedPointOperators",0)
close_system("CRLCustomEntry",0)
close_system("CRLMLFunctionReplacement",0)
close_system("CRLDataAlignment",0)

drawnow;
if exist("h","var") && ishghandle(h)
  close(h);
end


clear h;
clear isDaDemoSupported;
clear crl;