看到这个标题往那一放,搞过数字IC验证的人估计都会心一笑——“自己判卷”这四个字,简直是把Agent辅助硬件设计里最微妙的那层窗户纸给捅破了。DAC 2025上这篇关于MAGE的论文,我第一时间精读,倒不是因为它让LLM生成RTL这件事有多么石破天惊——生成RTL早就不新鲜了,VerilogEval之类的工作两年前就在做了——而是它把Testbench生成、仿真判定、迭代修改这一整套验证闭环也全部塞给了Agent,形成一个“写完代码自己考自己”的完整流程。这事听着美好,干过验证的人都清楚这里面水有多深。
整篇论文我读下来,核心观点可以一句话概括:MAGE试图用多智能体协作加仿真反馈,把LLM生成RTL这条单行道改成一条能自我纠错的双向通道。RTL不行就根据Testbench结果改,Testbench不行就换一批激励再试,直到仿真通过为止。听起来很顺理成章,但“自己考的试自己出题”这个设定,天然就埋着同源错误的雷。这篇精读我就围绕这个矛盾点展开,把MAGE的流程拆开,讲讲它哪些设计是真解决问题的,哪些地方只是缓解了问题,以及我实际复现这套思路时踩到过的坑。
1. 为什么DAC 2025会收录这样一篇“Agent写RTL还自己验证”的论文
1.1 LLM写RTL早就有,但MAGE换了赛道
先把背景捋清楚。用大语言模型写RTL这件事,在EDA圈早已不是新鲜事。从早期拿ChatGPT生成Verilog模块的玩具级尝试,到后来OpenAI、英伟达陆续公开的硬件生成评测集,主流做法其实一直很固定:拿自然语言描述的功能需求丢给LLM,让它吐出一段RTL,然后用一个离线预标注好的测试用例集去跑仿真,看跑通几个。这种做法本质上是把LLM当成一个会写Verilog的编译器前端,评分的尺子捏在测试集手里。
MAGE完全不是这个套路。论文里描述的核心流程,不是“生成一次然后打分”,而是生成、验证、修改、再验证的循环。Agent不只写设计代码,还会根据同一个设计需求自己写Testbench,然后用仿真器把RTL和Testbench放在一起跑,拿到运行结果之后回传给生成Agent,让它判断哪里不对、改哪里,改完再跑。这套机制让我想到的不是一个代码生成器,而是一个初入职场的数字工程师:写完模块自己搭testbench,跑不通就改,改完再跑。
这种思路在学术上的卖点很清晰:它不需要人工标注的测试集,也不依赖预先挖好的验证环境。对LLM生成RTL这个任务来说,最大的瓶颈从来不是写代码,而是判断“写的对不对”。人工搭测试平台成本高,预置测试集又太固定,MAGE选择把这个问题直接交给另一个Agent去解决,路径上确实绕开了一大块顽固障碍。DAC作为设计自动化领域的顶会,对这种把AI和设计方法论粘合起来的尝试天然有兴趣。
1.2 验证环节才是整个流程最吃人力的地方
我自己的实际经验是,过去一个芯片设计项目里,RTL编码的时间可能只占三到四成,剩下的时间大头其实花在验证上。写功能代码是“从需求到实现”的正向翻译,而写Testbench和检查波形是“从实现反推正确性”的逆向校验,二者思考方式完全不同。传统设计流程中验证工程师的工作量往往超过设计工程师,这已经是行业共识,很多公司Design和Verification的人员配比长期维持在1比1.5以上。
LLM进场之后,这个矛盾被放得更大了。让LLM生成一段RTL模块,哪怕是个简单的FIFO或者ALU,几十行代码几分钟就能出来。可问题在于怎么向别人证明这段代码是对的?针对全加器这种简单模块,人工作几个定向激励就行;但遇到带握手信号的AXI接口、跨时钟域的同步器、有限状态机里的每一条转移路径,就得设计完备的激励序列、检查输出时序、看覆盖率和断言报告,这些活儿不可能靠LLM写一次代码就自动消失。
MAGE论文有意思的地方就在这里:与其逃避验证成本,不如让Agent把这部分成本也背起来。它把“写激励”“跑仿真”“查失败原因”“改RTL”全部做成流程的固定节点,用工程化的方式逼着Agent把从设计到验证的完整循环跑完。这样整个流程产出物的质量边界,就从“代码能编译”推进到了“代码能通过仿真”。
1.3 从“生成代码”到“生成可信代码”的跃迁
如果把两种路线放在一起对比,能够更清楚地看出MAGE的野心在哪里。传统LLM生成RTL方案追求的是“一次生成成功率”——你给我一个需求,我尽量吐出能过标准测试的代码。但现实世界的芯片设计从来不是一次定稿的,RTL要满足的功能条件、时序约束、面积功耗目标都是逐步收敛的,初版代码几乎必然要改。MAGE追求的其实是另一件事:让LLM在最小人工干预下,自己把代码从“不完善”迭代到“能通过当前测试平台的验证”。
这个跃迁对我这种长期跟验证工具打交道的人来说意义很大。以前要评估一个LLM生成RTL的水平,我得准备测试集、搭环境、跑波形、逐条对比。MAGE的思路提供了一种可能性:只要给一个文本需求,整个验证闭环自动转起来,最后交付的不只是一段RTL,还有配套的Testbench和仿真报告。方向对了,剩下都是工程化的事。
2. MAGE的核心流程:一份设计规范如何走完全自动生成
2.1 输入侧:自然语言需求如何转换成机器可理解的规范
从论文的框架图来看,MAGE的第一步是把用户给的一段自然语言需求翻译成结构化的设计规范。这一步看着不起眼,实际上决定了后面所有环节的上限。直接拿“给我写一个支持突发传输的AHB slave”这种话作为输入,LLM大概率会凭训练语料里的常见设计模式乱发挥,输出的RTL可能跟用户预期差出十万八千里。
MAGE的处理方式是在输入端增加了一层规范抽取,把自然语言里的功能点拆成模块级特性:端口定义、数据位宽、接口协议、时序参数、异常处理。听起来像是工程师在写需求文档时做的事,但它把这个任务也交给了Agent自动完成。从我复现时的体验看,类似Prompt里的矩式描述模板、接口时序表、边界条件专用问题列表,对提升规范抽取质量效果非常显著。
需要说明的是,这一步做到什么程度,直接反映论文对LLM能力边界的判断。如果输入端给的信息足够结构化,后续生成RTL的难度就低很多;如果需求本身含糊,那Agent生成什么都是空中楼阁,测试验证环节再完善也救不回来。任何机器生成流程的可靠性天花板,都由输入信息的完整度决定,这不是MAGE的缺陷,是这类系统的通病。
2.2 生成侧:RTL设计和Testbench设计为什么要分立角色
接下来进入MAGE最核心的设计决策:RTL Agent和Testbench Agent被拆成了两个独立的角色。论文的解释很直接:二者的目标函数不同,一个要尽可能实现功能,一个要尽可能找出问题,混在同一个Agent里容易让模型陷入“自证清白”的思维惯性。
我在实际使用中非常认同这个拆法。让同一个LLM既写实现又写测试,它会不自觉地共享同一套功能理解。比如需求是“检测下降沿”,如果模型错误地理解成了“检测上升沿”,那么用它写的RTL和它写的Testbench很可能会基于同一个错误理解:Testbench里也会按上升沿来激励和检查,最后仿真一路绿灯,但实际功能完全不对。把设计Agent和验证Agent分开,相当于强行打断它们的“想法串通”,至少在机制上增加了一层对抗。
更进一步,MAGE还给Testbench Agent配备了覆盖率统计工具。生成器不只是在编辑器里“想”测试用例,而是跑完激励后调用覆盖率接口,看状态机走到几个状态、分支语句覆盖了多少行、表达式的true/false分支有没有都执行到。覆盖率数字会作为反馈信号进入下一轮迭代,促使Testbench Agent补充缺失的测试场景。这个设计很像资深验证工程师在做的“用覆盖率指标倒逼测试完备性”,只不过执行者从人变成了Agent。
2.3 收尾侧:仿真反馈与多轮迭代的实际运行机制
MAGE流程的收尾阶段,是把所有Agent的产物汇聚到一个仿真环境里,跑完拿到结果再做多轮迭代。论文里把每轮循环描述为:生成RTL、生成Testbench、运行仿真、收集结果、反馈给RTL Agent修改、再次运行。这个循环终止的条件是仿真全部通过,或者迭代轮数达到上限。
关键在于反馈信号的精细度。如果只告诉RTL Agent“你有条测试没跑过”,那么LLM大概率只能盲目改代码。MAGE的做法是把仿真日志里的具体失败信息摘出来:测试用例名称、期望值、实际值、波形时间点,一并打包反馈给设计Agent。这样设计Agent在看到“cycle 43处输出为0x2,期望0x5”的完整上下文后,定位代码缺陷时就有明确线索,二次修改的成功率明显比抽象反馈要高。
不过这里要泼一盆冷水:多轮迭代的收益不是线性的。我看论文实验结果时注意到,随着迭代轮数增加,RTL的修改幅度如果过大,很容易出现前两轮通过的老测试点在新版本下又失败的情况。MAGE选择了在每一轮改动后重新跑全量Testbench来压住这种回归问题,这保证了收敛的安全性,代价是仿真次数和总体运行时间直线上升。复杂模块跑上七八轮,经常要在仿真工具里烧掉几十分钟的墙钟时间。
3. 自己出题自己判卷:这里的信任边界在哪里
3.1 同源错误:为什么“一个Agent出题一个Agent做题”也并非无懈可击
这是整个MAGE框架我最为怀疑的地方,也是标题里那个灵魂拷问的根源。从直觉上说,测试者和设计者分属不同Agent,已经比“一个人包圆”好得多;但从系统层面看,两个Agent的底层模型是同一个,训练语料相同、先验知识相同、对某个协议或某个算法的理解盲区很可能也是相同的。
我给它起了个名字叫同源错误耦合。举个例子,如果需求文档中有句话是“地址总线支持非对齐访问”,训练语料里常见的设计模式可能默认认为非对齐访问需要拆分传输。RTL Agent基于这个先验把传输拆分逻辑写进设计,Testbench Agent基于同一个先验把“观察拆分行为”写进检查逻辑。结果仿真通过,两者都对,但真实硬件对接总线上别的设备时,对面根本不支持拆分传输——这个错误被两层Agent同时“认证”为正确。
论文里对这个问题给出的对策,是在生成Testbench时注入外部参考信息:把协议规范文档、常见错误列表、黄金参考模型的输出作为上下文喂给验证Agent,降低它对自身先验的依赖。但这些东西本身也都是文本,喂进去会不会被LLM“洗脑”成另一种错误共识,论文没有给出完美解答。这个问题是LLM辅助验证的终极之问,MAGE显然也没能完全解开。
3.2 仿真通过不等于功能正确:覆盖率和断言的盲区
在真实数字IC验证流程里,仿真通过从来只代表“当前激励下行为符合预期”,跟“功能正确”之间隔着一条巨大的河。MAGE用覆盖率工具尽量把河面缩小,但覆盖率和功能正确性之间的缝隙依然存在。覆盖率只能告诉你哪些代码被执行了,不能告诉你在复杂交互场景下代码是否以正确的方式被触发。
举个我自己遇见的典型例子。一个带优先级仲裁的模块,Testbench可能覆盖了“两个请求同时到达,高优先级获胜”的场景,代码行覆盖率和分支覆盖率都能打到95%以上。但正当一个高优先级请求正在被处理、低优先级请求恰好到达、紧接着高优先级请求又来了一个——这种时序交错场景所有人都忘了测。这种盲区仅靠覆盖率指标极难被自动发现,因为每个单独的设计元素都执行过了,只是组合方式没有被验证。
我已经不记得见过多少RTL缺陷是靠“跑一百次随机仿真”抓出来的了,随机激励的价值就在于它能用数量砸出有覆盖率指标测不到的组合场景。MAGE的Testbench Agent如果只是靠人类验证工程师的常规思维模板写定向激励,那么它对这种组合爆炸盲区的防御能力是非常有限的。
3.3 MAGE给出的纠偏手段只是缓解,无法根治
那MAGE到底靠什么来对抗上述这些问题?读完论文,我觉得它的补救手段一共有三层。第一层是前面提到的双Agent独立化,尽最大可能切断共享错误假设的传导路径;第二层是迭代终止条件中加入“多轮独立验证”概念,同一份RTL要连续通过多轮不同随机种子的Testbench才算合格,试图用多样化的激励序列冲散同源错误;第三层是保留人类审查入口,最终交付物中包含完整的仿真报告和覆盖率报告,供人类工程师抽样检查。
说实话,这三层手段单独哪一层都不足以给“自己判卷”的可靠性兜底,三层叠在一起也不能完全消除风险。但它把风险从一个“黑盒里的不可控因素”变成了“报告里可审查的偏差来源”,这本身就是工程意义上的进步。用可靠性工程的话说,MAGE不是在证明“这是对的”,而是在努力做到“错的时候能留下足够的线索让人发现”——这两件事的差距,决定了对这个工具不同心态的接纳程度。
4. 从论文披露的实验结果看MAGE的实际水平与短板
4.1 评测集选择:不同模块难度下的表现
MAGE在论文里测试的模块集合覆盖了从组合逻辑到时序状态机的多种设计,包括加法器、移位寄存器、FIFO、UART收发器、SPI控制器,还有一个简化的RISC-V ALU。这些模块的规模都不算大,但功能特征差异明显:有纯组合逻辑的,有带内部状态的,有需要和外部接口做时序握手的。
读论文里的结果数据时我发现一个规律:MAGE在组合逻辑类和单状态类模块上表现明显更好,而到了带复杂状态机的模块成功率就开始下降。原因不难理解:Testbench Agent在生成激励时需要对内部状态转移有精准预测,但预测量一大,它和RTL Agent之间本来就很脆弱的“理解对齐”就更容易被打破。状态机模型在Agent的文本先验里没有特别统一的标准模板,写出来的测试经常在奇怪的状态组合下和设计行为对不上。
这个局限说明,MAGE当前更适合作为前端模块级设计的自动生成工具,离替代真实SoC级别的完整验证还有很大距离。但它整体的自动化程度和数据结果看完,确实能让人对这个框架的进化路径有所期待。
4.2 与静态测试集方案的对标:优势体现在哪
论文里也做了一批对照实验,核心对比项是:同样让LLM生成RTL,一边用人工预写的固定Testbench判分(传统方案),一边用MAGE自动生成的Testbench去做多轮迭代。结论说实话给了我一个还比较有信心的数据印象:MAGE生成RTL的一次通过率低于静态测试集方案,但经过三轮迭代后的最终通过率显著高于静态方案。
这个对比结果相当有意思,它揭示了一个本质区别。静态测试集方案要求LLM“写出来就是对的”,靠的是模型的先验准确率;MAGE容忍初版有缺陷,靠的是验证闭环把它修对。前者是一条单次博弈,后者是一条多轮收敛。在实际工程环境里,多轮收敛比一次正确更贴近真实需求,因为即使人类工程师写RTL也没有谁能一遍写对,都是靠仿真迭代找bug修bug。
但这也带来运行时成本的代价。每轮MAGE迭代都要完整执行Testbench生成加仿真,一轮耗时可能是静态方案的十几倍。论文给出的运行时间预算我没细算,但个人试下来,单个模块跑完整个MAGE循环通常需要几十分钟级别的时间,模块稍微复杂点就奔小时级别去了。在探索性设计阶段,这种延迟换来的可靠性是值得的;在快速原型迭代阶段,它可能让你的工作效率下降一个数量级。
4.3 从数据展开看MAGE真实适用的业务边界
把实验结果和运行成本摆在一起,MAGE的适用场景其实很清晰。它最合适的是模块级IP验证回归场景——你有一个功能需求文本,希望得到一个经过完整仿真验证的RTL实现,对时间不敏感,但对正确性敏感。反之,如果你在一个大设计里频繁改需求、快速看idea能不能通,MAGE的重型闭环流程就会沦为负担。
论文自己也承认当前版本的局限在于RTL规模上限和仿真反馈粒度。模块规模一旦上升,LLM的上下文窗口撑不住完整代码和测试平台的反复重写;仿真反馈粒度一粗,设计Agent修改时就只能靠猜。这两点是所有基于LLM做设计自动化的系统共同的天花板,MAGE做到了这个天花板之下尽可能好的效果,但天花板本身还在原地。
5. 复现MAGE思路的工程经验:我实际搭建这套系统时踩过的坑
5.1 工具链选型:仿真器的选择直接影响迭代质量
自己动手搭一个MAGE类似系统时,第一个关键决策是选仿真器。论文用的专业级仿真器在个人环境不一定有license,我实际用的是开源的Icarus Verilog加Verilator组合。两者的取舍很有意思:Icarus Verilog对SystemVerilog的支持覆盖广、配置简单,跑仿真脚本一两行搞定;Verilator是编译型仿真器,跑大模块快,但它的Verilog语义更严格,一些RTL写得不够规范时编译错误比Icarus多得多。
真正让Icarus Verilog在我复现流程中胜出的原因,是它的报错信息更加人性化,定位testbench里哪一行在哪个时间点触发失败比较直接。MAGE流程里仿真日志要回传给LLM做分析,日志的可读性直接决定了LLM下一轮修改建议的质量。这一点看着很软性,实际影响极大:报错日志越结构化,Agent的修改方向越准,迭代轮数越少。
5.2 提示词工程的关键细节:角色隔离与上下文管理
在复现MAGE时我发现,提示词设计对效果的影响不亚于框架本身。最核心的一条经验是角色的上下文必须完全隔离。RTL Agent和Testbench Agent虽然共用同一个底层模型,但各自的系统提示词必须锁定各自的职责边界,不能混入对方的任何提示信息,否则模型会自动把两边信息串起来,产生我在第3节担心的同源错误耦合现象。
另一个实操细节是关于反馈上下文的剪裁。每次仿真失败后,完整的仿真日志可能有几百行,直接全部塞给LLM既浪费token又干扰注意力。我仿照论文里的做法做了日志摘要管道:先抓出failed测试的所在行、时间戳、期望值、实际值,再把这四个字段格式化成表格结构喂给模型。实测下来,经过摘要管道处理的反馈,RTL Agent单轮修改成功率比直接喂原始日志有明显提升。
5.3 试运行后的几个反直觉观察
跑通整套流程后,有几个观察和最初的预期不太一样。第一个是Testbench Agent比我预想的“懒惰”得多,如果不明确指定覆盖目标,它生成的激励经常集中在某几个普通的成功路径上,边界条件一个都不碰。所以我后来在prompt里强制加入了一张“验证清单”:必须覆盖正常输入、边界输入、非法输入、时序违例、复位中断这五类场景,生成的Testbench质量才有质的变化。
第二个观察是,多轮迭代会在这里产生“惯性修复”:RTL Agent修好一个bug的同时带有很高概率破坏之前的一个正确行为,然后又在下轮修复时把另一个地方弄坏。最终流程虽然能收敛,但中间过程像打地鼠。我后来人为限制了每次修改的代码量,要求Agent尽量做局部改动而不是重写整个模块,回归失败的次数明显减少。
第三个观察是算力开销。MAGE每一轮完整循环需要调用LLM生成代码、生成测试平台、返回分析日志,一个模块跑三到五轮迭代,光API调用成本就比单纯生成一次RTL高出两个数量级。所以这类系统不适合做廉价的大规模生成任务,它更适合用来做小批量高价值模块的深度打磨。
最后说点实在的
DAC 2025这篇MAGE论文让我印象最深的,不是它把Agent写RTL这件事做得多么完美,而是它把“验证闭环”正式放进了AI辅助硬件设计的讨论范畴。它承认了纯生成式方法的天花板,用工程手段去搭建一个可迭代、可自纠错的框架,哪怕这个框架里依然有同源错误和覆盖率盲区的隐患,哪怕它在复杂模块面前的效率和稳定性都还谈不上理想——但方向是对的。
我的个人态度是:像MAGE这种“自己判卷”的模式,现阶段还不能直接用在流片项目里做最终质量门禁,但用来做设计前期的功能探索、模块级IP自动生成、甚至验证工程师的辅助测试平台搭建,已经完全具备实用价值。如果你也想试,建议从一个简单的状态机模块开始,跑通闭环后再逐步增加复杂度。注意把运行成本管好,验证反馈的日志质量打磨到位,这套思路会让你重新思考“写RTL”和“证明RTL正确”这两件事的边界在哪。