K4-03 MIL/SIL/HIL 验证流程
课程代码 K4-03 · 板块 K 控制、软件与标定 / 嵌入式软件与开发 时长 约 4.0 小时(7 讲) 前置 K4-02 基于模型开发(MBD):Simulink 建模与代码生成;K2-01 热管理控制器(域控/ECU)硬件架构 本讲义定位 讲师授课蓝本 / 学员自学讲义,是 K4-03 大纲的完整展开版
按任务导航
| 你手上的事 | 直接看 | 还要配 |
|---|---|---|
| 审一份在环测试报告,判这句「通过」能不能当证据 | 第 1 讲:一句「通过」必须带的三项射程 | 第 6 讲(四类覆盖率互为补集)· 第 4 讲(模型版本与步长也是出口判据) |
| 评审一台热管理 HIL 台架的架构与注入能力 | 第 3 讲:按信号通路枚举组成、按异常层次枚举注入 | 第 4 讲(步长与保真度)· 第 5 讲(哪条用例靠哪格注入) |
| 定被控对象实时模型的步长与降阶 | 第 4 讲:RTF 与 τ_min 把步长推向相反方向,收敛试验定步长 | 第 3 讲(快信号为何不进主模型)· 第 7 讲(射程上限) |
| 编一份用例集并写出可判真假的判据 | 第 5 讲:四类工况、阈值边界三点取法、判定表补全再压缩 | 第 6 讲(未覆盖项四条分流)· 第 2 讲(ε 按信号分三档) |
| 分诊「HIL 过了、整车不过」的问题单 | 第 7 讲:成因表与分诊顺序,先证伪最便宜的两格 | 第 4 讲(模型射程)· 第 5 讲(那组合到底测没测) |
⛔ 本课不覆盖:建模、代码生成与定点化(→ K4-02 基于模型开发(MBD):Simulink 建模与代码生成)· ASIL 定级(→ K2-03 功能安全(ISO 26262)在热管理中的应用)· 降级策略本体(→ K5-02 热管理故障处理与降级策略)· 状态机静态核对(→ K4-05 模式状态机的完备性核对与可验证性设计)· 需求条目化与交接(→ K4-07 热管理控制功能规格(软件需求)的编写、评审与向 Tier1 交接)· 回归基线与激励库(→ K4-08 控制软件回归验证:基线与激励库、回归范围裁剪、自动执行与失败分诊)· 跨企业签署(→ K4-09 热管理控制软件的跨企业交付边界:交付物形态、DIA/SEooC、权限分级与联合验证签署)· 一维模型怎么建(→ J1-04 整车热管理系统级联合仿真)· 虚拟标定与 DOE(→ K6-13 虚拟标定:把标定动作前移到 MIL/SIL/HIL、自动寻优与回归标定 K6-01 热管理标定流程与工具(INCA/CANape) J7-03 基于仿真的 DOE 与多目标优化)· 环境舱与整车热平衡(→ K6-04 环境舱与整车热平衡标定);以及任何一个具体阈值取值——back-to-back 阈值 ε、覆盖率出口目标、RTF 工程裕量、τ_min 与步长取值、按 ASIL 分档那张结构覆盖推荐表的任何一格——它们由本项目验证策略与你手上那版标准给出,⛔ 本课一个数都不给,给的是反解链与判据结构。
引言:你说的「通过」,是什么意思的通过
一段控制策略从「模型里能跑」到「真装进 ECU 能用」,中间隔着 MIL、SIL、PIL、HIL 这一串在环关卡,一关比一关更接近真实硬件,也一关比一关更贵更慢。本课的输入是一份已经在 Simulink 里跑通、并且已经生成过代码的控制策略(K4-02 基于模型开发(MBD):Simulink 建模与代码生成 的交付物);输出是三样东西:一张验证形态与测试层级的二维排布表(哪一格测什么、出口是什么)、一套HIL 台架与被控对象实时模型的设计判据(架构、注入能力、步长与保真度)、一份用例设计方法与出口判据清单(四类覆盖率与未覆盖项处置)。
先说清这门课要解决的那个真实麻烦。工程现场最常见的争执,其实不是「测得够不够」,而是「你说的通过,是什么意思的通过」——同一句「HIL 过了」,在一个人嘴里指整包软件对需求规格的合格性验证,在另一个人嘴里可能只是某个模块在 HIL 上跑了两条冒烟用例;两份报告都写着「通过」,而它们根本不在回答同一个问题。这种争执谈不拢,不是因为谁不专业,是因为一份测试结论被当成了布尔值,而它永远带着射程。
射程由两件事划定:这一级换掉了哪一样东西,以及被控对象模型能表达出什么。全课两根钉子分别管这两件事,反复敲七讲。
钉子①:在环阶梯不是精度递进,是补集——每一级测的,恰恰是上一级测不到的那一类
把「各级各自换掉了什么」列成一张表,就能读出每一级独有的可测问题类:MIL 换的是算法逻辑本身(代码、芯片、电气环境三样都还不存在);SIL 换掉编译器与数据类型,测的是代码有没有偏离模型;PIL 换掉处理器,测的是目标芯片上的位精确性与单步任务的实测执行时间;HIL 换掉整个控制器硬件与电气环境,测的是真实 I/O、真实时序、真实供电下还成不成立。
关键在于这些集合互不包含。「SIL 全过,所以 HIL 只跑冒烟就行」这句话听起来合理,是因为它默认了「更真实=包含更简单」;而事实是更真实的那一级把简单那一级的被测对象整个换掉了。⇒ 三条推论要跟着走:
- 跳掉哪一级,不是「少测一遍」,是把那一整类问题原封不动推到它下一次会第一次暴露的地方——而那个地方越靠后越贵。代价的放大机制是可以说清的(同一个缺陷在 MIL 上改一次模型就完;到整车上改,要重新走一遍标定与验证),⛔ 具体倍数是项目相关量,本课不给。
- 「上一级全过」不构成下一级可以少测的理由——它们的射程不重叠。同理,「上一级发现的缺陷数少」也不能拿来论证下一级可以压缩:缺陷数少也可能是那一级根本测不到那类问题。
- 反过来也别读成「所以每一级都要跑全量用例」。正确推论是每一级跑它独有能测的那一类——用例按「这条用例要测的问题属于哪一级的独有集合」来派。
同一条补集逻辑在第 6 讲会原样复用一次:需求覆盖率、结构覆盖率、状态迁移覆盖、场景覆盖率也是四个补集。缺任何一类,那一类的问题不是「少发现一点」,而是整类不出现在报告里——报告上看不出任何异常,因为那一整栏根本没人填。
钉子②:HIL 上的「通过」,只在被控对象模型表达得出来的那部分物理里成立
HIL 台架上真实的只有控制器那一侧;被控对象是一个降阶后、按固定步长跑的实时模型。⇒ 模型里没有的动态,不会让任何一条用例失败。步长与降阶方案决定了这个射程有多大,所以它们是出口判据的一部分,⛔ 不是搭台架时的技术细节。这条直接决定三件事:
- 被控对象模型的步长与降阶方案,必须与测试规格一起评审、一起冻结、一起写进报告——两份报告若模型版本不同,它们的结论不可比,也不能互相引用。
- 用例数量不能补偿模型缺陷。用例越多,反而把「已充分验证」这个错误结论钉得越死:一千条全过的用例,和「这一千条恰好都没碰到模型缺的那个环节」,在报告上长得一模一样。
- 「HIL 过了、整车不过」不是台架无能的证明。它是一张可以逐格排查的成因表,而第一格必须先排除「其实那个组合根本没测」,⛔ 不许一上来就归因到模型保真度——那一格最贵、最难证伪。
反钉子:RTF ≤ 1 说明台架跑得起来,⛔ 说明不了步长合适
本课最容易被读反的一条是:「实时因子 RTF ≤ 1,就说明这个 HIL 模型的步长合适。」
它的前半截完全正确:RTF = 最坏一步的计算耗时 / 该步代表的物理时间,RTF ≤ 1 是由定义推出的硬约束(等于 1 就意味着算一步恰好用掉这一步代表的物理时间,超过 1 在物理上就是跟不上),⛔ 它不是谁定的经验要求。正因为前半截对、而且它是台架调试时第一个会报警、报得最响的指标,读者极容易把它当成步长这件事的唯一判据。
为什么它是反的:RTF 答的是「算得过来吗」,而步长真正要答的是「算得准吗」——关心的那个动态还在不在。这两条判据把步长推向相反的方向:RTF 要步长大,保真度要步长远小于 τ_min(本次验证要求表达出来的那些动态里最快的一个的时间常数)。可行域是两者之间那条窄缝,而只看 RTF 的人只看得见其中一侧的边界。⇒ 由此也定下一条方向性纪律:RTF 是可行性判据,⛔ 不得反过来用「RTF 很小」去论证保真度好。
读者会做错的那个具体动作:台架上 RTF 报超,他去把步长调粗——因为这是所有可选动作里最快、最不花钱、并且立刻见效的一个(换实时机要采购,简化模型要重新验保真度,降求解器阶数要重算)。调粗之后 RTF 立刻绿了,台架「达标」了,而他刚刚亲手滤掉的,正是这条回路里最快、最需要被看见的那个动态。⇒ 后果不是「精度差一点」,是台架从此对那一类问题永久失明,而所有指标都是绿的——这比台架跑不起来严重得多,因为跑不起来至少会被发现。
同一个病根还有三个更极端的形态,本课分别在第 4、6、7 讲各点破一次:「用例全过说明模型够用了」(方向反的——用例全过既可能是软件真的对,也可能是模型根本测不到它,两者在报告上长得一模一样)· 「偶发的失败复现不了,先关掉」(方向反的——在被控对象是确定性模型的台架上,复现率低本身就是一条指向模型缺环的信息,它该写进报告当证据,⛔ 不是关单理由)· 「覆盖率不好看,就把不好覆盖的那段防御性代码删掉」(方向反的——覆盖率是测量仪,删掉被测物让仪表好看,等于用鲁棒性换一个数字)。
⚠ 四者共享同一个病根:拿一个会报警、好看懂、调起来便宜的代理量,替换掉那个真正要答的、不会自己报警的目标量。
全课七讲怎么排
第 1 讲立坐标系:验证形态按「被测对象是什么 × 被控对象在哪」两轴画(一维阶梯图会把 RCP 摆错位置、并整类漏掉半实物在环),测试层级按「被测对象是软件的哪一层」画,两条轴正交——「跑在 HIL 上」⛔ 不等于「做的是合格性测试」。第 2 讲讲 MIL 与 SIL:back-to-back 要说清哪三件事,ε 为什么不能全信号取一个值。第 3 讲搭台架:按信号通路枚举的组成全集、三层时基、按异常层次枚举的注入能力,以及一条本课补的判据——台架自身的可信性要先立住,否则「注了没注上」与「注上了但没反应」在记录里长得一样。第 4 讲是全课唯一可手算的一块:降阶、RTF、步长可行窗与收敛试验、保真度不足的三种可分辨表现。第 5 讲设计用例:四类工况(第四类是无故障的纯资源竞争)、阈值边界三点取法、判定表、组合场景压缩、两类病理场景、用例来源全集。第 6 讲判出口:四类覆盖率的补集关系、分母口径、结构覆盖阶梯与档位、动态测试的原理性上限、未覆盖项的四条分流。第 7 讲收口到整车:射程上限、成因分诊、案例、回归编排与跨企业分工。
全课统一的口径,放在这里一次说清
后面各讲不再重复,遇到符号或口径存疑请回到这一段:
- 「通过」必须连同三项射程一起记账:① 在环形态(MIL/SIL/PIL/HIL/半实物)② 测试层级(单元/集成/合格性)③ 被控对象模型版本+步长+降阶方案。⛔ 报告与追溯链里不许只写「HIL 通过」。
- RTF 一律取最坏一步,且最坏必须在最坏分支+最重注入负载下取到;分子含模型求解、I/O 读写、总线收发、测量与记录的全部开销,⛔ 不只是求解器耗时。报告同时记最坏值与超时次数,⛔ 全课不出现「平均 RTF 达标」这种表述——超时一步就丢一步。
- 覆盖率一律带下标与档位,并同时给出分子分母的绝对条数。只写百分比会掩盖分母口径的变化;⛔ 不同档位、不同范围的覆盖率不得相加、不得求平均。
- 三组容易撞名的符号,本课这样约定:裸写的 Δ 只指 back-to-back 偏差 |y_code − y_model|,步长一律写全 Δt_HIL;C 一律带下标(C_th 是热容,单位 J/K;C_req、C_struct 是覆盖率,无量纲);ε 一律带信号类别下标(ε_cont / ε_disc / ε_time)。
- 台架侧与 ECU 侧的时间量在两个时钟域:Δt_HIL、RTF、实时机时间戳属台架侧,T_task(控制任务周期)、t_exec(单步实测执行时间)、ECU 时间戳属 ECU 侧,⛔ 两侧不得相加、不得直接比大小;要比较必须先声明同步方式。
- 标准版次一律写「以你手上那一版为准,引用前须核」,⛔ 不写「最新版」。⚠ 尤其 Automotive SPICE:3.1 与 4.0 两版并行流通,且 4.0 调整过过程域名称与工作产物编号 ⇒ 引用时必须显式声明所依版本,⛔ 不得混引。
读完这一节,你今天就能用的东西
拿到任何一句「通过」(自己团队的、Tier1 交来的、第三方台架出的),逐句问这四问;答不上来的那一句,不能被另一份报告引用,也不能当放行证据:
- 这一级换掉了哪一样东西?(→ 它只测得了那一类问题;答成「跑在 HIL 上」不算答案)
- 测的是软件的哪一层?(单元 / 集成 / 合格性——冒烟用例不能顶合格性验证)
- 被控对象模型是哪一版、步长多少、降掉了什么?(答不上来 ⇒ 这份结论的射程未知,⛔ 不是「射程很大」)
- 出口判据里除了覆盖率还有什么?(back-to-back 一致性、故障注入的降级响应符合性、台架自身的最坏 RTF 与超时次数、缺陷收敛趋势、追溯链完整性——只报覆盖率的报告,缺的那几栏不会自己喊出来)
这四问就是两根钉子的现场形态。后面七讲要做的,是把每一问背后的做法讲到能照着执行:第 1 讲让第 1、2 问有答案,第 3 讲与第 4 讲让第 3 问有答案,第 5 讲与第 6 讲让第 4 问有答案,第 7 讲告诉你四问都答上了、整车还是不过时,该按什么顺序往下查。
第 1 讲 一份「通过」从来不是布尔值,它永远带着射程
评审会上最贵的一句话是「这个我们在 HIL 上测过了,过了」。它听起来是一个结论,其实什么都没说:测的是软件的哪一层?被控对象模型是哪一版、多大步长、降阶掉了什么?跑的是几条冒烟用例,还是整包软件对需求规格的符合性?这三样有一样说不出来,这句「过了」就无法被第二个人引用——它既撑不起放行,也没法在出问题之后用来划定「哪些结论仍然成立」。工程现场最常见的争执,从来不是「测得够不够」,而是「你说的通过,是什么意思的通过」。这一讲不讲怎么搭台架、不讲怎么写用例,它只干一件事:把后面六讲要挂东西的那副坐标系立起来。坐标系有两条互相独立的轴——在环形态(这一级换掉了哪一样东西)与测试层级(测的是软件哪一层),再加一条贯穿全课的读法:各级之间是补集,不是精度阶梯。
本讲路线:先说清一份结论该带哪三项射程(1.1);把六种形态按两轴摆好、并说明为什么不能排成一条阶梯(1.2);逐格看 MIL/SIL(1.3)与 PIL/HIL(1.4)各自换掉了什么、于是各自独有地能抓到什么;把这一整块收进本课第一根钉子(1.5);立起第二条轴(1.6);安置那个不在阶梯上的形态 RCP(1.7);给出每一层都要留的四件工作产物(1.8);点破「HIL 测试通过」这行标题为什么不构成出口证据(1.9);最后补上一整格本课不讲、但不给它位置读者就一定会读错的东西——静态验证(1.10)。
本讲开头一次说清的三条记法与口径(后面各讲不再重复) ① 时间量分属两个时钟域,⛔ 不得相加、⛔ 不得直接比大小。台架侧的时间量(实时机的仿真步长、一步的计算耗时)跑在台架实时机的时钟上;ECU 侧的时间量(控制任务周期、单步实测执行时间 t_exec [s,工程上常用 μs])跑在 ECU 自己的晶振上。两侧要比较,必须先声明同步方式(共同时基或同步信号)——⚠ 这不是记法洁癖:没有共同时基,「谁先谁后」这一类时序结论就不可信,而台架上要不要单配这一格硬件,第 3 讲会正面回答。 ② 引外部标准与过程参考模型,一律写「以你手上那一版为准,引用前须核」,⛔ 不写「最新版」。特别地,本课要借用其层级划分的那套软件过程参考模型(Automotive SPICE)有 3.1 与 4.0 两版并行流通,且 4.0 调整过过程域名称与工作产物编号 ⇒ 引用时必须显式声明所依版本,⛔ 不得把两版的说法混着用(1.8 展开)。 ③ 本课全部时间量、阈值量与覆盖率目标都是平台相关量、⛔ 一律不给数,给的是取它的方法、反解链与判据结构。而坐标系本身与各级之间的补集关系与平台无关,是可以直接照抄去用的结构——这也是本课交付物里唯一不需要你先做实测就能用的那部分。
1.1 一份「通过」要能被别人引用,抬头必须写全三项射程
是什么。本课的输入,是一份已经在建模环境里跑通、并且已经生成过代码的控制策略(它是 K4-02 基于模型开发(MBD):Simulink 建模与代码生成 的交付物)。本课的输出是三样东西:一张验证形态与测试层级的二维排布表(哪一格测什么、出口判据是什么);一套台架与被控对象实时模型的设计判据(架构、注入能力、步长与保真度);一份用例设计方法与出口判据清单(四类覆盖率+未覆盖项的处置)。三样合起来回答同一个问题:你说的那个「通过」,管到哪里为止。
为什么。因为「通过」这两个字在被引用的那一刻会丢掉全部限定条件。同一句「HIL 过了」,在不同人嘴里可能指整包软件的合格性验证,也可能指某个模块在台架上跑了两条冒烟用例;两者都不算说谎,而把后者当成前者去放行,代价要到整车上才结算。⇒ 先立坐标系,后面五讲的每一条判据才有地方挂。
今天就能用的那一样:结论抬头的三项射程。本课要求任何一条「通过」在报告与追溯链里,必须连同下面三项一起记,⛔ 不许只写「HIL 通过」:
| 必写项 | 写什么 | 不写它会怎样 |
|---|---|---|
| ① 在环形态 | MIL / SIL / PIL / HIL / 半实物在环 | 读者不知道被测对象是模型、代码还是真实控制器,也就不知道哪一类问题原理上没被测 |
| ② 测试层级 | 软件单元验证 / 软件集成验证 / 软件合格性验证 | 一份集成层的执行记录会被当成整包软件的合格性证据(1.9) |
| ③ 被控对象模型版本+步长+降阶方案 | 版本标识、主模型步长、降阶掉了哪些环节 | 两份报告若模型版本不同,它们的结论不可比——而没人会发现,因为两边都写着「通过」 |
自检一句:把这三项遮住,剩下那句「通过」还说得清它管到哪里吗?说不清,这份报告就还没写完。第 ③ 项之所以是抬头的一部分而不是台架技术细节,理由在第 4 讲——模型的步长与降阶方案决定了这份「通过」的射程有多大,它必须与测试规格一起评审、一起冻结、一起写进报告。
易错点。① 把本课当成「HIL 台架操作手册」来读——具体工具链怎么点、怎么接线归工具供应商文档,本课交付的是判据;② 以为「验证」就等于「测试」——评审、静态分析、性质核对这一类活动同样是验证,但它们不在本课这条轴上(1.10 单独给它一格,本体去向 K4-05 模式状态机的完备性核对与可验证性设计)。
1.2 六种形态该按两轴摆,排成一条阶梯必然把 RCP 放错、把半实物漏掉
是什么。验证形态要按两条轴画:轴一=被测对象是什么(控制模型 → 主机上编译的生成代码 → 目标芯片上的生成代码 → 真实 ECU → 真实 ECU 加部分真实部件 → 整车),轴二=被控对象在哪(非实时模型 / 实时模型 / 真实物理)。六种形态在这副坐标里各占一格:
| 形态 | 被测对象是什么 | 被控对象在哪 | 这一格独有能抓到的问题类 |
|---|---|---|---|
| MIL | 控制模型 | 非实时模型 | 算法逻辑本身 |
| SIL | 主机上编译的生成代码 | 非实时模型 | 代码生成与定点化引入的偏差 |
| PIL | 目标芯片上的生成代码 | 非实时模型(PC 侧闭环) | 目标编译优化引入的行为差异、位精确性、单步实测执行时间 |
| HIL | 真实 ECU | 实时模型 | 真实 I/O 与电气、真实时序、供电 |
| 半实物/部件在环 | 真实 ECU + 部分真实部件 | 部分真实物理+实时模型 | 真实部件的非线性 |
| 整车/环境舱 | 装车状态的真实 ECU | 真实物理 | 线束、EMC、环境载荷、其它域的真实行为 |
| RCP(旁路标定/快速原型) | 外挂原型硬件 | 真车 | ⛔ 它不在这条阶梯上(1.7 单独讲) |
⚠ 把六格排成二维、以及「各级之间是补集」这个读法,是本课归纳的整理方式,⛔ 不是引自哪一条标准。
为什么不能排成一条阶梯。一维排法(MIL→SIL→PIL→HIL→整车)里藏着一个错误前提:「越靠后越真实,也越晚发生」。RCP 恰好是这个前提的反例——它最早发生,被控对象却最真实(就是真车)。一维图里它无处安放,于是要么被整个漏掉,要么被硬塞进阶梯中间、被误解成「HIL 的一种」。同一条线索还会整类漏掉半实物在环:它不在「MIL/SIL/PIL/HIL」这四个英文缩写构成的序列里,于是常被当成「HIL 的一个选配项」,而不是一种有自己射程、自己出口判据的独立形态。⇒ 只数「有英文缩写的那几个」,会漏掉半实物、漏掉整车这一格的定位,也会把 RCP 摆错。
工程量级。二维坐标本身没有数值。各形态的单次执行成本与周期是平台与供应商相关量、⛔ 本课不给数;但相对次序(越往右上越贵、越慢)与平台无关——图1 因此用一对无刻度的相对轴来表达,⛔ 图上不得据以比较任何两级的成本倍数。
易错点。① 把六个格子理解成「精度从低到高」——它们是补集不是精度阶梯,这正是 1.5 要钉的那件事;② 忘记 MIL、SIL、PIL 都可以跑在非实时环境里,于是把「实时」当成所有在环形态的共同属性,进而把实时因子与步长这一整套约束(第 3、4 讲)错误地套到 SIL 上——被套上之后最直接的后果是:本来可以无人值守整夜批跑的回归,被人为限制成「一小时工况跑一小时」。
1.3 代码这样东西,在 MIL 那一格还不存在,到 SIL 才第一次被测
MIL 测的是「算法逻辑本身对不对」。这一格里控制策略以模型形态运行,被控对象也是模型,两者在同一个仿真环境里闭环;被测对象是算法与参数,⛔ 不是代码——此时代码、芯片、电气环境三样东西都还不存在。这一格的独特价值在于它是唯一可以自由改结构的地方:发现逻辑错就直接改模型,不牵动代码生成、不牵动标定发布、不占台架。把一个逻辑错留到后面任何一格,改动成本都会跳一个台阶(跳法见 1.5)。
MIL 那条能立刻用上的排产判据。MIL 可以在普通工程机上批量跑,且不受实时约束——而 HIL 受实时约束,一小时的工况就要占一小时台架。⇒ 长时间尺度的工况(整日温度循环、多次充放电、长时序的仲裁饥饿用例)在 MIL 上做才划算;这一条直接决定一条用例该派到哪一层,⛔ 不是「越靠后越保险」。
MIL 的两个易错点。① 拿 MIL 的通过当成「算法已验证」并据此跳过 SIL——MIL 这一格里代码根本不存在,它没有能力测代码;② 在 MIL 阶段就去追求高保真的被控对象模型——MIL 的模型精度要求与 HIL 不是一回事(第 2 讲第一节讲清)。
SIL 测的是「生成的代码有没有偏离模型」。把代码生成器产出的目标代码在主机上编译后接进同一个仿真环境,与 MIL 用同一组激励对比两侧输出,偏差小于阈值判过——这条判定式怎么写、阈值按信号类别怎么分档定,第 2 讲展开。这一格里被换掉的是编译器、数据类型与执行顺序,⛔ 不是算法。
为什么这一格不能省。从模型到代码这一步会引入三类模型里根本不存在的东西:定点化的量化与饱和、数据类型转换、代码生成器为数值安全加的防御分支。这三类在 MIL 上原理上看不见——模型跑的是双精度浮点、跑的是求解器而不是定步长代码。⇒ 「MIL 过了所以代码没问题」这句话,缺的不是严谨,是被测对象。
SIL 的排产价值与两个易错点。SIL 同样不受实时约束、可以无人值守批量跑 ⇒ 它是回归测试的主力层(第 2 讲末节展开)。易错点:① 把 SIL 的「一致」理解成「正确」——SIL 只证明代码没有偏离模型,模型本身错了它一样一致;② 拿 SIL 剖出的执行时间当成 ECU 上的执行时间——那是主机 CPU 的时间,与车规 MCU 无关,那个数的来源只有下一格(资源与执行时间预算本体去向 K4-02 基于模型开发(MBD):Simulink 建模与代码生成)。
1.4 目标芯片与真实电气环境各自只在一格里出现,PIL 与 HIL 顶不了对方
PIL 补的是 SIL 与 HIL 之间最常被跳过的那一格。生成代码运行在目标处理器或评估板上,被控对象模型仍在 PC 侧闭环。它专测三类问题:① 目标编译器优化等级引入的行为差异;② 目标芯片上的位精确性(定点与浮点实现差异,衔接 K4-02 基于模型开发(MBD):Simulink 建模与代码生成 的定点化);③ 单步任务的实测执行时间 t_exec(对上 K4-02 基于模型开发(MBD):Simulink 建模与代码生成 的 ROM/RAM 与执行时间预算)。
为什么这三类只有这一格测得到。它们的共同点是只在目标芯片上才存在——主机 x86 与车规 MCU 的浮点实现、字长、优化策略都不同。跳过 PIL 的后果不是「少一层保险」:这三类问题会原封不动穿过 SIL,在 HIL 上以「偶发数值异常」或「任务偶尔超时」这种模糊形态第一次出现,而在 HIL 上没有任何工具能把它们与控制逻辑问题区分开——你只看得到一个现象,看不到它属于哪一类。
t_exec 这个量今天就能用的一条判据。它属平台相关量、⛔ 本课不给数;但下面这条与平台无关:t_exec 的唯一可信来源是 PIL 或目标端 profiling——主机上剖出来的数、按代码行数估的数、按算法复杂度推的数,一个都不算。⚠ 还要分清:PIL 上观测到的最大执行时间与最坏执行时间是两回事,前者是量出来的、后者要论证,⛔ 不得互相替代(本体去向 K4-02 基于模型开发(MBD):Simulink 建模与代码生成)。
PIL 的易错点。① 因为「HIL 上跑的也是真芯片,那 PIL 就不用做了」而跳过——HIL 上是整包软件在真实时序里一起跑,它测不出单个任务的执行时间构成,也无法在代码改动之后快速二分定位是哪一处变化引起的;② 把观测最大值直接写成最坏执行时间(同上)。
HIL 测的是「真实软硬件在真实电气环境下的表现」。真实 ECU 接实时仿真的被控对象模型,通过真实的传感器信号、执行器驱动、总线报文与供电闭环;被测对象是软硬件整体。这一格换掉的是整个控制器硬件、I/O 电路、总线与供电。
为什么这一整类只有 HIL 测得到。前三格里 ECU 的 I/O 是「一个数」;在 HIL 上它是一条有电平、有阻抗、有噪声、会开路会短路的物理通路。于是采样电路的量程与滤波、驱动级的保护动作、诊断对电气故障的判定、上下电时序、欠压行为——这一整类问题只有这一格测得到,前面三格里它们连发生的位置都没有。
HIL 的排产约束与两个方向相反的易错点。HIL 受实时约束 ⇒ 一小时的工况就要占一小时台架(为什么不能缩时,第 3 讲给出理由:ECU 跑自己的晶振时钟,缩时会把任务周期与滤波器时基一起缩掉),而台架是稀缺资源。⇒ 易错点① 把 HIL 当成「更真的 MIL」,把本该在 MIL/SIL 上跑的大批量回归堆到台架上,排期立刻成为整个项目的瓶颈;易错点② 反过来,因为 HIL 贵就把电气故障与上下电这一整类用例砍掉——而那恰恰是只有这一格能测的东西。⇒ 两个错误的方向相反,判据却是同一条:看这条用例要测的问题属于哪一格的独有集合。
1.5 五格是补集不是精度阶梯:「上一级全过」不构成下一级可以少测的理由
是什么。把「各级各自换掉了什么」列成一张表(1.2 那张表的最后一列),就能直接读出每一级独有的可测问题类:MIL=算法逻辑;SIL=代码生成与定点化引入的偏差;PIL=目标编译与位精确性、执行时间;HIL=真实 I/O 与电气、真实时序、供电;半实物=真实部件的非线性;整车=线束、EMC、环境与其它域的真实行为。这六个集合互不包含。
为什么「上一级全过」推不出下一级可以少测。「SIL 全过,所以 HIL 只跑冒烟就行」这句话之所以听起来合理,是因为它默默用了一个前提:更真实 = 包含更简单。而事实恰好相反——更真实的那一级把简单那一级的被测对象整个换掉了。SIL 测的是主机上编译的代码,HIL 测的是装在真实控制器里、跑在真实电气环境中的整包软硬件;两者的被测对象不是同一个东西,射程自然不重叠。⇒ 三条推论:
- 跳掉哪一级,不是「少测一遍」,而是把那一整类问题原封不动推到它下一次会第一次暴露的地方——而那个地方越靠后越贵;
- 「上一级全过」不构成下一级可以少测的理由——它们的射程不重叠;
- 反过来也不成立:某一级发现的缺陷数少,不等于那一层做得好,也可能是那一级根本测不到这类问题。
工程量级:代价怎么放大,⛔ 不给倍数。跳级的代价是项目相关量、⛔ 本课不给任何倍数,但放大的机制与平台无关,共四条,可以逐条对着自己的项目算:① 改动半径——在 MIL 上改一处模型,与在已发布版本上改代码并重跑标定、回归与合格性举证,动的东西不是一个量级;② 定位成本——越靠后,同一个根因表现得越模糊(1.4 那个「偶发数值异常」就是例子),排查要动的人越多;③ 排队成本——台架与整车是稀缺资源,每复现一次都要重新排期;④ 波及面——已经交付给下游或整车侧的版本要回收,追溯链上挂着的所有结论都要重新判还成不成立。⇒ 四条里没有一条与「精度」有关,它们全部与发现得多晚有关。
今天就能用的那一样:用例派发四问。拿到一条待测的问题类(缺陷的成因类别,⛔ 不是需求条目),按顺序问,第一个答「是」的那一格就是它该去的地方:
- 它依赖真实的电气与 I/O吗(电平、阻抗、开短路、供电、真实时序)?→ 是,派 HIL;
- 它依赖目标芯片的编译与字长吗(优化差异、位精确性、单步执行时间)?→ 是,派 PIL;
- 它依赖生成代码与模型之间的差异吗(量化、饱和、类型转换、生成的防御分支)?→ 是,派 SIL;
- 都不是 → 它是算法逻辑问题,派 MIL。
另有两条旁路:依赖真实部件的非线性→ 半实物在环;依赖线束、EMC、环境载荷与其它域的真实行为→ 整车/环境舱。
⚠ 这条「按问题依赖什么来派发」的分流判据是本课归纳的,⛔ 不是引自哪一条标准。它的下一个动作很具体:把用例集按这四问重排一遍,凡是排到 MIL/SIL 的长时序用例,从台架排期里摘出去;凡是排到 HIL 而当前只在 SIL 上跑过的,标成缺口。
易错点。把这条钉子读成「所以每一级都要跑全量用例」——⛔ 不是。正确的推论是每一级跑它独有能测的那一类;跑全量既买不到覆盖,还会把最贵的那一格排到瓶颈上去。
1.6 第二条轴:测试层级问的是「被测的是软件哪一层」,它与在环形态正交
是什么。坐标系的第二条轴有三格,每格有明确的被测对象与出口:
| 测试层级 | 被测对象是什么 | 出口是什么 |
|---|---|---|
| 软件单元验证 | 单个模块 | 单元用例通过 + 结构覆盖达到该功能对应的档位 |
| 软件集成验证 | 模块之间的接口与数据流 | 接口用例通过 + 集成缺陷收敛 |
| 软件合格性验证 | 整包软件对需求规格的符合性 | 需求覆盖率达标 + 合格性测试报告 |
为什么它与在环形态正交。这三层回答的是「测的是哪一层的正确性」,而在环形态回答的是「拿什么当被测对象、拿什么当环境」——两个问题互相独立。单元验证既可以在 MIL 上做,也可以在 SIL 上做;合格性验证既可以在 SIL 上做,也可以在 HIL 上做。⇒ 「跑在 HIL 上」这件事本身,一个字都没说测的是哪一层(1.9 展开这个错误最贵的那个形态)。
工程量级。三层的用例数量分布与被测粒度成反比——单元层用例多而短,合格性层用例少而长;这一条与平台无关,是分层的必然结果。具体条数是项目相关量、⛔ 不给数。
易错点。① 把两条轴压成一条,说出「HIL 测试」「SIL 测试」这种只说了形态、没说层级的话——评审时两边各自理解成不同的东西,而谁都不觉得对方说错了;② 以为三层之间有强制的先后关系——先后来自被测对象的可用性(模块得先有才能集成,整包得先集成完才能验合格性),⛔ 不是来自形态。
1.7 RCP 不在这条阶梯上:它的被控对象已经是真车,三条边界必须写死
是什么。策略还没进量产 ECU 时,用外挂原型硬件旁路量产 ECU 的目标功能,在实车上边跑边在线改参数——这是软件开发与实车验证并行的唯一手段。在 1.2 那副坐标里,它落在「被控对象=真车、被测对象=外挂原型硬件」这一格,与 HIL 恰好在对角线的两端。
为什么它解决的是时间问题而不是覆盖问题。整车路试的窗口有限,等量产软件成熟了再上车,会把开发周期串起来;RCP 把这两段并行掉。⇒ 它买到的是日历时间,⛔ 不是验证覆盖——它的被测对象根本不是量产软硬件。
今天就能用的那一样:三条边界,写进方案里,⛔ 不靠默契。
- bypass 只接管被旁路的那一部分功能,其余功能仍由量产 ECU 执行 ⇒ 结论只对被接管的那一块成立;方案里要画出这条边界在哪,⛔ 不许含混说「整车上验过了」。
- 旁路上标出的参数不进量产标定数据的主线——它们是在另一套硬件、另一套时序上标出来的。
- 这些值只能当量产软件的标定初值,⛔ 不得直接作为放行结果;下游怎么承接,去向 K6-01 热管理标定流程与工具(INCA/CANape)。
工程量级。原型硬件的算力与接口能力通常明显强于量产 ECU ⇒ 在 RCP 上跑得动的策略,不代表量产 ECU 跑得动;这一条与具体型号无关,成立的原因是两类硬件的定位不同。真正的可行性证据是目标端的资源与执行时间预算(去向 K4-02 基于模型开发(MBD):Simulink 建模与代码生成,量的来源是 1.4 那一格)。
易错点。① 把 RCP 上验过的策略当成「实车已验证」,据此压缩 HIL 与整车验证——被测对象不是量产软硬件,这条结论没有落点;② 把 RCP 标出的参数直接写进发布件——边界 ② ③ 同时被跨过,而且追溯链在这里断掉:这些值来自哪一次试验、哪一版策略、哪一套硬件,事后谁都说不清。
1.8 三层各留同一套四件工作产物,缺一件其余三件的价值就塌掉
是什么。1.6 那三层,与 Automotive SPICE 里的三个软件测试过程域一一对位——单元验证、集成验证、合格性验证分别对应 SWE.4/SWE.5/SWE.6。⚠ 这里给的是去向而不是条款:本课未取得标准原文,来源等级=转述 ⇒ ⛔ 本课不写各版过程域的条款内容、编号细节与工作产物名称的逐条对照,⛔ 也不把这些标识当成「必须这么做」的条款去背;而且 3.1 与 4.0 两版并行流通、4.0 调整过过程域名称与工作产物编号 ⇒ 要用它,请查你手上那一版并在报告里写明版本。
每一层要留的工作产物是同一套四件:
| 工作产物 | 这一层的它具体是什么 | 缺了它,塌掉的是什么 |
|---|---|---|
| 测试规格 | 这一层测什么、不测什么、出口判据与判定方法 | 用例的取舍依据不可追——评审只能问「为什么没测 X」,问不出「你按什么取的点」 |
| 测试用例集 | 逐条用例:前置条件、激励、期望、判定 | 结论无法复跑,别人重做一遍得不到同一个结果 |
| 测试结果记录 | 每次执行的输入、输出、通过与否、执行环境 | 通过与否不可复核;出问题后说不清当时到底跑没跑 |
| 与需求条目的双向追溯链 | 需求→用例、用例→需求,两个方向都要能查 | 需求一变更,说不出哪些用例要重跑 |
为什么第四件必须是「双向」。只有「需求→用例」这一个方向时,你能回答「这条需求测了没」,但回答不了反向那个问题:「需求改了,哪些用例作废、哪些要重跑」。而这正是「测试矩阵长期不随需求变更更新、覆盖率数字失真」这个毛病的机制——不是没人负责,是查不出来。⇒ 追溯链是不是双向的,一句话就能验:随手挑一条需求,问它被哪几条用例覆盖;再随手挑一条用例,问它对着哪几条需求。两个方向有一个答不上来,第四件就没建成。
版本声明这条口径落到这里的具体动作。引用过程参考模型的任何一处(层级划分、产物清单、过程域标识),报告与测试规格里必须显式写明所依版本;两版的名称与工作产物编号不同,⛔ 不得混着用。⛔ 一律不写「最新版」这种会过期的表述,写「以你手上那一版为准,引用前须核」。
易错点。① 把过程域标识当条款去背——它是过程参考模型,本课只借它的层级划分与产物清单;② 把「能力等级怎么定、评估怎么做」也往这里塞——那是另一门课的射程,去向 K4-04 软件版本、配置与变量管理,⛔ 本课不讲。
1.9 「HIL 测试通过」这行标题,本身不构成任何出口证据
是什么。这是两条轴被压成一条之后,最贵的那个具体形态:某个模块在 HIL 台架上跑了几条用例,结果全绿,报告标题写「HIL 测试通过」;三个月后这份报告被引用成「软件已通过验证」,出现在放行材料里。
为什么它撑不起那句引用。「HIL」这三个字母只说明被测对象是真实 ECU、环境是实时仿真的被控对象模型;它一个字都没说测的是单元、集成还是整包软件对需求规格的符合性,也没说出口签的是哪几类覆盖率,更没说被控对象模型是哪一版、什么步长。⇒ 关键在于:这份报告本身可能完全合规(作为一次集成验证的执行记录,它该有的都有),错的是引用它的人——而引用的人没有任何线索能发现自己引错了,因为报告上确实写着「通过」。
今天就能用的两张自检。
出报告的一侧:抬头三项写全(形态 + 层级 + 被控对象模型版本与步长,见 1.1),并在结论句里带上层级——写「本次集成验证在 HIL 形态下执行,结论适用于……」,⛔ 不写光秃秃的「HIL 测试通过」。
引用别人报告的一侧:三问,任一答不上来就退回去要,⛔ 不许自行脑补——① 这份报告的层级是什么?② 被控对象模型是哪一版、什么步长、降阶掉了什么?③ 它签的出口判据是哪几条?三项在跨企业交界处尤其要问清,那里的证据链最容易断(分工与签署的定位在第 7 讲,本体去向 K4-09 热管理控制软件的跨企业交付边界:交付物形态、DIA/SEooC、权限分级与联合验证签署)。
易错点。① 以为只要在标题里注明「HIL」就够了——形态是三项里的一项,⛔ 不能顶替另外两项;② 反过来,因为怕被误引就干脆不出中间报告——⛔ 不对。正确做法是报告照出,三项射程写全:中间报告本身是集成层的合法工作产物(1.8 第三件),不出它反而会让追溯链缺一环。
1.10 静态验证根本不在这条轴上,⛔ 不给它一格,读者就会把「覆盖率跑满」读成「完备」
是什么。评审、静态分析、形式化性质核对这一类活动,被测对象同样是软件,但它们不跑——不需要激励、不产生执行记录、也不产生覆盖率。它们与本课整条轴(动态测试)是补集关系。⚠ 把它单独列成一格,是本课补的,⛔ 不是引自哪一条标准;本课只声明这一格存在并说清补集关系,本体去向 K4-05 模式状态机的完备性核对与可验证性设计(模式状态机的静态完备性核对)与 K4-02 基于模型开发(MBD):Simulink 建模与代码生成(静态分析与规范类告警),⛔ 本课不重讲。
为什么不给它位置就会读错。动态测试有一条原理性上限:它只能发现「跑到了但结果不对」,发现不了「这个组合从来没被写进规则表」。一条从没被写下来的规则,不会在任何一条用例里失败——它不产生失败,它产生沉默;而覆盖率反而可能很好看,因为写下来的那些分支全跑到了(第 6 讲展开这条上限,以及它对迁移覆盖率分母的直接影响)。⇒ 如果坐标系里没有这一格,读者会顺理成章地把「四类覆盖率全达标」读成「完备」,而这两句话之间隔着一整类查不出来的问题。
今天就能用的那一样:两类证据分账。静态分析报出的告警与动态测试发现的缺陷不进同一本账——两者的性质与处置流程都不同:前者是「这段代码可能有问题」,处置是逐条判定为真问题或书面判定不适用;后者是「这次执行的结果与期望不符」,处置是定位、修改、复跑同一条用例。⇒ 混进一本账最直接的后果是缺陷收敛曲线失真:一批被判定为不适用的静态告警会把趋势拉得很难看,或者反过来,真缺陷被淹在告警堆里。
易错点。① 把静态分析告警当成「测试发现的缺陷」记进同一本账(上一段);② 以为形式化性质核对可以替代动态测试——反过来也不成立:静态核对证明不了「实现与需求一致」,动态测试证明不了「该有的规则都写了」。⇒ 这两句话正是「补集」这个词在这里的全部含义:缺哪一侧,缺的都不是一点点精度,而是一整类问题不出现在任何报告里。
后面还有 6 讲正文 · 关键公式 · 案例拆解 · 常见误区 · 动手做