控制和显示执行顺序
模型的执行顺序是软件在仿真期间调用模块输出方法的顺序。软件在模型更新过程中确定此顺序,您可以通过点击建模选项卡上的更新模型来启动模型更新。该软件还会在仿真期间更新模型。
您不能设置执行顺序,但您可以为非虚拟模块分配优先级,以指示这些对应的模块图中的模块相对于其他模块的执行顺序。
一些非虚拟模块不支持模块优先级。例如,软件忽略在以下模块上设置的优先级:
Merge 模块。
具有函数调用输入端口的模块,例如引用导出函数模型的 Function-Call Subsystem 模块和 Model 模块。
具有动作端口的模块,例如 If Action Subsystem 和 Switch Case Action Subsystem 模块。
For Iterator Subsystem 模块中的 For Iterator 模块和 While Iterator Subsystem 模块中的 While Iterator 模块。For Iterator 和 While Iterator 模块必须分别是在 For Iterator Subsystem 和 While Iterator Subsystem 模块中执行的第一个模块。
如果对这些模块设置优先级,则模块优先级违规配置参数设置将确定您是否会收到警告或错误。
在不存在数据依存关系冲突的情况下,软件会尽量遵循模块优先级设置。要确认您已设置的优先级结果或调试您的模型,请显示并检查您的非虚拟模块和子系统的执行顺序。
有关模块方法和执行的详细信息,请参阅:
执行顺序查看器
在调试选项卡上,选择叠加信息 > 执行顺序。执行顺序查看器在 Simulink® 编辑器右侧的窗格中打开。
执行顺序查看器显示基于最新编译的执行顺序的信息。
系统索引 - 表示当前系统或非虚拟子系统的模型中的唯一值。对于顶层模型,该系统索引为
0
。对于每个非虚拟子系统,系统索引是正整数。直接位于非虚拟子系统内部的模块具有与该子系统相同的系统索引。要确定某个模型中的子系统是否属于同一系统,请比较其系统索引值。
在模型引用层次结构中,同一个系统索引可能会多次使用。它仅在层次结构的每个模型中保持唯一。
执行顺序模块列表 - 按基于任务的执行顺序排列的模块列表。模块列表提供所选任务的完整执行顺序信息,提供的信息比模块图显示得更多。例如,该列表包括隐藏模块和子系统模块图中的模块。
任务 ID - 当前系统中每个任务的唯一标识符。每个任务对应于一组模块,这些模块基于它们所派生的采样时间信息,以相对于彼此的设置顺序执行。单个任务 ID 可以包含具有多种不同类型的采样时间的模块。执行顺序在不同任务中显示具有不同类型的固定采样时间的模块。例如,固定采样时间为
[Inf 0]
和[Inf Inf]
的 Simulink 模块分别显示在任务 1 和任务 2 中。有关采样时间的详细信息,请参阅固定采样时间。要以编程方式获取采样时间信息,请使用
get_param
函数。有关详细信息,请参阅模块编译后的采样时间。get_param('model_name/block_name','CompiledSampleTime')
对于定步长,将每个离散速率视为单独任务配置参数决定是否在一个或多个任务中以离散速率执行模块。
要更新自上次编译以来已更改的模型的执行顺序信息,请重新编译该模型。在执行顺序查看器中,点击重新编译模型以更新执行顺序信息按钮 。
要突出显示属于某个任务的模块并显示其执行顺序,请在执行顺序查看器中选择该任务。默认情况下,软件选择与活动模块图对应的第一个任务。
注意
从 R2023b 开始,执行顺序显示画面不再突出显示所选任务的信号线和虚拟模块。有关虚拟模块的详细信息,请参阅非虚拟和虚拟模块。
当活动模块图不包含作为给定任务的一部分执行的任何模块时,您无法在执行顺序查看器中选择该任务。活动模块图可能包含作为此任务的一部分的虚拟模块,如 Inport 模块。
要隐藏突出显示和执行顺序,请点击清除突出显示按钮 。
从模块导航到任务
要显示在其中执行模块的任务,请点击模块。
标签中的任务编号显示为链接,您可以点击这些链接以在执行顺序查看器中选择对应的任务。当一个模型有许多任务时,您可以点击这些链接而无需在执行顺序查看器中滚动任务列表。
要比较模块之间的任务,请选择多个模块。
执行顺序的表示
该模块图在每个非虚拟模块的右上角显示一个数字。这些数字表示模块的执行顺序。要执行的第一个模块具有最小执行顺序值,通常是 1
。显示的执行顺序可以是不连续数字,但模块始终按可见数字的顺序执行。假设一个任务显示执行顺序 1、2 和 4。标记为 1 的模块在标记为 2 的模块之前执行,标记为 2 的模块在标记为 4 的模块之前执行。
例如,在此模型中,模块执行顺序的范围是从 1
到 12
,每个非虚拟模块都会收到一个执行顺序。
虚拟和非虚拟子系统
虚拟 Subsystem 模块只是在图形层面存在的模块,并不执行。因此,它们不是执行顺序的一部分。当模块按模块路径排序时,创建虚拟子系统会影响模块的执行顺序。虚拟子系统中的每个模块作为原子单元执行,并且在根级模型的上下文中有一个执行顺序;如果该虚拟子系统在一个非虚拟子系统内部,则这些模块在父级非虚拟子系统的上下文中有一个执行顺序。对于虚拟子系统,该子系统内的模块执行顺序列在花括号 {} 内。
非虚拟 Subsystem 模块是在功能意义上存在的模块,会作为一个单元来执行。它们有单一执行顺序和不同于根级模型或任何父级非虚拟子系统的系统索引。一个非虚拟子系统内的模块有它们自己的执行顺序,它们独立于根级模型或任何父级非虚拟子系统。
例如,此模型包含名为 car dynamics
的虚拟子系统和名为 discrete cruise controller
的非虚拟原子子系统。
虚拟 car dynamics
子系统将它所包含的模块的执行顺序列表显示在花括号内。它包含的模块在与 Step、Sum 和 Scope 模块以及 discrete cruise controller
非虚拟子系统相同的级别上执行。Integrator 模块首先执行,并将其输出发送到 Scope 模块,后者第二个执行。
非虚拟 discrete cruise controller
子系统只有一个执行顺序 (4
),表明该子系统和其中的模块是相对于相同级别的模块执行的第四个。
注意
根据您的模型配置,软件可以在您的模型中插入隐藏的非虚拟子系统。结果,隐藏的 Subsystem 模块内部的可见模块具有的系统索引可能不同于当前系统索引。例如,如果选择条件输入分支执行配置参数,该软件可能会创建隐藏的非虚拟子系统进行优化,这可能影响已排序的执行顺序。
代数环
代数环中的模块会移到一个隐藏的非虚拟子系统中。软件首先确定隐藏子系统在其他模块的上下文中的执行顺序,然后确定隐藏子系统中的模块的执行顺序。请参阅代数环概念。
函数调用和执行子系统
对于函数调用和执行子系统,子系统的执行由其发起方的执行来控制。因此,该子系统及其发起方具有相同的执行顺序。
该软件忽略 Function-Call Subsystem、If Action Subsystem 或 Switch Case Action Subsystem 模块设置的任何模块优先级,但您可以设置启动这些子系统的模块的模块优先级。
在导出函数模型的根级,函数调用执行顺序有 F
前缀。
有关详细信息,请参阅导出函数模型概述。
总线和多个发起方
当一个模块基于指向该模块的不同执行路径执行多次时,该模块具有多个执行顺序。例如:
连接到总线的模块的执行顺序对应于总线包含的每个信号。
具有多个发起方的函数调用或执行子系统的执行顺序对应于每个发起方。
确定执行顺序
基于任务的排序,根据其派生的采样时间信息设置模块和端口的执行顺序。通过基于任务的排序,可以简单高效地确定模块的执行顺序。
使用基于任务的排序可以:
根据采样时间单独排序任务。
生成多个排序列表,而不是为所有任务中的模块生成一个扁平化排序列表。
简化速率转换处理。
避免误报不同任务中关联模块的数据依存关系冲突。
代码生成结果实现高效的速率分组。
一个子系统可以属于多个任务中的不同排序列表。
直接馈通输入对执行顺序的影响
为了确保排序执行顺序反映模块之间的数据依存关系,软件根据模块输出对模块输入端口的依赖性对模块输入端口进行分类。如果某个输入端口的当前值确定了一个模块输出的当前值,则该输入为直接馈通输入。请参阅代数环概念。
具有非直接馈通输入的模块示例包括:
无直接馈通输入的模块示例包括:
确定模块执行顺序的规则
为了对模块进行排序,软件使用以下规则:
如果一个模块驱动另一个模块的直接馈通输入,则在执行顺序中此驱动模块必须显示在它所驱动的模块之前。
此规则可确保当软件调用需要当前输入的模块输出方法时模块的直接馈通输入是有效的。
如果一个模块驱动另一个模块的输入(该输入不是直接馈通输入),则这两个模块之间不存在数据依存关系,因此其相对执行顺序无关紧要。
以下模型说明这一结果。
Car Dynamics 虚拟子系统中的 Integrator 模块
1/s
没有直接馈通输入。因此,即使其输入连接到 Gain 模块1/m
,Integrator 模块的执行顺序仍排在 Gain 模块1/m
之前。Integrator 模块的输出驱动 Gain 模块b
的输入,因此 Integrator 模块的执行顺序排在该 Gain 模块之前。在根级模型中,Step 模块
step response
驱动 Sum 模块,因此 Step 模块的执行顺序排在 Sum 模块之前。Sum 模块驱动discrete cruise controller
非虚拟子系统的直接馈通输入,因此子系统的执行顺序排在 Sum 模块之后。
discrete cruise controller
非虚拟子系统被视为具有直接馈通输入的模块,因为其输出取决于通过名为 Kp
的 Gain 模块的分支的当前输入值。在子系统内部,所有具有直接馈通输入的 Gain 模块都在它们驱动的 Sum 模块之前运行。
用于确定包含异步任务的模型中模块执行顺序的规则
在仿真中,在确定任务中的模块排序顺序时,异步函数调用发起方具有最高优先级。有关详细信息,请参阅异步采样时间和Rate Transitions and Asynchronous Blocks (Simulink Coder)。
为了确定包含异步采样时间的模型中的模块执行顺序,软件使用以下规则:
如果异步函数调用发起方由对应的速率转换模块共享的离散速率触发,则在具有公共离散速率的任务中,异步函数调用发起方将排在执行顺序的最前面。
例如,在以下模型中,有一个异步函数调用发起方(一个 Async Interrupt (Simulink Coder) 模块),它由离散速率
D1
触发。在离散任务中,异步函数调用发起方排在执行顺序的最前面。Rate Transition 模块在异步速率A1
和离散速率D1
之间转换。如果 Rate Transition 模块缩减到
NoOp
,则 Rate Transition 模块不会执行,且在离散任务的排序顺序位置会转移到与其连接的上游或下游离散模块。例如,在上述模型中,
RTB2
缩减到NoOp
,因此它在排序顺序中的位置转移到下游 Gain 模块。如果两个异步函数调用发起方执行同一公共离散速率任务,则优先级较高的异步函数调用发起方在该离散速率任务中先执行。
例如,在以下模型中,两个异步函数调用发起方(两个 Async Interrupt (Simulink Coder) 模块)由同一离散速率
D1
触发。任务优先级高的函数调用发起方排在执行顺序的最前面。基于任务的排序不支持异步采样时间的并集。与多个异步采样时间的并集相关联的所有模块都在单个任务中进行排序。
例如,在以下模型中,具有相同 Simulink 任务优先级的两个异步函数调用发起方(两个 Async Interrupt (Simulink Coder) 模块)由相同的离散速率
D1
触发。在此模型中,Rate Transition 模块RTB1_Union
计算 U1 = union(A4 , A5). 与并集相关联的模块组合在Task 0
中。有关联合采样时间的详细信息,请参阅Union Rate,有关异步采样时间的信息,请参阅异步采样时间。
检查是否有涉及 Data Store Memory 模块的执行顺序更改
模型升级
使用基于任务的排序而不是原有(模块)排序可以更改涉及 Data Store Memory 模块的相对执行顺序。升级顾问检查会检测更改,并提供选项以允许在从 Simulink 早期版本升级模型时保持原始执行顺序。
打开升级顾问。在建模选项卡中,选择模型顾问 > 升级顾问。
选中检查 Data Store Read 和 Data Store Write 模块的相对执行顺序的复选框。
点击运行此检查。
查看结果表中的任何更改。如果您要保留原始执行顺序,请点击修改。
代码生成
为代码生成编译模型时,Data Store Read 和 Data Store Write 模块在生成代码中的相对执行顺序可能与在普通仿真模式下的顺序不同。模型顾问检查会检测这些差异,并提供选项来更改在普通仿真模式下的执行顺序,以匹配在生成代码中的顺序。
打开模型顾问。在建模选项卡上,选择模型顾问 > 按产品 > Simulink Coder。
选中检查 Data Store Read 和 Data Store Write 模块的相对执行顺序变化复选框。
点击运行此检查。
查看结果表中的任何更改。如果有差异列出,并且您要更改普通仿真中的执行顺序以符合生成代码中的执行顺序,请点击修改模块优先级。