4. 为静态分析准备Stateflow模型

Polyspace对Stateflow的分析结果,很大程度上不取决于分析引擎本身,而取决于模型在进入分析前被"塑造成什么样子"。同一份Stateflow逻辑,如果求解器配置、代码生成目标、属性检查器选项和建模规范不同,Polyspace可能给出完全不同的告警集合:有的告警是真实缺陷,有的则是配置不当引入的噪声。本节围绕四类准备工作展开——模型配置参数、代码生成目标设置、Stateflow属性检查器关键选项,以及影响分析结果的建模规范。

一、模型配置参数:先让模型"可被分析"

Polyspace分析Stateflow时,实际处理的是由模型生成的代码或中间表示,因此求解器与仿真配置会直接影响分析输入。需要重点确认的参数包括:

  • 求解器类型与步长:Stateflow中的连续状态或与Simulink连续模块耦合时,求解器选择会影响生成代码中的积分与时间推进逻辑。若模型本身是纯离散逻辑,应显式设置为固定步长离散求解器,避免Polyspace在分析中引入不必要的浮点积分路径。
  • 固定步长大小:步长决定了生成代码中采样周期的常量值。步长设置过小可能使某些计数器或时间判断在分析中被判定为"永不满足"或"溢出风险",需要在分析前与实际部署周期对齐。
  • 采样时间与任务周期:Stateflow图表若继承采样时间,需确认其与Simulink模型的周期一致;若图表显式指定采样时间,应检查是否与目标ECU任务周期匹配。
  • 数据类型与目标字长:模型配置中的硬件实现参数(如char、short、int、long的位宽)必须与目标编译器一致,否则Polyspace按默认字长分析时,整型溢出、移位、类型转换类告警会与实际不符。

一个常见做法是:在分析前用Simulink.BlockDiagram.getChecksum或配置集比对,确认分析所用配置与代码生成配置一致。若不一致,Polyspace的结论不能直接用于代码质量判定。

二、代码生成目标设置:让分析对象与交付物一致

Polyspace分析的是生成代码,因此代码生成目标设置决定了"分析什么"。关键设置包括:

  • 系统目标文件:选择ert.tlc(Embedded Coder)还是grt.tlc(通用实时目标),会显著改变生成代码的结构。嵌入式目标通常生成更紧凑、更接近手写代码的形式,更适合做MISRA等规范检查。
  • 语言标准:C99与C90在声明位置、复合字面量等方面不同,Polyspace的解析器需与目标语言标准一致,否则会出现语法层面的误报。
  • 代码风格与标识符:是否启用可复用子系统代码、是否内联参数、标识符命名规则,都会影响Polyspace对函数边界和变量作用域的判定。
  • 浮点与整型运算:是否允许浮点、是否使用定点,直接决定分析中数值范围推导的路径。
建议在分析前固定一份"分析专用配置集",将代码生成目标、语言标准、硬件实现参数冻结,避免每次分析因配置漂移产生不可复现的告警差异。

三、Stateflow属性检查器中的关键选项

Stateflow属性检查器(Model Advisor中的Stateflow Checks或图表属性中的诊断设置)是控制Stateflow语义严格程度的核心。对Polyspace分析影响最大的选项包括:

  • 状态动作中的变量初始化:若允许未初始化即使用,Polyspace会报"未初始化变量"告警;若强制初始化,则需在建模时补齐,否则分析无法通过。
  • 转移冲突与默认转移:属性检查器可检测互斥转移、默认转移缺失等问题。这些在Polyspace中可能表现为不可达代码或死逻辑告警。
  • 循环与递归限制:Stateflow中的循环上限、递归调用限制会影响Polyspace对最坏执行路径的推导。若设置过宽,可能掩盖真实的栈溢出风险。
  • 数据类型传播:是否允许隐式类型转换、是否强制显式类型,直接影响Polyspace对类型不匹配、精度损失的判定。
  • 数组越界与索引检查:属性检查器中的数组范围检查若关闭,Polyspace可能无法识别越界访问,导致漏报。

实际操作中,建议在Model Advisor中运行"Stateflow Check"相关检查项,将结果与Polyspace告警做交叉比对:属性检查器报出的问题,往往正是Polyspace告警的根因。

四、影响分析结果的建模规范

建模规范不是"风格问题",而是直接决定Polyspace能否给出有效结论的前提。以下规范对分析结果影响最直接:

  • 避免在Stateflow中使用未定义行为:如除零、有符号整型溢出、移位超过位宽。这些在Polyspace中会被明确标记,但若建模时已存在,分析只能报告而不能修复。
  • 显式声明数据类型与范围:为每个数据对象指定类型、上下限,Polyspace才能进行精确的范围分析。未指定范围时,分析会退化为保守估计,产生大量误报。
  • 保持状态机结构清晰:避免过深的层次嵌套和大量并行状态,否则Polyspace的状态空间爆炸会导致分析超时或结果不完整。
  • 统一命名与作用域:局部变量、输出、参数的作用域应明确,避免同名变量在不同层级中含义不同,导致Polyspace误判数据流。
  • 避免动态类型与隐式转换:Stateflow中若大量依赖隐式类型转换,Polyspace的类型推导会变得不稳定,告警可信度下降。

下面这张图概括了从模型配置到Polyspace分析结果的完整准备链路,以及四类准备工作各自影响的分析维度。

Stateflow模型静态分析准备链路 模型配置参数 求解器 / 步长 / 字长 代码生成目标 ert.tlc / C99 / 标识符 属性检查器选项 初始化 / 转移 / 类型传播 建模规范 范围 / 层次 / 作用域 Polyspace 分析输入 生成代码 / 中间表示 类型与范围信息 状态空间结构 配置集快照 数值范围告警 溢出 / 除零 / 精度损失 控制流告警 不可达 / 死逻辑 / 冲突 数据流告警 未初始化 / 越界 / 类型不匹配 规范符合性告警 MISRA / 编码规则 配置漂移检测与告警基线比对 配置集冻结 → 分析 → 差异定位 → 修正模型或配置 准备阶段 分析阶段 结果判读阶段

从图中可以看出,四类准备工作并非孤立:模型配置参数决定分析输入的"物理属性",代码生成目标决定分析对象的"代码形态",属性检查器选项决定语义严格程度,建模规范决定分析能否收敛到有意义的结论。任何一环缺失,都会使Polyspace的告警集合偏离真实质量状况。

五、一份可执行的分析前检查清单

将上述内容整理为一份可直接使用的检查清单,建议在每次提交Polyspace分析前逐项确认:

检查项 确认内容 不满足时的风险
求解器与步长 离散模型使用固定步长,步长与ECU任务周期一致 浮点积分路径引入误报,时间判断失真
硬件字长 char/short/int/long位宽与目标编译器一致 整型溢出、移位类告警与实际不符
代码生成目标 使用ert.tlc,语言标准与目标一致 代码结构与交付物不一致,规范检查失效
属性检查器 变量初始化、转移冲突、类型传播选项已确认 未初始化、不可达逻辑漏报
数据范围 关键数据对象已指定上下限 范围分析退化为保守估计,误报激增
状态机层次 嵌套深度与并行状态数量在可控范围 状态空间爆炸,分析超时或结果不完整
配置集冻结 分析配置与代码生成配置一致且已记录 告警不可复现,无法做基线比对
若分析结果中出现大量"未初始化变量"或"不可达代码"告警,应优先回到Stateflow属性检查器和建模规范中排查,而不是直接修改Polyspace分析选项。配置层面的"消音"会掩盖真实缺陷。