
简介这份资源是Synopsys于2021年9月发布的HAPS原型验证平台调试工具官方用户手册面向使用HAPS硬件原型平台进行设计验证的工程师与技术人员重点解决protocompiler debugger在断点设置、内存查看与修改、信号跟踪、执行流程分析等调试环节中的操作指引问题适合具备一定硬件原型验证基础、需要系统掌握调试流程的中高级用户查阅。资源包共1个文件为PDF格式的完整手册大小约2.31MB内容涵盖版权与保密声明、出口管制说明、商标信息及前言等章节正文部分围绕调试器的核心功能与使用场景展开并涉及错误处理、性能优化与调试技巧等实践内容。目前已有785人学习关注可作为HAPS平台调试工作的案头参考帮助读者快速定位功能说明、理解调试流程并对照排查实际问题。1. 拿到一份 HAPS 调试手册先别急着翻目录上周有个做 FPGA 原型验证的朋友甩过来一份 PDF文件名是protocompiler_debugger_user_guide.pdf说项目里 HAPS 板子跑起来之后信号全是 X想抓波形不知道从哪下手问我这份手册值不值得啃。我翻了一遍结论是如果你手上正在用 HAPS 系列原型平台做 SoC 或 IP 的硬件加速验证这份 2021 年 9 月版的调试器用户手册基本是绕不开的案头资料——它把 Instrumentor 插桩、ProtoCompiler 编译、Debugger 联机调试这条链路讲得比较完整尤其是 IICE 硬件描述、Deep Trace Debug、板级 bring-up 自检这几块外面零散博客很少覆盖。但它不是入门教程默认你已经跑通了插桩和编译流程直接讲怎么开调试器、怎么配断点观察点、怎么用状态机触发抓深层数据。适合谁适合已经能把设计烧进 HAPS、但一遇到“信号不翻转”“采样深度不够”“多 FPGA 之间对不上”就卡住的工程师。下面按我实际拆文档的顺序把能抄作业的部分和血泪坑位摊开讲。2. 插桩到调试的完整链路Instrumentor 与 ProtoCompiler 到底谁管什么2.1 为什么不能直接开 Debugger很多人第一次用 HAPS 调试器会翻车在一个认知上以为 Debugger 是个独立工具打开就能看信号。实际上手册第 1 章开篇就点明了Debugger 和 Instrumentor、ProtoCompiler 是强绑定的前两个工具没跑过Debugger 连设计都打不开。原因在于 HAPS 是硬件原型平台不是仿真器你不可能像在 Verdi 里那样任意层次随便拉信号——能看的信号是插桩阶段就定死的。Instrumentor 干的事是让你在 RTL 里指定要监控的信号然后生成一个 instrumentation design constraintsidc文件里面记录了被插桩的信号清单和对应的 IICEIntegrated Instrumentation and Communication Engine硬件资源分配。ProtoCompiler 再拿这个 idc 去编译把调试逻辑真正映射到 FPGA 里的 IICE 块上。Debugger 最后通过 UMRBus 通信接口连到板子读的就是这些 IICE 块采样回来的数据。所以链路是RTL 插桩约束 → Instrumentor 生成 idc → ProtoCompiler 编译出带调试逻辑的位流 → 烧进 HAPS → Debugger 联机读采样。任何一环断了Debugger 里要么看不到信号要么看到的信号名对不上。我一般会先确认 idc 文件里目标信号确实在列再看编译日志里 IICE 资源有没有溢出最后才开 Debugger顺序反了就是白折腾。2.2 插桩约束怎么写才不浪费 IICE 资源手册没有给完整的 idc 语法示例但结合 IICE 硬件描述那一章能反推出约束的粒度逻辑。IICE 的采样块、断点块、观察点块都是有限硬件资源你插的信号越多、触发条件越复杂占用的块就越多。常见做法是分层插桩第一轮只插模块边界和关键握手信号跑通后再按需往可疑子模块里加。下面这段是我按手册描述整理的 idc 片段写法语法以实际工具版本为准重点是让你看清“信号—触发—采样”三者的对应关系# 示例为某个 AXI 从设备接口插桩 # 监控写地址通道握手与写数据通道有效信号 instrument_signal -design top -path u_dut/u_axi_slv/awvalid -iice_group grp_axi instrument_signal -design top -path u_dut/u_axi_slv/awready -iice_group grp_axi instrument_signal -design top -path u_dut/u_axi_slv/wvalid -iice_group grp_axi instrument_signal -design top -path u_dut/u_axi_slv/wready -iice_group grp_axi # 为上述信号组分配一个采样块采样深度按需设置 set_iice_sampling -group grp_axi -depth 1024 -trigger_position 512逻辑说明instrument_signal把 RTL 层次路径下的信号登记进插桩清单-iice_group把逻辑相关的信号绑到同一个 IICE 组方便后续统一配触发和采样。set_iice_sampling里的-depth是采样缓冲区深度-trigger_position决定触发点在缓冲区里的位置——设成 512 意味着触发前保留 512 个采样点、触发后还能再采 512 个这个参数直接决定你抓到的是“事发前因”还是“事发后果”。参数怎么改深度受 IICE 块数量和板上存储资源限制不是想设多大就多大触发位置一般设在缓冲区中点偏后除非你明确只想看触发之后的波形。提示插桩阶段多花十分钟确认信号路径拼写比编译两小时后再回头改约束划算得多。路径写错不会报错只会让你在 Debugger 里看到一个永远不翻转的幽灵信号。2.3 编译产物里要盯哪几个文件ProtoCompiler 跑完之后除了常规位流还会产出调试相关的元数据。手册没有逐一列文件名但从 Debugger 打开设计的流程看它需要读设计层次信息和 IICE 分配报告。我一般会检查三样东西编译日志里 IICE 资源占用是否接近上限、生成的调试数据库是否完整、以及 IICE Assignments Report 能不能正常打开。这个报告在手册第 6 章的 Logic Analyzer 参数部分有提到它列出了每个断点块、观察点块、采样块被分配到了哪个 FPGA 的哪个位置。多 FPGA 场景下这份报告尤其关键因为跨 FPGA 的触发信号走的是片间链路分配不合理会导致触发延迟甚至触发丢失。如果编译日志里出现 IICE 资源不足的警告别硬扛回 Instrumentor 砍信号或者合并采样组。我见过一个项目为了图省事把整个总线所有通道全插上结果编译报资源溢出回头删信号又花了两天典型的后悔药没处买。3. 断点、观察点与状态机触发把“抓不到”变成“抓得准”3.1 断点块和观察点块的区别不是名字手册第 4 章把 IICE 硬件拆成断点块、观察点块、采样块、复杂计数器几部分。新手容易把断点和观察点混着用实际上两者在硬件里的行为不一样。断点块盯的是条件成立的那一刻比如某个信号等于特定值、某个状态机进入某状态条件满足就触发观察点块盯的是信号的变化或匹配更适合“某信号出现某模式时记录”。多个断点和观察点可以同时激活手册专门有一节讲 Multiple Activated Breakpoints and Watchpoints意思是硬件支持并行匹配但并行激活的块越多单块能用的匹配位宽和资源就越紧张。实操上的选型逻辑如果你要抓“写地址等于 0x4000_0000 时发生了什么”用断点如果你要抓“ready 信号连续三个周期为低”这种模式用观察点配合计数器更稳。别指望一个断点块干所有事资源是硬约束。3.2 复杂计数器怎么配才有意义复杂计数器是手册里我觉得最容易被低估的功能。它不只是数周期而是可以按条件增减用来做“事件发生 N 次后触发”或者“连续 M 个周期满足条件才触发”。创建复杂计数器的步骤手册写在第 4 章 Creating a Complex Counter 一节核心是设定计数条件、计数方向增/减、目标值和触发动作。举个实际场景某个 FIFO 的 almost_full 信号偶尔拉高你想抓它连续拉高超过 8 个周期的那一次。单纯用断点会在第一次拉高就触发抓到的全是正常波动。配一个复杂计数器条件设为 almost_full 为高时递增、为低时清零目标值 8达到目标再触发采样就能精准命中异常持续场景。参数上要注意计数器的位宽目标值设太大可能超出硬件计数器能力手册没给具体上限但一般 16 位以内比较稳妥超过就得拆成多级计数。3.3 状态机触发从简单模式切到高级模式的门槛手册把触发分成 Simple 和 Advanced 两种模式Advanced 模式下有状态机编辑器可以画多状态、多条件的触发序列。这是抓偶发、跨模块、有先后顺序的 bug 的利器。比如“先看到 A 模块发出请求再看到 B 模块在 100 个周期内没回应答然后触发抓取”——这种时序相关性用简单触发根本表达不了。状态机编辑器的用法手册第 4 章 State-Machine Editor 和 State-Machine Examples 两节讲得比较细我提炼一下落地步骤先在编辑器里定义状态节点每个节点挂一个触发条件表达式再定义状态转移边边上可以带计数或延时约束最后指定哪个状态是触发态进入该态就启动采样。下面是一个状态机配置的伪代码示意帮助理解结构# 状态机触发配置示意语法以工具实际支持为准 state_machine create -name sm_bus_hang state_machine add_state sm_bus_hang -name WAIT_REQ state_machine add_state sm_bus_hang -name WAIT_RSP state_machine add_state sm_bus_hang -name TRIGGER # WAIT_REQ等待请求有效 state_machine set_condition sm_bus_hang WAIT_REQ {req_valid 1} # 请求有效后进入 WAIT_RSP并启动 100 周期超时计数 state_machine add_transition sm_bus_hang WAIT_REQ WAIT_RSP -counter timeout_cnt -limit 100 # 超时未等到应答则进入触发态 state_machine add_transition sm_bus_hang WAIT_RSP TRIGGER -condition {rsp_valid 0 timeout_cnt 100} state_machine set_trigger_state sm_bus_hang TRIGGER逻辑说明三个状态构成一条“请求—等待—超时触发”的链。add_transition上的-counter和-limit是状态机里嵌计数器的用法比单独配复杂计数器更紧凑。参数说明-limit 100要根据你的总线协议超时窗口来定设太小会误触发正常延迟设太大可能超出状态机计数器位宽。踩坑点在于状态机的条件表达式里引用的信号必须都在插桩清单里漏插一个信号状态机编译时不会明确告诉你“这个信号没插桩”而是表现为该状态永远不转移排查起来很费劲。注意Advanced 触发模式占用的 IICE 资源明显多于 Simple 模式如果只是抓单信号跳变别上状态机杀鸡用牛刀还会挤占其他调试块的资源。4. Deep Trace Debug 与板级自检采样深度和硬件健康的两道保险4.1 DTD 的内存配置决定了你能看多深HAPS Deep Trace DebugDTD是手册第 2 章的主题解决的是普通 IICE 采样缓冲区太浅、抓不到长时序问题的痛点。它借用板上的 DDR3 或 DDR4 内存做深层采样存储采样深度从 KB 级跳到 MB 甚至更大。手册分了 DTD Memory Configurations、Running Deep Trace Debug with DDR3 Memory、Running Deep Trace Debug with Multi-FPGA DTD Module 几节说明不同硬件配置下 DTD 的跑法有差异。关键参数是内存分配。DTD 用的内存和你的设计本身可能共享板上 DDR 资源配多了挤占设计可用带宽配少了采样深度不够。我一般会先跑一遍haps boardstatus看板上内存和链路状态再决定 DTD 的内存划分。多 FPGA 场景下DTD 模块跨片工作时还要确认片间链路的带宽余量手册专门有一节讲 Multi-FPGA DTD Module说明跨片采样对链路是有要求的链路质量差会直接导致采样数据错乱。查看捕获的 DTD 样本在手册 Viewing Captured Deep Trace Debug Samples 一节操作上是在 Debugger 的 Sampled Signals 面板里加载 DTD 缓冲区和普通采样数据的查看方式类似但数据量大得多建议先按触发位置定位再展开别一上来就全量渲染GUI 会卡。4.2 板级 bring-up 自检不是可选项手册第 3 章 Board Bring-up 是我认为最该先读的一章尤其对刚接手一块 HAPS 板子的人。它列了一长串诊断命令clock_check、con_check、con_electrical_check、con_speed、DDR4_selftest、fixed_interconnect_check、ht3_cable_reach_check、ht3_loopback_check、leds_buttons_dip_check、reset_check、spi_flash_memory_check、umr_check。这些命令覆盖了时钟、连接器电气特性、链路速率、DDR 自检、片间线缆可达性、回环、LED/按键/DIP 开关、复位、SPI Flash、UMR 总线。调试前跑一遍这些自检能排掉大量“以为是设计 bug 其实是板子问题”的冤案。比如信号全 X可能根本不是 RTL 问题而是clock_check发现某路时钟没起来多 FPGA 之间数据对不上可能是ht3_cable_reach_check报某根线缆链路余量不足。手册把这些命令的参数和判读标准都列了haps boardstatus和haps prog这类 Utility Commands 也在第 3 章末尾。# 板级自检典型顺序命令名以手册为准 haps boardstatus # 先看板子整体状态 clock_check # 确认各路时钟 reset_check # 确认复位释放 con_electrical_check # 连接器电气特性 ht3_loopback_check # 片间链路回环 DDR4_selftest # 内存自检 umr_check # UMR 总线通信逻辑说明顺序上先看全局状态再逐项排时钟、复位、电气、链路、内存、通信因为后面的检查依赖前面的基础条件。参数说明部分命令带可选参数指定 FPGA 编号或链路号多板多片场景下不指定可能只测默认目标。踩坑点DDR4_selftest跑的时间可能比较长别以为卡死了就中断ht3_loopback_check需要物理回环件或特定线缆配置没接对会一直报失败先确认硬件连接再怀疑板子坏。5. 避坑与排查五个让我返工过的真实坑位5.1 信号在 Debugger 里显示但永远不翻转现象插桩清单里有这个信号Debugger 也能看到名字但采样数据全是 0 或 X。原因通常有三种一是 RTL 路径写错但工具没报错实际插的是另一个同名或空路径二是该信号被综合优化掉了插桩约束没有阻止优化三是信号所在模块的时钟没起来采样块根本没采到有效数据。解决先跑clock_check排时钟再回综合日志搜该信号是否被 optimize 掉最后核对 idc 里的层次路径和实际网表层次是否一致。我现在的习惯是插桩后先做一次小规模编译只验证信号可见性再全量编译。5.2 触发条件设了但从来不触发现象断点或状态机条件看起来没问题跑很久就是不触发。原因多半是条件表达式里的信号采样时钟域和触发块时钟域不一致或者条件里用了组合逻辑中间信号该信号在采样时刻不稳定。解决把触发条件尽量落在寄存器输出上跨时钟域信号先同步再插桩状态机条件里避免引用多级组合逻辑必要时在 RTL 里加一级采样寄存器专门给调试用。手册在 IICE 硬件描述里提到采样块和触发块的工作机制理解了这个就不难推出为什么要用寄存器信号。5.3 DTD 采样数据错乱或丢段现象Deep Trace Debug 抓回来的数据有明显断档或错位。原因DTD 内存配置和设计本身的内存访问冲突或者多 FPGA 场景下片间链路带宽不够导致采样数据回传丢包。解决先用haps boardstatus看链路状态再适当降低 DTD 采样率或缩小单次采样窗口多片场景下确认 DTD 模块的跨片链路和设计数据链路是否争抢同一物理通道。手册 Verifying the Hardware Configuration 一节给了硬件配置核对方法值得照着走一遍。5.4 多 FPGA 调试时触发不同步现象A 片触发了B 片的采样数据对不上时间轴。原因跨片触发信号走片间链路有固定延迟且各片 IICE 块的时钟相位可能不同。解决手册 Cross Triggering 一节讲了交叉触发机制实操上要把触发源统一到同一个参考时钟域并在分析时把片间链路延迟补偿进去。如果延迟大到影响判断考虑把相关信号集中插桩到同一片牺牲资源换同步性。5.5 换了台机器 Debugger 连不上板子现象同一块板子原来机器能连换机器后 UMRBus 通信失败。原因Debugger 的通信配置连接方式、目标地址、驱动没跟着迁移或者新机器的网络/接口权限不同。解决手册第 5 章 Debugger Communications Settings 和 UMRBus Communications Interface 讲了配置项重点核对连接类型和目标标识umr_check命令可以直接验证通信链路。我一般会把通信配置导出成脚本随项目走换机器先跑脚本再开 GUI省得逐项手配。6. 把调试配置脚本化一次配好反复复用的笨办法手册第 6 章提到 Tcl Script Window 和 Executing a Script File这是我觉得整份文档里最值得养成习惯的功能。GUI 点断点、拖状态机不是不行但每次换设计、换板子、换人接手重新点一遍既慢又容易漏。把插桩后的调试配置——断点条件、观察点模式、状态机、采样深度、触发位置——全部写成 Tcl 脚本随项目版本管理才是可持续的做法。我的做法是分三层脚本第一层是板级自检脚本开机先跑boardstatus、clock_check、reset_check这几条确认硬件健康第二层是调试配置脚本按功能模块分组创建断点、观察点、状态机每组带注释说明抓什么问题第三层是采样导出脚本触发后自动把 Sampled Signals 面板数据导出成可分析的格式方便离线比对。下面是一个配置脚本的骨架# layer2_debug_setup.tcl - 调试配置脚本骨架 # 打开设计并加载插桩元数据 open_design -name top_dut -idc ./build/top_dut.idc # 配置 AXI 写通道断点写地址命中特定区间时触发 create_breakpoint -name bp_axi_aw -signal {u_dut/u_axi_slv/awaddr} \ -condition {awaddr 0x40000000 awaddr 0x40001000} \ -action trigger_sample # 配置观察点ready 连续低电平模式 create_watchpoint -name wp_ready_low -signal {u_dut/u_axi_slv/awready} \ -pattern {0 0 0} -action trigger_sample # 设置采样缓冲区与触发位置 set_sample_buffer -depth 2048 -trigger_position 1024 # 启动采样 run_debug -timeout 100000逻辑说明open_design把设计和 idc 元数据关联起来这是 Debugger 能解析信号名的前提create_breakpoint和create_watchpoint分别对应断点块和观察点块的配置条件表达式里的信号必须已在插桩清单中set_sample_buffer的深度和触发位置要和 IICE 资源匹配设超了会报错或静默截断run_debug带超时防止无限等待。参数说明-condition里的地址区间按你的设计实际地址映射改-pattern {0 0 0}表示连续三个采样周期为低模式长度受观察点块位宽限制。踩坑点脚本里的信号路径是层次化路径换综合选项或换顶层封装后路径可能变建议把路径抽成变量集中管理改一处全脚本生效。验证脚本是否生效我一般看两个地方一是 Debugger 的 Watchpoints/Breakpoints 面板里条目数量和条件是否和脚本一致二是 IICE Assignments Report 里资源分配有没有超出预期。如果脚本跑完面板是空的多半是open_design的 idc 路径不对或者信号路径没匹配上先查这两处再怀疑脚本语法。从那以后我每次接手新的 HAPS 调试任务都强制先跑一遍板级自检脚本、再加载调试配置脚本、最后才开 GUI 手动微调这套笨流程帮我省掉了至少一半“配置漂移”导致的假 bug。希望帮到你。本文还有配套的精品资源点击获取