相关文章推荐
虚心的长颈鹿  ·  django rest framework ...·  2 月前    · 
聪明伶俐的鞭炮  ·  2022.21 ...·  1 年前    · 
神勇威武的红酒  ·  透射电镜 - 知乎·  1 年前    · 
逆袭的墨镜  ·  python - 重命名 Pandas ...·  1 年前    · 
首发于 MBD开发

Simulink模型设置对自动代码生成的影响

一 模型的通用设置

与代码生成相关的设置都在Code Generation里面,下面就介绍常用的一些对代码生成有影响的设置。

1.1 System target file

这个是选择系统目标文件,一般生成生成嵌入式系统代码的话,都是选ert.tlc。如果是生成autosar架构的应用层代码就选autosar.tlc。如果是生成window系统桌面能运行的代码的话,选择grt.tlc。实际应用中基本不是选ert.tlc就是autosar.tlc

1.2 Language

如果是要生成C代码就选C,要生成C++代码就选C++。现在基本都是生成C代码,但感觉以后如果要应用Adapt AUTOSAR的话,就会生成C++代码了

1.3 Build process

如果我们仅仅是要生成代码,不需要后续编译的话,就勾选{Generate code only}。如果不勾选这个的话,生成玩代码就会自动运行makefile进行编译,如果生成的代码是要配合别的代码文件一起使用的话,编译基本都是报错的,所以这边推荐都是勾选上{Generate code only}

{Package code and artifacts}这个选项如果勾上的话,会把生成的代码打包成一个压缩文件。

{Toolchain}是选择编译代码时需要用到的编译器,如果只是仅仅生成这个模块的代码,编译是后面有专门的编译环境的话,这边选"Automatically locate an installed toolchain"就可以了,最近版本的matlab已经默认了LCC的编译环境,可以保证Stateflow的代码生成,比较老的matlab版本是需要自己装一个编译器,比如MinGW或VS之类的才能保证Stateflow能正常生成代码。

1.4 Prioritized objectives

这个可以选择代码生成时,如果一些规则有冲突的话,按照哪种优先级来生成代码。比如如果按照下图来选择的话,就是MISRA C规范优先级最高,为了保证生成的代码能满足MISRA C规范,会牺牲掉ROM以及RAM的经济性以及执行效率。这个可以根据实际需求来选择。这个不会影响实际功能,所以如果没有这方面讲究的话,不选也无所谓

1.5 Check model before generating code

这个如果选"on"的话,会在生成代码前做一遍模型检查。这个一般都会选off,否则每次生成代码前都做一遍模型检查很浪费时间。

二. 模型优化设置

2.1 Default parameter behavior

这个选项表示默认的参数行为类型,可以选"Inline"和"Tunable"。"Inline"表示生成代码时直接用这个参数的值,"Tunable"表示会有这个参数的变量定义,以保证代码实际运行时,可以修改这个参数的可能。我们来看一下区别。

对于这个Unit Delay模块的初始值,我们设置了一个参数init_value,并且把值设为1。

下面是"Inline"设置生成的代码,初始化的时候,直接用的是1这个值,而没有体现出任何实际的参数。也就是说这个初始值就固定为1了。

下面是"Tunable"生成的代码,初始化的时候是给了一个全局变量,这个全局变量的值是1,但是因为有了全局变量,在代码运行的时候是可以把这个值标定为其他值的,这也就是Tunable的含义。

值得注意的是,这个设置仅对没有明确参数类型的变量生效。如果你对一个参数定义为了之前说的参数对象,并且属性是ExportGlobal,那这个参数一定是Tunable的,不会受这个选项的影响。

2.2 Remove root level I/O zero initialization和Remove internal data zero initialization

这两个选项都是表示是否要生成初始值为0的变量初始化赋值,因为一般编译器对于一个变量默认的初始值就是0,所以可以对初始值是0的变量不进行初值赋值。勾选{Remove root level I/O zero initialization}表示模型的输入和输出的初始值如果是0的话,就不生成初始化赋值。勾选{Remove internal data zero initialization}的话,就表示模型内部变量的初始值如果是0的话,就不生成初始化赋值。

下面看一下{Remove internal data zero initialization}勾选与否的具体例子。

勾选的情况下,初始化函数里没有任何内容,因为内部变量的初始值都是0

不勾选的情况下,即使内部变量的初始值是0,也会有赋值语句生成了。

2.3 Optimization levels

这里面的设置是生成代码时的优化设置。其中{Level}可以有3个选择,"Minimum"表示不进行任何优化,这个可以最大限度的保证代码和模型的可追溯性。"Maximum"表示进行最大程度的优化,这时生成的代码会优化一些模型的细节。另外一个选项是折中的选择。

Priority也可以有3个选择,看要哪个项目的优先级最高,分别是平衡RAM的用量和执行速度,最大的执行速度和最小的RAM用量

另外也可以通过勾选{Specify custom optimizations}指定里面具体的一些细节,这些细节的内容和上面选项对应关系如下图,这边就先不详细解释每一个选项的作用了,关心的同学可以查看matlab的帮助,或者后面专门写一遍介绍这个的文章。

模型优化设置里面还有一些高级的设置,点击三个点就能看到

2.4 Loop unrolling threshold

表示要用到for循环的维度阈值,这里设为5,表示维度超过5的话,就会用到for循环。

比如我们把这个模型的输入输出维度设为3

把{Loop unrolling threshold}设为4,那么生成的代码如下,都是一个维度一个维度计算的。

把{Loop unrolling threshold}设为2,因为维度3大于2,这时就会生成for循环了。

2.5 Optimize using the specified minimum and maximum values

表示生成的代码是否会根据变量指定的范围做优化。

比如有一个除法,我们设置alpha1的范围是[1,1.25],我们设置了会生成零除保护的代码

如果不勾选这个选项,那么生成的代码如下,如果除数为0,则结果等于uint32的最大值

如果勾选了这个选项,那么由于除数的范围不包括0,那么就不会生成零除保护的代码

2.6 Inline invariant signals

勾选这个选项后,对于不变的变量,会直接用其实际的值

比如对于如下模型

勾选{Inline invariant signals}后,生成的代码如下,变量offset_const没有生成,而是直接使用了其不变的值9


不勾选勾选{Inline invariant signals}生成的代码如下,仍然会生成变量的名称,其值在初始化的时候被赋值为9

2.7 Remove code from floating-point to integer conversions that wraps out-of-range values

勾选这个选项后,当浮点数转定点数时,就是直接转换,不会生成多余的保护代码,比如对于如下模型,由浮点数转为uint8类型

当不勾选这个选项时,会生成当浮点数小于0时,取反的代码

当勾选这个选项时,就直接把浮点数转为定点数

其实对于浮点数转定点数比较好的做法是,先把浮点数限制到定点数的范围之类,然后再转定点数,这样勾选这个选项也不会有问题,生成的代码也比较简洁。

2.8 Remove code that protects against division arithmetic exceptions

勾选这个选项后,就不会再生成零除保护的代码了。

对于零除的可能,推荐直接在模型中体现如果除数是0的时候的处理,而不是靠这个选项来保证不会发生零除。

三. 模型代码报告设置

勾选{Create code generation report}的话,在代码生成完成后会生成一份报告。

3.1 Open report automatically

生成完报告后会自动打开报告

3.2 Generate model Web view

同时会生成一份网页版的模型,如果要把模型分享给没有matlab的人,可以使用这个选项

3.3 Static code metrics

会生成一份代码静态统计的报告

3.4 Code-to-model

可以通过代码直接连接到模型,比如点击这个链接就可以直接跳到生成这段代码的模型处

3.5 Model-to-code

可以通过模型跳转到其生成得到代码处。选中一个模型,点击鼠标右键,选择C/C++ Code/Navigate To C/C++ Code 就可以跳转到其生成得到代码处。


3.6 Traceable Simulink blocks, Traceable Stateflow objects, Traceable MATLAB functions

支持Simulink模块,Stateflow和Matalb function的代码和模型之间的追溯

对于模型生成的报告,这些选项都是推荐勾选的。

四 变量命名规范的设置

下图是默认的各种变量的命名规范。

其中一些特殊符号的含义如下:

$M为了防止命名有重复,而插入的词尾后缀,这个是必须的

$N插入生成对象的名称,可以是模块名,信号线名或者参数名$R插入模型名称,如果模型名中有非法字符会用下划线替代

$A插入数据类型名称

下面我们来看一下实际的例子,按照上图,对模块输出的临时变量的命名规则设置,"rtb_"是固定的字符,"$N"是模块名或信号线名,"$M"是防止命名重复的后缀。

生成出来的代码如下,其中"rtb_"是固定的,然后因为该模块后的信号线上没有信号名,"$N"用的是模块名"LookupTable_1D",由于这个模型并没有用到其他的叫"LookupTable_1D"的模块,所以不会有重复的命名,于是$N的后缀就被省略掉了。

我们修改一下设置,把rtb_替换为wk_,并且添加变量数据类型的描述$A

这样生成的代码如下,可以看到,临时变量的名称就按我们的设置有了变化

五 插入自定义代码

我们可以在 Custom Code 里设置在不同的位置插入我们想要的自定义代码。

可以插入自定义代码的位置有4个,分别是代码文件,头文件,初始化函数和终止函数。

比如我们设置如下:

那么生成的代码如下,在.c文件开头的地方,插入了自定义的代码。

在.h文件开头的地方,插入了自定的包含头文件

在初始化函数中,也插入了自定义的代码

六 代码接口设置

这里主要设置一些生成的代码与外部集成环境的接口的设置。这里介绍几个比较重要并且常用的设置。

6.1 Code replacement library

这里可以设置将一些函数,生成为符合特定规范的函数。

比如对于查表函数,如果Code replacement library设置为None的话,就会生成默认的查表函数。

如果设置为"AUTOSAR 4.0"的话

生成的查表函数就是按照autosar规范的查表函数名称生成

6.2 Support

这个主要是设置代码生成所支持的一些特殊类型。这里需要注意的是,这边只能勾选代码集成环境支持的类型,否则代码集成的时候可能会有问题。

这里不勾选的类型,如果模型中有的话,生成代码时就会报错。比如,如果处理器不支持浮点数计算,那我们这边就不能勾选"floating-point numbers",如果此时模型中有浮点类型的信号时,就会报错了。

6.3 ASAP2 interface

如果需要使用到Matlab生成A2L文件的话,就需要勾选ASAP2 interface,否则的话,就不需要勾选该选项。

勾选的话,就会生成一个a2l文件。

6.4 Standard math library

这个比较重要,这个需要根据实际编译器所用的math library版本选择。C89/C90和C99在生成某些数学函数的形式上会有区别。

比如对于max函数,C89/C90生成的代码如下:

C99生成的代码如下,直接使用了C99中有定义的fmaxf函数。

七 代码模板

7.1 Generate an example main program

勾选这个选项后,会生成一个main函数,调用模型生成的主函数。如果不需要这么一个函数的话,就不要勾选该选项了。

7.2 生成代码的模板

如果需要自定义生成代码模板的话,可以修改ert_code_template.cgt文件。

或者自己写一个模板文件。

比如默认的模板文件中,规定了在代码文件开头有File信息,model信息,Model version信息,Simulink Coder version信息,代码生成时间,模型设置信息等。

比如我们可以更改模板加入自己公司的logo。或者为了避免每次生成代码时间都不一样会导致SVN上的代码有区别,可以删除时间信息。通过修改模板生成的代码如下:

模板文件如下:

八 代码放置

比较有用的一个设置是{File packaging format}

如果设为Modular的话,代码文件会按模块化分开:

如果嫌代码文件太多的话,可以设为Compact,这样就只有一个.c和一个.h文件了:

如果需要数据文件是单独一个文件的话,就选择Compact(with separate data file)。

九 数据类型名替换

勾选{Replace data type names in the generated code}后,就可以替换默认生成的数据类型。

比如我们可以把Simulink的single类型在生成代码的时候生成float32,而不是默认的real32_T。

首先,定义float32为Simulink.AliasType,并且将BaseType设为single。即在命令窗口输入:

float32 = Simulink.AliasType;

float32.BaseType = 'single';

然后在设置中,将single的Replacement设为float32

这样,生成出来的代码如下,定义sisngle类型时,就用了float32

利用这个设置就可以将自动生成代码的数据类型和已有代码的数据类型完全匹配上。

发布于 2020-06-04 22:26

文章被以下专栏收录