Files
skills-win/simulink-rtl-redev/SKILL.md
T
bowei ea4541ee90 sync: SHANGHAI-U9 2026-07-27 三个 Simulink→RTL skill 转系统级 + 新增 simulink-rtl-redev
- simulink_rtl_dev / rtl-ip-replace: 从工程级 .claude/skills 迁到用户级并去工程耦合
  (模型名/Notes 文档依赖/工程实测基线移出; addpath 与脚本路径改用户级)
- rtl-ip-replace/scripts/gen_cmp_tb.py: Vivado 路径不再写死, 改读 VIVADO_PATH /
  XILINX_VIVADO (兼容 install root / bin / bin\vivado.bat 三种写法), 回落时提示
  去设 skills_env.md 的 VIVADO_PATH
- simulink-rtl-redev: 新增。原生模型改动后的仿真模型同步规范, 含两个实测过的工具
  check_sync.py (三条时序链新鲜度闸门) 与 measure_k.m (时域/频域/包络三估计器互证)
- sim-rtl-flow/SKILL.md: 加入 sync_sim:* 步骤, 引用上述三个 skill
2026-07-27 10:39:53 +08:00

12 KiB
Raw Blame History

name, description
name description
simulink-rtl-redev 改动原生模型(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_<model>.json), 声明这个模型的源与派生产物。root 相对 manifest 所在目录,其余路径相对 root:

{
  "model": "<model>",
  "root": "..",

  "native_model": "matlab/<proj>/xxx_h.slx",
  "build_scripts": ["matlab/<proj>/build_core.m"],
  "gen_scripts":   ["matlab/<proj>/make_sim.m"],
  "mcode_impl":    ["matlab/<proj>/core_mcode.m"],
  "runtime_deps":  ["matlab/<proj>/pscore.m", "matlab/<proj>/coef.mat"],

  "sim_model":        "matlab/<proj>/xxx_hs.slx",
  "rtl_source_model": "matlab/<proj>/xxx_h_<Mod>_E.slx",

  "gate_result": "Notes/gate_<model>.txt",
  "gate_tools":  ["matlab/<proj>/gate.m", "matlab/<proj>/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_<model>.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 作偏移。

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 -> <key>: <path> 该路径不存在。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 只承载执行路径与工具。