体系结构论文(109):UCAgent: An End-to-End Agent for Block-Level Functional Verification

张开发
2026/5/26 1:49:00 15 分钟阅读
体系结构论文(109):UCAgent: An End-to-End Agent for Block-Level Functional Verification
这篇文章研究的是能不能用一个 agent把硬件模块级 functional verification 从头到尾自动做下来。作者提出的系统叫 UCAgent。它想解决的不是 assertion generation、coverage closure、testbench generation 这些单独子任务而是从规格理解、环境搭建、coverage 建模、testcase 生成、执行与分析一路串起来做 end-to-end verification。为此作者提出了三个核心机制1. 用纯 Python verification environment 替代让 LLM 去写大量 SystemVerilog/UVM。2. 用一个 31-stage 的细粒度工作流把复杂 verification 拆成很多可检查的小步骤。3. 用 VCLMVerification Consistency Labeling Mechanism维持 specification、coverage model、testcase 三者之间的一致性和可追踪性。这篇文章的主张很明确1. LLM 不是完全不能做 verification。2. 但如果直接让它一把生成 SV/UVM 验证环境稳定性会很差。3. 需要通过语言迁移、工作流拆解、checker 约束和一致性标签把问题改造成 LLM 更容易做的形式。一. Introduction为什么功能验证这么难Introduction 一开始先重新定义 functional verification它的本质是确认硬件实现是否正确满足设计规格。作者强调随着硬件设计复杂度指数增长验证已经变成时间、人工和可靠性上的“瓶颈”。这里有几个信息点验证现在消耗了很大比例的项目周期验证工程师的需求远高于设计工程师连设计人员自己也要花很多时间协助验证即便投入很多人力first-silicon success 仍不高逻辑/功能错误依然是重 spin 的主要来源。这段的逻辑是投入很大 → 但结果仍不理想 → 所以需要新的自动化范式。传统方法为什么“不够用了”作者接着说行业长期依赖的还是constrained random verificationformal verificationhardware emulation但这些方法本质上只是“维持平衡”没有真正缩小“设计复杂度增长”和“验证能力增长”之间的差距。这里不是说传统方法没用而是说它们仍然重要但靠它们单打独斗已经越来越难覆盖现代设计的复杂性所以大家自然会开始关注 AI / LLM 驱动的验证自动化。现有 LLM 验证研究工业界和学术界都在做但 mostly 只做局部作者指出Synopsys、Cadence、Siemens 等 EDA 厂商都在把 AI 引入验证流程典型方向包括assertion generationcoverage closuredebug学术界也在做assertion generationautomated testbench generationcoverage improvement但作者认为这些工作多数都只是优化验证流程中的一个局部阶段而不是把整个验证过程自动串起来。也就是说人还是那个 orchestration 的核心并没有真正实现“end-to-end autonomous verification”。现有端到端尝试被分成两大类作者把已有的 LLM 自动验证工作分成两类第一类SystemVerilog / UVM-based这些方法的共同点是仍然围绕传统验证语言和验证框架做自动化比如自动生成 UVM testbench、分多 agent 做规格解析、测试规划、代码生成等。第二类Python-based它采用纯 Python 生成策略尝试实现 end-to-end RTL 自动验证。作者这样分类其实是在给自己的工作铺垫UCAgent 明显站在 Python-based 这一侧但又想比 PRO-V 做得更完整。三个核心挑战一个真正的端到端自动验证系统到底会死在哪些地方。Challenge 1LLM 生成 Verilog/SystemVerilog 验证代码不够可靠作者的判断是LLM 在 Python 上通常表现不错但在 Verilog/SystemVerilog 上明显更差。原因有两层。第一层训练数据太少作者引用 The Stack v2 的数据说Python 数据量极大而 Verilog 和 SystemVerilog 的数据量小得多。于是模型对 HDL 的掌握天然更弱。第二层语言本身难即使不考虑数据量SystemVerilog 验证代码本身也更难语法复杂时序和并发语义强容易出现语法正确但语义不一致的问题。所以作者的一个重要判断是如果让 LLM 大量直接生成 SV/UVM 验证代码那么系统稳定性天花板会很低。这就是为什么他们后面改用 Python。Challenge 2复杂端到端验证流程很难靠 LLM 稳定完成作者认为功能验证不是一次性生成一个文件而是一个很长的流程要处理规格文档设计代码验证代码仿真日志测试报告这些信息量非常大很容易超出 LLM 的有效处理能力。于是会出现hallucinationcontext rotinstruction following 变弱作者又把这个挑战拆成两个更具体的问题。1信息丢失和错误累积验证阶段之间是强依赖的。如果前面规格分析少理解了一条约束或者 coverage model 有一个命名错了后面的 testcase、coverage 报告、bug 分析都会被带偏。所以作者的观点是必须在每个阶段结束后进行自动检查而不能等到最后统一发现问题。2简单 workflow 无法适应不同模块有些模块简单比如 FIFO、算术单元LLM 直接生成输入输出检查也许还行。但有些模块交互复杂比如 bus crossbar需要 mock、复杂依赖、严格时序和接口约束。这个时候如果 workflow 太粗糙就会生成接口不匹配、行为错误的验证实现。这里的重点是验证流程不能只有一个统一粗模板而要能根据 DUT 复杂性配置。Challenge 3整个验证闭环里最难的是“一致性”这是这篇文章最有辨识度的点。作者认为一个健壮的功能验证流程必须在以下三个东西之间建立严格 traceabilityfunctional specificationcoverage modeltestcase implementation换句话说规格里提取出来的每个功能点覆盖模型里的 covergroup / coverpoint测试里真正执行到的检查点三者必须是一一对应、可追踪的。作者把这种“验证目标、实现方式和最终结果之间的语义闭环”定义为Verification Consistency。这是非常重要的一个概念。因为很多自动化工作虽然生成了测试也跑出了覆盖率但你很难证明这个 coverage 到底是不是对应原始 spec有没有凭空 hallucinate 出不存在的功能点有没有 spec 里的重要 feature 没被真正覆盖到。Figure 1 是整段引言里最关键的例子。它直观地说明了“一致性断裂”是怎么发生的。图里的原始规格左边 UART Spec 中说的是bit0: Data Readybit1:Overrun Errorbit2: Parity Errorbit3: Framing Error没有 Underrun Error中间的 feature listLLM 在中间把这个功能总结成UART Receiver Error DetectionOverrun ErrorParity ErrorFraming Error到这一步看起来还没太大问题。右边 coverage model 出问题了到了 coverage model 阶段LLM 把overrun改成了overflow又额外加了一个underrun这就出现了两种典型错误Naming inconsistency原始规格里的术语被偷偷替换了虽然看上去意思接近但已经不再严格一致。HallucinationLLM 凭空加了规格里根本没有的场景。作者借这个例子说明如果没有专门的机制去维护一致性那么最后 coverage model 虽然“像那么回事”但它和真实设计意图已经脱节了验证结果也就不再可信。现有方法的不足在引言后半部分作者对几个代表性方法做了一个对比性批评PRO-V没有 functional coverage model因此没法建立“spec → coverage”的完整 traceabilityUVM²主要依赖 prompt 限制没有显式机制确保跨阶段输出严格一致MAVF虽然建立了 test point 和 testcase 的 cross-reference matrix但没有覆盖整个端到端流程的一致性机制。这段的潜台词是现有工作也许能做自动生成但还不能真正构成完整、闭环、可验证的自动验证系统。UCAgent 在引言里提出的三大对应解法在 Figure 1 之后作者正式提出 UCAgent 的解决思路。改语言载体——把验证实现转到 Python作者用 Picker 把 DUT 转成 Python 包PyDUT再用 Toffee 引导 LLM 在 Python 中搭建 testbench 和 testcase。本质逻辑是HDL 验证代码难生成Python 更符合 LLM 的能力边界所以不要硬让 LLM 在自己不擅长的地方作战。这不是简单的“换个语言写代码”而是重新设计 LLM 参与验证的接口层。改流程组织——31-stage 细粒度 workflow作者把验证流程拆成 31 个细阶段每一阶段都要经过 checker 校验。这样可以降低单步任务复杂度阻止错误跨阶段扩散让系统在失败时可以局部修复而不是整条链重来。这一点非常像把“大任务 agent”改造成“可验证的阶段化 pipeline”。改一致性维护方式——VCLMVCLM 通过层级标签让 spec、coverage、testcase 三者共享同一套显式标识。这样每个功能组每个功能点每个检查点都可以跨阶段被 checker 自动追踪。也就是说作者不再只依赖 prompt 说“请保持一致”而是把一致性变成machine-checkable constraint。二、方法Figure 2其实是整篇文章最核心的总览图之一。它想说明UCAgent 不是单靠一个 LLM 在自由发挥而是由三个机制共同约束和支撑。图里可以拆成四个层次来看。输入层Spec 和 DUT左边的Task Inputs是SpecDUT也就是说这个系统的起点不是“让模型凭空想”而是让它基于设计规格文档被测硬件模块来完成验证任务。中间核心LLM中间是 LLM它负责贯穿多个阶段地产生工件包括verify componentscoverage modeltest cases但这里的 LLM 并不是裸奔的它上下左右都被机制包住了。下方机制一Python Verification EnvironmentLLM 的输出不是 UVM/SV testbench而是进入Python Verification Environment。也就是DUT 经 Picker 变成PyDUTLLM 基于 Toffee 和 Python 抽象构建验证组件、覆盖模型和测试。这相当于给 LLM 换了一套“更适合它工作的操作系统”。上方机制二 右侧机制三上方是Verification Workflow表示 LLM 不会一次性把所有东西生成完而是按阶段推进Analyse SpecInsert MockBuild Coverage ModelBuild TestCases这些阶段结果都会被Checkers检查如果失败会形成Error Feedback回到 LLM让它修正。右下角是Artifacts VCLM表示 feature list、coverage model、test cases 这些工件之间不能各写各的而要通过 FG / FC / CK 标签建立一致性。checker 还会进一步做 label checking。2.1 Python Verification Environment为什么不让 LLM 直接写 SystemVerilog而要让它生成 Python2.1.1 作者的根本判断HDL 是 LLM 的短板作者一上来就明确说之所以建立纯 Python 验证环境是为了绕开hardware description language 数据稀缺这个瓶颈。他们认为当前 LLM 驱动验证的主要限制之一就是LLM 不能稳定地产生高质量 SystemVerilog 验证代码。这背后的逻辑是SV 在工业里当然是标准但 LLM 在 SV 上学得不够好Python 才是 LLM 更擅长的语言。注意这里作者不是在说“Python 更专业”而是在说如果目标是让 LLM 稳定完成自动验证那么应该把工作语言设计成更符合模型能力边界的形式。2.1.2 Picker 和 Toffee 各干什么作者提到两个关键工具Picker把 Verilog/SystemVerilog 的 DUT 转成 Python package也就是PyDUTToffee基于 Picker 之上提供更高层的 Python 验证抽象。你可以这样理解Picker 负责“把 RTL 暴露成 Python 可操作对象”Toffee 负责“把 testbench 编写提升到更高层”所以这个体系不是让 Python 取代仿真器而是让 Python 成为控制、驱动、检查 RTL 的上层接口语言。2.1.3 解决了什么问题作者特别强调这种基础设施会把很多低层硬件交互细节抽象掉比如时钟控制仿真调度细节delta-cycle 等时序细节依赖这带来的直接收益是LLM 不用直接处理太底层的硬件验证细节testbench/testcase 更容易生成更适合通过少量 in-context learning 驱动硬件这一步其实非常关键。因为如果让 LLM 直接面对完整的 SV/UVM 语义和事件调度任务难度会陡增。作者这里本质上是在做一层verification abstraction layer。2.1.4 这一小节最后一句很重要作者最后说LLM 通过 Toffee 与 PyDUT 交互来构建 testbench 和 testcase而整个执行过程又受到fine-grained workflowstage-specific checkersVCLM三者共同约束从而保证syntactic correctness与设计规格的严格对齐。这说明Python 环境本身不是完整解决方案只是三大机制中的第一块地基。2.2 The Verification Workflow完整工作流图。它把整个验证过程拆成四大块Requirement AnalysisVerification Infrastructure ConstructionCoverage and Verification Interface ConstructionTestcase Development and Execution虚线框表示有些阶段默认可跳过。作者强调这是一个可配置 workflow不是僵硬固定模板。Requirement Analysis这一列主要在做“理解任务”的工作包含Requirement Analysis and PlanningDUT Function UnderstandingFunctional Specification AnalysisDUT Function GroupingFunction Point DefinitionCheck Point Design这一步的本质不是写代码而是把规格转成结构化验证目标。也就是回答DUT 有哪些功能块每个功能块有哪些功能点每个功能点需要哪些检查点你可以把它理解成把自然语言规格转成后续 coverage 和 testcase 可以消费的验证语义骨架。这也是后面 VCLM 的起点。Verification Infrastructure Construction这一列是最“验证工程化”的部分主要是把测试环境真正搭出来包括这部分意思很明确先把 DUT 包起来不是直接拿 RTL 裸跑而是先包装成可操作的 wrapper / fixture / bundle 接口。必要时引入 mock如果 DUT 依赖外部组件或者交互太复杂单纯对 DUT 本身施激励不够那就要生成 mock。这正是作者前面引言里说的复杂模块需要更复杂的环境建模不能套一个简单模板。先验证环境本身环境不是搭完就默认对还要做mock functional testbasic fixture evaluation必要时 human check这说明作者并不把“环境代码生成”视作理所当然成功而是把它也纳入被验证对象。Coverage and Verification Interface ConstructionCoverage group / point 的作用前面 requirement analysis 得到的是概念上的功能点这里要把这些功能点变成可执行 coverage model可调用检查接口后面 testcase 能实际触发和打点的结构Basic API 的意义这相当于先构造一些基础验证原语例如某个接口怎么驱动某个功能怎么调用某类状态怎么检查这会降低后续 testcase 直接生成的复杂度。换句话说这一列是在做从验证目标建模过渡到验证执行接口建模。Testcase Development and Execution这说明 testcase 并不是一次性生成完事而是个迭代闭环过程。先做模板先有 testcase template再实例化具体测试。跑起来再分析不是“写出来就行”还要执行并分析结果。覆盖率驱动补充如果 line coverage 不够就继续增强 testcase。还能做随机 testcase说明这个流程并不局限于 directed tests也支持进一步向随机测试扩展。作者认为功能验证必须通过 structured workflow 来管理复杂性。它把整个生命周期拆成多个相对独立、输入输出明确、结果可检查的阶段。比如specification analysis 必须输出有精确 label 结构的文档coverage modeling 必须输出可执行 covergrouptestcase generation 必须产出能通过特定检查的仿真代码。也就是说这个工作流不是“为了画图好看”而是为了把每一步都变成deterministic deliverable。这是 agent 能稳定工作的关键。Checker 在这里的真正角色是什么作者这里对 checker 的定义很值得注意checker mechanism encodes expert quality criteria into executable constraint logic.这句话意思是checker 不是简单判个 pass/fail而是把验证专家对每个阶段产物的质量要求写成机器可以执行的约束逻辑。因此一旦某阶段输出不达标checker 会返回具体错误信息LLM 根据这些 error message 自我修正再重新尝试这一阶段所以 checker 的作用相当于局部裁判阶段闸门自动反馈器这也是为什么作者说这个系统能抑制错误累积。为什么是 31-stage作者说这个 31-stage 架构是通过基于 checker 反馈的经验式 refinement得到的。他们观察哪些任务容易失败就继续细分这些任务最后收敛到一个更细粒度的工作流。工作流设计本身也是实验结果的一部分作者不是先验地知道“31 是最优”而是通过失败统计和任务重构逐步打磨出来的。这是一种很典型的系统工程论文思路。2.3 VCLM这一节是整个方法里最有辨识度的部分。作者说为了解决多阶段之间 verification consistency 难以维持的问题他们提出Verification Consistency Labeling Mechanism (VCLM)。VCLM 建立了三层标签FGFCCK并要求 LLM 在三个关键阶段都持续使用这些标签functional specification analysiscoverage model constructiontestcase implementationVCLM 的本质是“把隐式语义变成显式约束”作者明确说VCLM 的作用是把原本隐式的设计依赖关系转化成structured, machine-checkable data。以前你只能通过 prompt 说请保持 coverage model 和 specification 一致请让 testcase 覆盖这些功能点。但 prompt 只是自然语言要求LLM 很容易改名漏项幻觉出不存在的点而现在通过标签机制规格里的功能点有明确 IDcoverage model 必须复用这些 IDtestcase 也必须引用这些 IDchecker 自动核对这些 ID 是否对应正确于是“保持一致”就从一个软要求变成了一个硬约束。VCLM 是怎样和 checker 联动的作者说stage-specific checker 会系统性地提取这些标签验证跨阶段一致性。如果某个工件没有带上必须的标签带了错误标签和前一阶段标签不匹配checker 就会拒绝该输出并返回明确错误 trace 给 LLM触发立即自我修正。为什么“不能只靠 prompt”作者明确说只靠自然语言提示比如“ensure the coverage model is consistent with the specification”对于复杂硬件设计来说是不可靠的。这句话其实是在批评很多 LLM 系统论文常见的问题过度依赖 prompt engineering缺乏显式结构约束输出看似合理实际很难保证可追踪性。三、部署Figure 6 用一个 vector floating-point addition module 展示了 VCLM-enabled workflow。流程很直观1. 在 specification 阶段功能点被标成类似 FG-ARITHMETIC, FC-VFADD, CK-FP32 这样的标签。2. 到 coverage modeling 阶段这些标签必须原样复用到 CoverGroup、CoverPoint、Bin。3. 到 testcase 阶段测试函数也必须声明自己覆盖哪些 check point。4. checker 在阶段之间做 cross-reference。这张图的意义是把 VCLM 从抽象概念变成了可执行机制。它不是“加几个注释”而是整个 workflow 的跨阶段语义锚点。Figure 4 讲的是实现总览主要包括四个模块1. Agent Middleware2. Workflow Management Module3. Stage Validation Module4. Verification Execution Environment这里最关键的是分层1. Middleware 负责 LLM、上下文、工具调用。2. Workflow manager 决定现在在哪个阶段、下一个阶段是什么。3. Validation module 负责 checker 和 VCLM。4. Execution environment 真正跑仿真和测试。Figure 5 则更细地展示了 workflow management module包括 YAML 配置、StageManager、checker gating 等。这两张图说明作者很重视“系统可控性”。不是单纯让 agent 自由发挥而是1. 明确阶段边界。2. 明确通过条件。3. 明确失败回路。这对 verification 任务尤其重要。四、实验作者测试了五个模块包括1. UART-165502. ALU7543. IntegerDivider4. ICache-WayLookup5. PageTableWalker其中前几个规模和结构差异明显而 PageTableWalker 已经是很大的设计。作者用默认 automated workflow 跑这些模块并比较 Claude-Sonnet-4.5、GPT-5、Qwen3-Coder-Plus 等模型。这说明实验不是单一模块 demo而是有一定横向覆盖。Figure 7 分四块展示1. Runtime2. Code coverage3. Coverage bins count4. Functional coverage从结果看1. IntegerDivider 的 functional coverage 可以到 100%。2. UART 和 ALU754 的 functional coverage 多数也在 86% 以上。3. UCAgent 在不同模块上能达到最高 98.5% code coverage 和 100% functional coverage。这对一篇 end-to-end verification agent 论文来说已经是比较扎实的结果。但图里也显示不同模型风格不同1. Claude-Sonnet-4.5 覆盖更高、更细。2. GPT-5 更稳定。3. Qwen3-Coder-Plus 更快但覆盖较低。这种差异说明 UCAgent 不是“屏蔽了底层模型差异”而是提供了一个能把不同模型能力放大的流程。Figure 8 把流程拆成三个大阶段来看1. Component generation2. Coverage-model generation3. Testcase generation结果非常有启发性1. Component generation 相对稳定耗时中等失败少。2. Coverage-model generation 最快、失败率也最低。3. Testcase generation 是最难、最慢、失败最多的阶段。它说明verification 自动化里最难的还是把抽象 intent 落成真正有效的测试刺激。文章还指出1. Claude 在 testcase generation 上试错很多但最终 coverage 最好。2. GPT-5更平衡、更稳。3. Qwen 更快但因为功能分解更粗后续 testcase 难度低一些最终 coverage 也更低。这让 Figure 8 不只是“耗时图”而是帮助理解模型行为差异。Case studies文章给了三个 case study。第一IntegerDivider。Qwen3-Coder-Plus 在 RISC-V 特定边界行为上失败说明即使有 workflow模型本身的 domain knowledge 仍然限制 verification completeness。workflow 能兜住很多过程错误但兜不住模型对某些领域知识根本不懂。第二LaneFAdd。UCAgent 找出了三个之前未发现的边界条件 bug并且借助 VCLM 把失败追踪回具体 function/check point。第三PageTableWalker。这个模块太大默认 workflow 跑不完最后需要 human-in-the-loop8 小时内达成预期结果。1. UCAgent 对模块级任务有效。2. 但超大规模设计还不能完全自动化。

更多文章