--- name: simulink-rtl-redev description: > 改动原生模型(xxx_h.slx)之后,如何保证仿真模型(xxx_hs.slx)同步、仿真结论仍然算数。 典型触发场景:Vivado 综合时序不满足要改流水、硬件调试发现问题要改 RTL、定点位宽调整。 核心:生成脚本不会把原生核的改动翻译成 m 代码,只改一侧 = RTL 已变而仿真还在验证旧行为。 提供两个工具:同步新鲜度闸门 check_sync.py(三条时序链,退出码即结论)、 延迟实测 measure_k.m(时域/频域/包络三个估计器互证,不一致返回 NaN 而非猜测值)。 另含改动分类、验证三步、环内/环外加流水的差别、六条禁令。 触发词:改了原生模型、同步仿真模型、xxx_h 和 xxx_hs 不一致、时序违例改流水、 硬件调试改RTL、仿真模型过时、等价闸门、cycle-true 同步、check_sync、measure_k、 测延迟、K 是多少、加流水延迟多少拍、原生模型 仿真模型 双轨、改完怎么验、 makehdl 之前要做什么。 规范全文见工程 Notes/Task16-3.md。适用于任何"原生模型+仿真模型"双轨结构的工程。 --- # simulink-rtl-redev — 原生模型改动后的仿真模型同步 ## 这个 skill 解决什么 两个模型描述同一段算法: | 记号 | 名称 | 内容 | 用途 | |---|---|---|---| | `xxx_h.slx` | 原生模型(-e) | 目标模块全部用可综合原生块搭建 | **生成 RTL** | | `xxx_hs.slx` | 仿真模型(-x/-q) | 由原生模型派生,跑不动的**原生核**换成等价的 **m 实现** | **跑场景仿真** | **核心原则:改了原生模型,必须同步改仿真模型,并重新验证两者行为一致。** 原因:从原生模型派生仿真模型的脚本只做"摘掉原生核、换上 m 实现、接线", **它不会把原生核的改动翻译成 m 代码**。只改原生模型再重跑生成脚本, 仿真模型不会跟着变——它只是把同一份未改动的 m 实现重新包一遍。 后果:**RTL 已经变了,而仿真还在验证旧行为**。板上出问题时仿真给不出线索, 因为它测的根本不是同一个设计。 ## 什么时候需要手工同步 只看改动落在哪里: | 改动位置 | 是否需要手工同步 m 实现 | |---|---| | **原生核之内** | **需要**。这是两套实现的重叠区 | | 原生核之外(其余链路) | 不需要。生成脚本原样继承,重生成即可 | ## Agent 路径:先跑闸门 任何时候怀疑"仿真结论还算不算数",第一件事是跑同步新鲜度闸门。 ### 一次性:写 manifest 在工程里建一份 manifest(建议放 `Notes/sync_manifest_.json`), 声明这个模型的源与派生产物。**`root` 相对 manifest 所在目录**,其余路径相对 `root`: ```json { "model": "", "root": "..", "native_model": "matlab//xxx_h.slx", "build_scripts": ["matlab//build_core.m"], "gen_scripts": ["matlab//make_sim.m"], "mcode_impl": ["matlab//core_mcode.m"], "runtime_deps": ["matlab//pscore.m", "matlab//coef.mat"], "sim_model": "matlab//xxx_hs.slx", "rtl_source_model": "matlab//xxx_h__E.slx", "gate_result": "Notes/gate_.txt", "gate_tools": ["matlab//gate.m", "matlab//cmp_core.m"] } ``` `runtime_deps` 必填**运行时才从路径解析的 .m** 与运行时读取的数据文件 (`.mat`、系数表、数据字典)。改它们时模型本身一个字节都不变,漏列等于没查。 `rtl_source_model` 与 `gate_tools` 可省(省了就不查对应项)。 ### 每次改完模型:跑闸门 ``` cd <工程根> python "%USERPROFILE%\.claude\skills\simulink-rtl-redev\check_sync.py" Notes\sync_manifest_.json ``` Linux/macOS 把路径换成 `~/.claude/skills/simulink-rtl-redev/check_sync.py`。 **退出码即结论**:`0` 通过,`1` 有过时产物,`2` manifest 有问题(路径不存在等)。 可直接串进脚本做前置门禁。 选项:`--quiet` 不打印文件清单,`--json` 输出机器可读结果。 它查三条时序链: ``` 链 1(派生新鲜):max(源文件) < min(派生产物) 链 2(闸门新鲜):max(派生产物) < 闸门结果 链 3(工具新鲜):max(闸门工具) < 闸门结果 ``` **链 1 是最容易漏的那条。** 只查"闸门晚于全部源文件"会放行下面这种情况: 闸门确实在改完源之后跑的,但仿真模型停留在改动之前。本工具在真实工程上正是这样 抓出了一个已存在的漂移——链 2、链 3 都 PASS,只有链 1 FAIL。 ## 同步流程 ``` [1] 改原生实现(改构建脚本,不直接手改 .slx) | [2] 把同样的改动落到 m 实现 <-- 漏掉这步是本 skill 存在的理由 | [3] 重新生成仿真模型 | [4] 若改动带来延迟变化:先实测新增拍数 K | [5] 跑等价闸门 --> 原生核 与 m 实现 是否一致 | [6] 跑短程冒烟 --> 链路是否还通 | [7] 跑全场景全长 --> 对照基线,指标是否达标 | [8] 从原生模型生成 RTL ``` 任一步不过,回到 `[1]` 重走,不要从中间插入——仿真模型一旦重生成,后面的结果全部作废。 **`[4]` 必须在 `[5]` 之前**:延迟变了,闸门比对要带偏移,K 没测出来这一步做不了。 跑完 `[3]` 之后、进 `[5]` 之前,先用 `check_sync.py` 确认新鲜度,能省掉一次白跑的闸门。 ## 三类改动的差别 | 类别 | 例 | m 实现要改吗 | 延迟 | 场景判据 | |---|---|---|---|---| | **不改延迟** | 资源共享、块重构、常量折叠 | 通常不用 | 不变 | 与基线**逐位相同** | | **改延迟** | 插流水寄存器 | 补等量延迟 | +K | 吸收 K 后与基线**逐位相同** | | **改定点** | 位宽、二进制点、饱和/舍入 | **必须改** | 不变 | 行为已变,**重新定性并建立新基线** | - **延迟必须实测,不能按设计意图推算。** 用 `measure_k.m`(下节),至少两种互不依赖的方法测出一致值。 - **在反馈环内插流水,代价远大于环外。** 环外只是一个可被注入侧参数吸收的常数延迟; 环内会改变环路群延迟,必须重新定标环路参数(步长、移位、门限),并先在单元台验证 阶跃响应再上全链。**能搬到环外就搬到环外。** ## 实测新增延迟 K:`measure_k.m` 流程 `[4]`。B 类(加流水)改动必须先测 K 才能进 `[5]`——闸门的判据本身要用 K 作偏移。 ```matlab addpath(fullfile(getenv('USERPROFILE'),'.claude','skills','simulink-rtl-redev')); [K, R] = measure_k(ref, dut); % ref/dut 为实数或复数 IQ 向量,同采样率 ``` `ref` 是改动前(或参考抽头)的信号,`dut` 是改动后(滞后 K 拍)的信号。 返回 `K` = 认定的整数延迟,**方法不一致时返回 `NaN`**,不给猜测值。 `R` 里有各方法的分项结果。可选参数:`'MaxLag'`(4096)、`'OnsetTol'`(1e-3)、 `'FracTol'`(0.05)、`'Verbose'`(true)。**只用基础 MATLAB**,不依赖 Signal Processing Toolbox。 三个估计器,前两个域完全不同、始终可用,第三个仅在信号有静默前导时适用: | 方法 | 域 | 说明 | |---|---|---| | 1 互相关 argmax | 时域 | 整数 | | 2 互谱相位斜率 | **频域** | 分数;纯延迟使 `angle(Y·conj(X))` 对频率成直线,斜率即 −K | | 3 起始点差 | 幅度包络 | 整数;阈值取各自**峰值**的比例,故 DUT 的噪声底不会误触发;连续激励信号判 `n/a` 而非失败 | 判据:方法 1 与 2 必须一致;方法 3 适用时也必须一致;插值峰距整数不超过 `FracTol`。 **为什么非要两种。** 实测:两路**完全无关**的信号,相关器照样给出 `K = 241` (|rho| 仅 0.0198 的假峰)——单靠它会把一个纯噪声峰当成延迟。方法 2 给出 −26.350, 两者互不相认,工具才判 FAIL。这就是"至少两种互不依赖的方法"的全部理由。 实测过的六种情形: | 情形 | 结果 | |---|---| | 干净整数延迟 40,复数 IQ | PASS,3 法一致 | | 增益 0.37× + 全程噪声底 | PASS,2 法一致(方法 3 自动判 n/a) | | 连续激励无静默段,延迟 17 | PASS,2 法一致 | | **分数延迟 12.5 拍** | **FAIL**:方法 1 给 13、方法 2 给 12.500,且插值峰偏离整数 0.5 | | **两路无关信号** | **FAIL**:241 vs −26.350 | | 真延迟 40 + 3 阶非线性失真 | PASS,2 法一致(\|rho\| 0.989) | 分数延迟那一条尤其要留意:它说明改动**没有引入干净的整数流水延迟**(碰到了分数内插/重采样 路径)。这时不能四舍五入接着走,要回去查改的是不是环内。 ## 等价闸门的语义(极易搞错) 闸门比对的是**原生核与 m 实现这两套实现**,不是"新行为与旧行为"。因此: - 闸门对**所有类别**的改动都必须跑,判据都是"一致"; - 即使行为相对上一版变了,只要两侧按同样意图改完,**两套实现对新行为的描述仍必须一致**; - 改完两侧仍不一致,说明两边理解有分歧——这正是闸门要抓的。 **不要以"行为变了"为由跳过闸门。** 跳过它就等于放弃了对双实现是否同步的唯一检查。 闸门的局限:它只证明"在所用激励下一致",不证明全状态空间等价。 状态机边界、饱和、复位时序这类角落必须补定向用例,不能指望随机激励覆盖到。 ## 六条禁令 | # | 规矩 | 理由 | |---|---|---| | 1 | 仿真模型是**产物**,不能手改;要改就改生成脚本再重生成 | 手改必被下次重生成冲掉,git 上无法溯源 | | 2 | 只改一侧的改动**视为未完成**,不得进入验证 | 两套实现已分叉 | | 3 | 没跑过闸门,**不得跑场景仿真,也不得生成 RTL** | 前者测的可能是旧设计,后者错误直接进硅 | | 4 | 旧结果**永不覆盖**,每次运行带唯一标签、落唯一目录 | 失败记录是"改动前后对比"的另一半;陈旧编译缓存会静默复现旧结果 | | 5 | 判据不得为了通过而修改 | 一条带机理分析的 FAIL,价值高于一个来路不明的 PASS | | 6 | 时序违例优先改模型,**禁止**用多周期豁免放宽慢角富余路径 | 布线器会吃满被放松的预算,表现为"报告通过、板上异常" | ## Gotchas - **时间戳只是权宜之计。** `copy`/`touch`/版本签出都会扰动 mtime。 `check_sync.py` 因此只能作自查,不是证明。更可靠的做法是让生成脚本与闸门自动记录 所用源码的校验和,运行前比对不符即拒绝开跑——那属于工具建设,本 skill 不含。 - **"闸门比全部源文件新"不等于没问题。** 这正是链 1 存在的理由,见上文。 - **`runtime_deps` 漏列 = 没查。** 运行时解析的 .m 和 `.mat`/系数表改动时, 模型校验和纹丝不动。这类依赖必须显式声明,工具无法自动发现 (`load('x.mat')` 这种字符串依赖追不到)。 - **manifest 里每个声明的路径都必须存在**,否则 exit 2。这是故意的: 路径写错而静默跳过,比报错危险得多。 - **exit 2 与 exit 1 含义不同**:2 是 manifest 坏了(你的配置问题), 1 是真的有过时产物(你的工程问题)。串脚本时别把两者混为一谈。 ## Troubleshooting | 症状 | 原因 / 处置 | |---|---| | `ERROR: manifest refers to something that is missing -> : ` | 该路径不存在。exit 2。检查 `root` 与相对路径;`root` 是相对 manifest 所在目录的 | | 链 1 FAIL | 派生产物早于源。**先**把原生核改动落到 m 实现,**再**重生成,**再**重跑闸门。只重生成不同步 m 实现无效 | | 链 2 FAIL | 闸门跑在当前派生产物之前 —— 重跑闸门 | | 链 3 FAIL | 闸门工具在记录的通过之后改过 —— 重跑闸门 | | 三条链全 PASS 但板上仍与仿真不符 | 新鲜度没问题,问题在别处:查闸门覆盖(定向用例是否覆盖到出问题的状态),或查 `runtime_deps` 是否漏列 | | `ERROR: manifest declares no sources / no derived products` | manifest 缺 `native_model` 一类的键,或值是空列表 | ## 规范全文 本 skill 是 `Notes/Task16-3.md` 的可执行化。规范原文(含制定过程与十轮评审纠正的 逻辑错误)见该文档;本 skill 只承载执行路径与工具。