为什么从带有“duration”操作符的状态流逻辑生成的C代码中有转换为real_T (double) ?

6次浏览(过去30天)
在Stateflow逻辑中使用'duration'会导致在生成的代码中进行(real_T)转换。
C代码应在嵌入式环境中使用,精度要求单一。
是否有可能使用'duration'操作符并在没有转换为double的情况下生成代码?
Stateflow逻辑:
up = duration(Measurements_input.curr_battery_prim.)>FLOATING_STATE_UPPER_LIMIT, sec) > CHARGING_STATE_SWITCHING_TIME;
生成的代码:
661 /*期间“浮动”“< S2 >: 112”* /
662如果((real_T) (rtDW。chartAbsoluteTimeCounter -
663 rtdt . durationlastreferencetick_1) >
664 charging_state_switching_time * 200.0f) {
665 /*过渡:“< S2 >: 152”* /
666 rtDW。is_NormalOperation = IN_Charging;
667
668 /*条目“充电”“< S2 >: 113”* /
669}
谢谢,

答案(1)

安迪·巴特利特
安迪·巴特利特 2021年8月9日
编辑:安迪·巴特利特 2021年9月2日
可调参数的持续时间似乎是一个限制单设计
在上面的模型中,tuneParam1、tuneParam2和tuneParam3是Simulink。万博1manbetx类型为single的参数是可调的(StorageClass = ExportGlobal)。输入u,输出y,常数c1, c2也是单一的。
当运行Model Advisor检查严格单精度时,会检测到双精度的使用。
使用Embedded Coder生成C代码确实显示了与持续时间计算相关的双精度的使用。
我没有成功地去除可调参数情况下的双精度值。我将在MathWorks中询问是否有一种方法可以消除我遗漏的双精度。如果没有,我们将寻求加强这一点。
如果不是一个可调参数,那么下面的方法应该可以工作
声明可能是简单的解决办法
我怀疑您正在进行双精度比较操作,因为您的模型已经(隐式或显式)声明了 CHARGING_STATE_SWITCHING_TIME为double。
我还怀疑CHARGING_STATE_SWITCHING_TIME的声明方式使编码器不将其视为可以折叠到其他计算中的常量值。如果它是可恒定折叠的,那么CHARGING_STATE_SWITCHING_TIME * 200.0F将被像1.234这样的文字值替换。
我认为最简单的解决方案是找到CHARGING_STATE_SWITCHING_TIME声明的位置,并将该声明更改为single。如果您希望值折叠为常数,那么也可以考虑将其声明为常数。
混合基本MATLAB类型的关系运算符
我对关系操作符的处理做了一些研究。
混合了单精度和双精度的关系操作符通常会生成包含双精度的代码。这是意料之中的,因为MATLAB被设计为对基本MATLAB类型(双,单,逻辑,uint8,…)的任何组合的关系操作给出全精度理想答案。int64)。带有单变量和双常量的关系操作目前也会生成包含浮点双精度操作的代码。MathWorks正在研究优化这些用例,以避免在未来的版本中使用double类型。
状态流持续时间通常是高度优化的
我还对statflow处理R2021a的持续时间做了一些调查。我发现statflow倾向于高度优化处理。
作为一个例子,考虑这张图,其中u是单一的,采样时间是2^-10秒。
注意这个表达式
Duration () > 0.37
由于采样时间为2^-10,当0.37/2^-10 = 378.88个时钟滴答流逝时,持续时间将大于0.37。Stateflow生成以下整数代码来处理持续时间与0.37的比较
EmbedSFDuration。持续时间LastReferenceTick_1_o > 379
它不仅没有使用浮点双精度,而且根本没有使用浮点。只是整数。这样通常会更快。
为什么这种优秀的优化水平没有在您的模型中发挥作用?如上所述,我怀疑右边是双的,不能经常折叠,因此减少了优化。另外,请注意,我使用R2021a进行了测试,它可能比您使用的版本更优化。
现在,正如上一节所预期的那样,这个图表确实为另外两个关系操作符生成了双精度操作符。
condIsTrue = (EmbedSFDuration_U。U1 >= 0.41);
EmbedSFDuration_U。U1 < 0.3
根据需要显式强制转换常量
为了避免双精度关系运算符,一种解决方案是在使用MATLAB(包括Stateflow MATLAB Action Language)时显式键入常量。下面的图表中u和y是单个的,这是一个关系运算符中使用的显式常量强制转换的例子。
这将为关系操作符生成以下C代码,并避免重复操作。
condIsTrue = (EmbedSFDuration_U。u3 >= 0.41F);
EmbedSFDuration_U。u3 < 0.3F
您可能想知道其他隐式声明为double的常量-0.05和0.15。赋值操作符则是另一回事。文字值的赋值将触发不断的折叠,而double的使用将被消除。
EmbedSFDuration_Y。y2 = -0.05F;
<剪>
EmbedSFDuration_Y。y2 = 0.15F;
如上所述,MathWorks希望在未来的版本中为混合了双精度和单精度的关系运算符提供类似级别的常量折叠。如果你认为这应该是一个高优先级,请给我们留言或在下方留下评论。在交流这个需求时,请告诉我们你所在的公司。谢谢。
提示:Stateflow C动作语言的上下文敏感常量
如果您正在使用传统的Stateflow C动作语言,您可以为上下文敏感的常量使用特殊的语法。
U < 0.3cC动作语言特性上下文敏感常量
末尾的小“c”表示字面值0.3没有声明的类型。相反,您希望statflow在生成的代码中找出在数值上有用且高效的类型。在这种情况下,对0.3使用u类型是可取的。
提示:用于MATLAB比较的类转换
如果您正在使用MATLAB,包括Stateflow的MATLAB Action Language和MATLAB Function块,并且您不想显式设置常量的类型,则可以使用类强制转换。
U < cast(0.3,“喜欢”, u)% MATLAB类型转换
这将强制将值0.3转换为与u相同的类型。这将适用于任何类型,包括基本MATLAB类型和定点类型。这种类强制转换的使用使得关系操作代码完全多态,因此可以在许多情况下重用。
2的评论
安迪·巴特利特
安迪·巴特利特 2021年9月2日
啊,我大脑中编码的部分看到的都是大写字母,按照惯例认为是常量。
可调参数是另一回事。我调查了他们,修改了他们的答案。

登录评论。

s manbetx 845


释放

R2020a

社区寻宝

在MATLAB Central中找到宝藏,并发现社区如何帮助您!

开始狩猎!