文档

确定为什么Simulink Ac万博1manbetxcelerator正在重新生成代码

有时Simulink万博1manbetx®会在加速模式(TM)的模拟开始时重新生成模型的仿真目标,但并不总是清楚为什么会发生重新生成。此示例演示如何使用Simulink®MATLAB®命令来确定万博1manbetx为什么Simulink为加速模式模拟重新生成代码。

万博1manbetxSimulink的加速模式通过创建模型的可执行版本(称为仿真目标)来加速模型的仿真,并运行该目标,而不是像在普通模式仿真中那样解释模型。加速模式通过从模型生成C代码并调用MATLAB®mex函数来编译生成的代码并将其动态链接到Simulink来创建仿真目标。万博1manbetx

代码生成和编译过程发生在您第一次以加速模式模拟模型时。此外,代码生成可能发生在后续的模拟中,特别是当模型在模拟之间发生变化时(例如,在添加块之后)。代码生成需要时间,为了在给定的时间跨度内最大化模拟的数量,通常希望避免这种情况。

万博1manbetxSimulink使用模型的校验和来确定是否需要重新生成代码。这个校验和是一个由四个整数组成的数组,通过使用基于模型属性及其包含的块的md5校验和算法计算得出。模型中更改校验和的任何更改都会导致Simulink为加速模式重新生成模拟目标。万博1manbetx

有时,不清楚是哪个模型更改触发了校验和更改,从而导致代码重新生成。这个例子展示了如何研究为什么Simulink需要为给定模型及其配置重新生成加速器模式万博1manbetx模拟的代码。

创建临时工作目录

由于在加速模式下模拟会创建一些文件,首先移动到一个临时区域。

originalDir = pwd;tempDir = tempname;mkdir (tempDir) cd (tempDir)

打开一个范例模型

在本例中,我们将使用一个简单的模型slAccelDemoWhyRebuild。

模型=“slAccelDemoWhyRebuild”;open_system(模型)

模型第一次以Accelerator模式运行时,它会按照预期生成和编译代码。

simOutput = evalc([“sim(“”、模型“‘)’]);如果~ isempty (strfind (simOutput“为模型构建加速器目标”) disp (内置的Simu万博1manbetxlink Accelerator文件其他的disp (“未构建Simulink Ac万博1manbetxcelerator文件”结束
没有建立Simulink A万博1manbetxccelerator的mex文件

如果再次运行模拟,而不对模型进行任何更改,我们期望Simulink可以重用现有的代码,而不需要重新生成代码。万博1manbetx执行相同的命令进行验证。

simOutput = evalc([“sim(“”、模型“‘)’]);如果~ isempty (strfind (simOutput“为模型构建加速器目标”) disp (内置的Simu万博1manbetxlink Accelerator文件其他的disp (“未构建Simulink Ac万博1manbetxcelerator文件”结束
没有建立Simulink A万博1manbetxccelerator的mex文件

现在我们改变模型中的一些参数。我们将为块'Integrator'设置以下设置:-设置'忽略限制并在线性化时重置'为'on' -设置'初始条件'为'5'

set_param([模型,' /集成商'],“IgnoreLimit”“上”);set_param([模型,' /集成商'],“InitialCondition”“5”);

当我们再次运行模拟时,我们看到Simulink重新生成了代码。万博1manbetx

simOutput = evalc([“sim(“”、模型“‘)’]);如果~ isempty (strfind (simOutput“为模型构建加速器目标”) disp (内置的Simu万博1manbetxlink Accelerator文件其他的disp (“未构建Simulink Ac万博1manbetxcelerator文件”结束
没有建立Simulink A万博1manbetxccelerator的mex文件

我们想知道原因。

为了确定先前生成的代码对于当前模型配置是否仍然有效,Simulink将用于生成代码的模型的校验和与当前校验和进行比较。万博1manbetx如果它们相等,则先前生成的代码仍然有效,并且Simulink加速模式将其用于当前模拟。万博1manbetx如果值不同,Simulink加速模式将重新生万博1manbetx成并重新构建代码。因此,检查校验和计算的细节可以揭示为什么Simulink重新生成代码。万博1manbetx

获取校验和详细信息

下面的命令获取模型校验和计算细节:

[cs1, csdet1]万博1manbetx = Simulink.BlockDiagram.getChecksum(模型);

第一个输出是模型校验和值本身。第二个输出给出了校验和计算的细节。

让我们将修改后的块参数设置为原始值,并获得该配置的校验和和详细信息

set_param([模型,' /集成商'],“IgnoreLimit”“关闭”);set_param([模型,' /集成商'],“InitialCondition”' 0 ');(cs2 csdet2] 万博1manbetx= Simulink.BlockDiagram.getChecksum(模型);

比较这两个校验和值相当于确定Simulink Accelerator是否会重新生成代码。万博1manbetx请注意,校验和值是不同的,正如我们基于Simulink Accelerator在每次运行时重新生成代码的事实所期望的那样。万博1manbetx

如果(cs1 ~= cs2)“校验和是不同的”其他的disp (校验和是相同的结束
校验和是不同的

现在我们知道校验和是不同的,下一个问题是为什么。校验和计算中包含许多内容,包括信号数据类型、一些块参数值和块连接信息。为了理解为什么校验和不同,我们需要看看用于计算校验和的项发生了什么变化。作为第二个参数返回的校验和详细信息提供了该信息。

csdet1
csdet1 = struct with fields: ContentsChecksum: [1x1 struct] InterfaceChecksum: [1x1 struct] ContentsChecksumItems: [176x1 struct] InterfaceChecksumItems: [48x1 struct]

校验和细节是一个包含四个字段的结构数组。其中两个字段是模型校验和的组件校验和(它们被称为ContentsChecksum和InterfaceChecksum),另外两个字段是相应的校验和细节。这些细节对应于进入两个组件校验和计算的各种信息。模型[structural]校验和是ContentsChecksum和InterfaceChecksum的函数。

首先,让我们确定区别在于模型的内容还是模型的接口

如果(csdet1.ContentsChecksum。值~ =csdet2.ContentsChecksum.Value) disp(“内容校验和不同”其他的disp (“内容校验和相同”结束如果(csdet1.InterfaceChecksum。值~ =csdet2.InterfaceChecksum.Value) disp(“接口校验和不同”其他的disp ('接口校验和相同'结束
内容校验和不一致接口校验和相同

使用详细信息来确定校验和更改的原因

现在我们知道更改在ContentsChecksum中,我们可以查看ContentsChecksumItems以查看更改了什么。

idxForDifferences = [];idx = 1:length(csdet1.ContentsChecksumItems)如果(~ strcmp (csdet1.ContentsChecksumItems .Handle (idx),...csdet2.ContentsChecksumItems (idx) .Handle)) idxForDifferences = [idxForDifferences idx];disp ([“处理不同的项目”num2str (idx)]);结束如果(~ strcmp (csdet1.ContentsChecksumItems .Identifier (idx),...csdet2.ContentsChecksumItems (idx) .Identifier) disp ([“项目的标识符不同”num2str (idx)]);idxForDifferences = [idxForDifferences, idx];结束如果(ischar (csdet1.ContentsChecksumItems (idx) value))如果(~ strcmp (csdet1.ContentsChecksumItems (idx) value,...csdet2.ContentsChecksumItems (idx) value) disp ([“项目的字符串值不同”num2str (idx)]);idxForDifferences = [idxForDifferences, idx];结束结束如果(isnumeric (csdet1.ContentsChecksumItems (idx) value))如果(csdet1.ContentsChecksumItems (idx)。值~ =...csdet2.ContentsChecksumItems (idx) value) disp ([“项目的数值不同”num2str (idx)]);idxForDifferences = [idxForDifferences, idx];结束结束结束
第41项的值不同

现在我们知道了idxForDifferences中列出的索引项之间的差异,我们可以在两个ContentsChecksumItems数组中查看这些项

blk1 = csdet1.ContentsChecksumItems(idxForDifferences(1))。处理blk2 = csdet2.ContentsChecksumItems(idxForDifferences(1))。处理id1 = csdet1.ContentsChecksumItems(idxForDifferences(1))。标识符id2 = csdet2.ContentsChecksumItems(idxForDifferences(1)).标识符id2 = csdet2.ContentsChecksumItems
blk1 = 'slAccelDemoWhyRebuild/Integrator' blk2 = 'slAccelDemoWhyRebuild/Integrator' id1 = 'IgnoreLimit' id2 = 'IgnoreLimit'

这两个项目的句柄都是'slAccelDemoWhyRebuild/Integrator',它表示数据发生变化的块。两者的标识符都是'IgnoreLimit',这告诉我们这是块设置的改变,导致模型的校验和不同。块的初始条件设置不会出现在校验和详细信息中。因此,我们期望只要修改初始条件的设置,就不会发生重建。

避免在连续的模拟上重新构建

现在我们找到了导致这个工作流的校验和不同的参数,我们可以通过保持该参数不变并查看是否在连续的模拟中发生重建来验证发现。

让我们再次在加速模式下模拟模型。我们期望它为这个模拟重新构建,因为我们更改了上面校验和计算的参数('IgnoreLimit')。

simOutput = evalc([“sim(“”、模型“‘)’]);如果~ isempty (strfind (simOutput“为模型构建加速器目标”) disp (内置的Simu万博1manbetxlink Accelerator文件其他的disp (“未构建Simulink Ac万博1manbetxcelerator文件”结束
没有建立Simulink A万博1manbetxccelerator的mex文件

现在让我们只改变初始条件设置并再次模拟。我们希望这次不会再发生重建。

set_param([模型,' /集成商'],“InitialCondition”“3”);simOutput = evalc([“sim(“”、模型“‘)’]);如果~ isempty (strfind (simOutput“为模型构建加速器目标”) disp (内置的Simu万博1manbetxlink Accelerator文件其他的disp (“未构建Simulink Ac万博1manbetxcelerator文件”结束
没有建立Simulink A万博1manbetxccelerator的mex文件

正如校验和分析所预期的那样,更改“初始条件”的参数不会导致加速模式下模拟代码的再生。

清理

关闭模型并删除生成的文件。

明确bdclose(模型)([模型,“_acc”) cd(originalDir) rmdir(tempDir)“年代”
这个话题有用吗?