简介这是一份由Cadence Design Systems官方发布的Cerebrus用户指南对应22.1x版本更新于2023年12月主要面向集成电路设计工程师与EDA工具使用者适合从事数字后端物理实现、时序收敛、功耗与面积优化的团队作为案头参考。指南系统讲解了Cerebrus的各项指令、功能特性及典型使用案例覆盖机器学习驱动的设计优化与收敛流程可作为深入了解该工具操作细节的权威参考。资源包内含1个PDF文档整体约6.19MB适合在本地离线查阅与检索文档由位于加利福尼亚州圣何塞的Cadence总部出版内容完整可直接打印或按章节跳转。目前已吸引539人学习下载对于正在评估或部署Cerebrus的团队有直接实用价值。借助其中的完整操作指引用户能够更快上手先进设计优化功能减少反复试错提升设计效率与结果质量同时文档中关于知识产权与使用限制的说明也有助于读者规范地运用全套工具链。1. 为什么我们需要 Cerebrus一个让 PPA 优化不再靠玄学的 AI 工具Cadence Cerebrus 的 user guide 读起来很长但核心思想浓缩成一句话就是把数字芯片后端实现里的 PPA 优化从人的经验驱动变成强化学习驱动。它会在你已经冻结 RTL、定好工艺库的前提下自动去试综合和布局布线流程里上千个参数组合用多轮迭代逼近更优的面积、功耗和时序。适合的团队是那些已经有成熟 Genus/Innovus 流程、传统脚本怎么调都卡在瓶颈、又不想大改 RTL 的项目。这篇笔记会从原理讲到最小可跑配置再到常见的翻车点和排错方法希望能帮你第一次上手时少踩几个坑。2. Cerebrus 的工作流与强化学习原理它到底在调什么2.1 一次 Cerebrus 闭环综合、PR、采样、学习Cerebrus 的核心是一个强化学习代理。它不直接触碰你的 RTL而是把你现有的综合和布局布线流程封装成一个“环境”。每一次迭代代理从当前设计状态出发选择一个动作——这个动作可能是一组工具选项比如综合时的 compile effort、布局时的密度上限也可能是是否开启某种结构优化。动作作用到流程上跑完一次完整的 genus 到 innovus 流程得到最终的 PPA 指标。代理根据这个指标与上一轮的差值计算奖励更新策略网络然后进入下一轮。传统自动化优化器比如基于贝叶斯的方法通常是生成一批候选参数并行评估后再选下一批。它不关注流程内部的序列因果而 Cerebrus 选择强化学习的一个关键原因正是数字实现流程本身是有顺序的综合阶段的选择会直接影响布局布线的可用空间布局布线的拥塞程度又会反向影响时序收敛。代理需要在每个时间步观察当前阶段的状态再决定下一阶段怎么调参这比一次性搜索所有参数更贴近物理实现的真实因果链。由此也能理解Cerebrus 并不关心你的 RTL 写得怎么样它只关心在给定 RTL 和库的前提下如何通过调整流程让 PPA 更优。也正因为是闭环你需要提供一个能够完整跑通、能稳定输出的基准流程。如果基准流程本身每次跑的结果剧烈抖动代理的每一次采样都会被噪声污染学习几乎无法收敛。还有一个常见的误解是“Cerebrus 会直接改网表”。实际上大多数情况下它是通过控制综合与 PR 的工具选项来间接影响网表结构比如是否允许某些寄存器重定时、是否加大时钟门控力度。它在动作空间里定义这些开关而不是直接做逻辑重写。理解这一点对后续配置很有帮助。2.2 可调动作空间里的三类参数流程选项、实现策略、结构变换我习惯把 Cerebrus 能调的动作分成三类。第一类是流程选项包括 Genus 里的 compile effort、优化目标切换、时钟门控阈值Innovus 里的 placement effort、时钟树综合算法选择、优化迭代次数。这些变量原本是写死在脚本里的常量现在变成代理可以拨动的旋钮。第二类是实现策略这类参数往往跨工具。比如为了缓解拥塞是提高综合时的面积优化力度还是改变布局时的 cell density 约束又比如功耗优化是选择在多电压域上做电源切换还是在时钟门控上加大插入力度。这类参数存在耦合手动调很容易在局部最优里打转但强化学习天然适合探索这种跨步骤的组合。第三类是结构变换这是 Cerebrus 比较有特色的部分。它会根据设计特征决定是否对某些路径做 retiming是否针对特定模块做面积凸优化。这类变换会直接影响时序收敛特性所以通常默认关闭需要你在配置里显式打开。我建议新手先只开第一类和第二类等流程稳定后再放开结构变换否则动作空间过大训练阶段会非常漫长。另外需要注意Cerebrus 的动作空间并不是完全开放的它有一套预定义的动作模板你也可以自定义。但自定义的每一项动作都需要能和你的流程脚本变量对应上并且动作的取值要尽量离散、可解释连续的数值范围会让探索效率明显下降。下面这张表总结了典型动作的例子方便你在设计自己流程时参考。动作类别典型参数示例影响范围流程选项compile_effort, place_effort, cts_algorithm全局收敛速度与最终质量实现策略cell_density, clock_gating_threshold拥塞、时序、功耗结构变换retiming_enable, area_convex_mode路径结构较高风险2.3 适用边界不是所有设计都值得上 CerebrusCerebrus 的强化学习需要大量采样每一次采样都是一次完整的综合加布局布线。如果你的设计跑一遍流程需要十几个小时那么一百轮迭代就是好几天。所以它不是万灵丹。通常适合的是单轮能在几小时内结束的中小型模块或者可以拆分成多个 block 并行优化的设计。对于一颗大型 SoC 全集直接在顶层跑 Cerebrus 很不现实更常见的做法是先让各关键模块分别用 Cerebrus 优化再把产出的最优流程配置固化到顶层集成脚本里。还要考虑团队流程的成熟度。如果基准流程根本跑不通或者每次运行结果都不稳定Cerebrus 不会帮你逆天改命。它只会把流程的不确定性当成实验噪声甚至学到错误方向。我一般会先确认传统脚本已经能稳定收敛并且关键指标的报告路径、日志格式都是固定可解析的然后才考虑引入 Cerebrus。最后是策略的可迁移性。在一个模块上学到的策略放到尺寸、密度或结构差异很大的另一个模块上通常需要重新训练。虽然有迁移学习的机制存在但不要指望开箱即用。工程上我更愿意把 Cerebrus 当作“特定模块的 PPA 深耕工具”而不是一个能适用于整个项目的万能黑匣子。3. 从零跑通 Cerebrus最小输入、配置与启动命令3.1 目录组织与输入文件RTL、SDC、Liberty 和基准流程缺一不可最小输入集合是RTL或者已经综合好的门级网表、SDC 时序约束、工艺库Liberty 文件以及可能的物理库如 LEF还有一个可以手动跑通的基准流程脚本。这个基准流程通常是 Genus 的 Tcl 脚本加 Innovus 的 Tcl 脚本或者把两者串起来的顶层 shell 脚本。Cerebrus 需要有一个可执行命令这个命令能完成从 RTL 到 GDS 的完整流程并且最终输出面积、功耗和时序报告。目录建议按这样组织proj/ ├── rtl/ │ └── top.v ├── sdc/ │ └── top.sdc ├── lib/ │ ├── stdcell_tt.lib │ └── stdcell_ff.lib ├── scripts/ │ ├── genus_run.tcl │ ├── innovus_run.tcl │ └── run_flow.sh ├── cerebrus/ │ ├── config.tcl │ └── outputs/ └── logs/把 Cerebrus 的配置和输出单独放在cerebrus/目录里不要和源文件混在一起。原因是一旦开跑它会生成大量迭代输出包括每一轮的网表、报告和模型权重文件数量动辄上百混在工程目录里会让版本管理非常痛苦。我习惯在配置文件里把输出目录指向cerebrus/outputs并把所有中间产物重定向到这里。基准流程脚本是整个配置的核心。Cerebrus 通过环境变量或占位符的方式把代理选出的参数注入到你的脚本里所以你在写基准脚本时要把打算交给 Cerebrus 调节的变量做成可覆盖形式而不是硬编码。下面是一个可被 Cerebrus 参数化的 Genus 脚本片段# genus_run.tcl 片段 set compile_effort [expr {[info exists ::env(CEREBRUS_COMPILE_EFFORT)] ? $::env(CEREBRUS_COMPILE_EFFORT) : medium}] set place_effort [expr {[info exists ::env(CEREBRUS_PLACE_EFFORT)] ? $::env(CEREBRUS_PLACE_EFFORT) : medium}] read_libs $LIB_FILES read_hdl $RTL_FILE elaborate syn_generic -effort $compile_effort这里::env(CEREBRUS_COMPILE_EFFORT)表示读取环境变量CEREBRUS_COMPILE_EFFORT如果没设置就回退到默认的medium。这样脚本既能独立运行也能被 Cerebrus 驱动。环境变量注入不是唯一方式有些版本支持让 Cerebrus 直接修改 Tcl 变量但环境变量简单直接也不容易与流程内部变量冲突。注意不要试图让 Cerebrus 自己拆解整个流程它没有那么聪明。它只负责修改你标记出来的变量你需要自己把变量接到工具命令的对应参数上。另外基准流程必须固定输出标准报告Cerebrus 默认会从日志或报告文件中抓取面积、功耗、WNS 和 TNS。如果你的报告是自定义格式必须告诉它怎么解析这一步往往是第一次集成时最容易漏掉的地方。3.2 一份能启动的最小 Cerebrus 配置Tcl 代码与逐行解释下面给一份最小配置语言是 Tcl这是 Cerebrus 常见的配置格式。不同版本字段名可能略有差异但结构大致相同。# cerebrus_config.tcl set DESIGN_NAME top set RTL_FILE rtl/top.v set SDC_FILE sdc/top.sdc set LIB_FILES lib/stdcell_tt.lib lib/stdcell_ff.lib set FLOW_CMD bash scripts/run_flow.sh set DELAY_GOAL 0.5 ;# 期望的时序裕量ns set AREA_GOAL 0.8 ;# 期望的面积权重系数 set POWER_GOAL 1.0 ;# 期望的功耗权重系数 set ACTION_SPACE { { CEREBRUS_COMPILE_EFFORT low medium high } { CEREBRUS_PLACE_EFFORT low medium high } } set REWARD_WEIGHTS { WNS 1.2 TNS 0.8 AREA 0.4 POWER 0.6 } set MAX_ITERATIONS 100 set PARALLEL_JOBS 4 set OUTPUT_DIR outputsDELAY_GOAL、AREA_GOAL、POWER_GOAL是目标的参考值REWARD_WEIGHTS决定了模型如何权衡 PPA。ACTION_SPACE定义了代理可调的动作集合每个元素是一个列表第一个是环境变量名后面是可选值。这里只给了三个离散档位实际动作可以更细比如把 compile effort 设为 0.1 到 0.9 的连续范围但新手从离散档开始更稳妥。MAX_ITERATIONS是最大迭代数PARALLEL_JOBS是同时跑多少个采样任务。奖励计算大致可以理解为reward WNS_improvement * 1.2 TNS_improvement * 0.8 - AREA_increase * 0.4 - POWER_increase * 0.6。当你的项目在冲刺 signoff 阶段我会把 WNS 的权重拉高到 1.5 甚至 1.8因为时序是硬条件面积功耗只要不恶化太多就能接受。反过来如果是一个功耗受限的移动芯片可能要把 POWER 的权重改到比时序更高。另外如果不配置自定义日志解析Cerebrus 会假设流程输出的是标准报告。首次跑通前尽量保持流程输出格式符合它的默认预期等整个闭环正常运转了再逐渐加入自定义解析逻辑。3.3 启动任务与日志解读从初始化到采样的标准输出启动 Cerebrus 的命令很简单。在cerebrus/目录下执行cd cerebrus cerebrus -config cerebrus_config.tcl -run 21 | tee logs/cerebrus_run.log如果你的安装环境需要特定的 license 变量先 source 好环境。启动后控制台会先打印配置和初始化信息然后进入采样循环。一个正常的启动日志大致是[INFO] Loading design top... [INFO] Found RTL: rtl/top.v, SDC: sdc/top.sdc [INFO] Flow command: bash scripts/run_flow.sh [INFO] Action space size: 3 x 3 9 combos [INFO] Startup parallel jobs: 4 [INFO] Iteration 1: job-1 starting with params {compilehigh, placemedium} [INFO] Iteration 1: job-2 starting with params {compilelow, placelow} ... [INFO] Iteration 1: job-1 finished, WNS0.42ns, TNS0.0, AREA142000, POWER28.5mW, Reward1.2日志里最需要关注的是每个 job 返回的 PPA 数值和 reward。如果 reward 持续走低说明模型在往错误方向走。这时候不要急着加大迭代数先检查奖励函数的符号和权重是否配置反了比如你想惩罚面积增长却把面积权重写成了负数代理就会拼命把面积做大。还要看单个流程报错的比例如果一大半 job 都是Flow aborted那问题大概率在基准流程本身而不是 Cerebrus。PARALLEL_JOBS直接影响总运行时间。并行度也不是越大越好因为多个 job 会竞争内存和 license。我一般观察单个流程的内存峰值再做粗略估算让单机内存使用率控制在七到八成留一点余量给系统。如果你发现系统开始频繁 swap或者日志中出现超时就该调低并行 job 数。4. Cerebrus 常见翻车点与排查四条血泪经验4.1 现象迭代曲线发散PPA 越来越差多轮迭代后epoch 曲线不是上升而是持续下降或者在散点图上 PPA 毫无规律地跳动但整体趋势在变坏。你还会在日志中看到大量超时或流程中断的记录。第一个怀疑点永远是流程稳定性。如果基准流程每次运行都有一定随机性代理观察到的奖励会携带噪声可能把噪声误归因于某个动作。另一个高频原因是奖励权重符号写反或者权重失衡例如把 TNS 权重设成负值代理自然会去破坏时序。还有一个只在小范围配置里出现的坑是在同一轮并行 job 里混用了不同的工艺角比如一部分 job 用 slow 角另一部分用 fast 角奖励函数却是同一个定义。这样代理无法判断指标变化来自动作还是来自工艺角。解决方法是先做基准无动作稳定性测试连续跑五到八遍计算 WNS、TNS、AREA、POWER 的均值和标准差。如果标准差明显超过你的接受范围先固定流程里的随机种子、关闭并行、统一输出目录直到串行多次结果基本一致。然后再回头逐项验证奖励权重比如只保留时序权重跑几次用固定动作验证奖励符号是否符合直觉。最后如果你开了多个工艺角建议让每个并行 job 使用同一个工艺角不要把工艺角设计成可调动作。4.2 现象同配置跑两次结果标准差超过 5%你用完全相同的参数和配置先后启动两次 Cerebrus得到的面积和时序相差很大甚至一次收敛一次 DRC 爆炸这时候不一定是算法不稳定。最常见的直接原因是并行 job 之间工作目录冲突文件互相覆盖。比如 Innovus 的网表写入路径固定为results/两个 job 同时写同一个文件后写的覆盖前人的最后的报告可能来自一个不完整的过程。第二个原因是流程脚本里有随机优化算法比如 placement 或 CTS 的随机种子没有固定同样的设置也会得到不同结果。第三个原因是绝对路径污染脚本里写死了set_output_dir ./results而 Cerebrus 把并行 job 放到了不同的临时目录所有 job 仍然往同一个路径写。解决方式很直接。第一步给每个 job 分配独立运行目录通过环境变量JOB_ID拼到路径里mkdir -p results/run_${JOB_ID} cd results/run_${JOB_ID}第二步在流程脚本中固定所有随机种子比如 Innovus 的placeDesign -seed和clockDesign -seed。第三步先关掉所有并行串行跑两遍确认结果一致再开放并行。如果串行一致并行不一致那基本是目录冲突尽力去清理所有硬编码的中间路径即可。4.3 现象一个设计调好换到另一个模块立刻失效你在一个模块上跑了上百轮迭代Cerebrus 找出一组不错的参数于是直接把参数复制到另一个模块的流程脚本里结果时序更差、面积更大甚至比默认脚本还差。根本原因在不同模块的物理特征差异。Cerebrus 学到的是针对特定状态到动作映射的策略而不是通用全局规则。面积紧张的模块可能最优动作是降低 cell density 来缓解拥塞但换到余量充足的模块这个动作只会浪费面积时序也未必变好。也就是说导出的最优参数只是一组局部最优解绑定于特定 RTL、宏单元比例和时序约束。解决方式不要指望一组参数打天下。更合理的做法是让 Cerebrus 在多个代表模块上训练或者按设计面积、寄存器数量、逻辑深度做特征聚类每个聚类单独训练一个策略。工程上也可以把训练好的模型权重存档在新模块上做少量迭代的 fine-tune而不是从零开始。我建议在配置中打开 checkpoint 定期保存模型这样后续复用会容易很多。4.4 现象几十轮训练后动作仍在一个小区间内反复横跳训练进行到三分之一左右代理依然在某个动作组合附近反复尝试reward 没有明显提升日志显示每次选择的参数都差不多看起来像是卡住了。这通常是探索和利用失衡。强化学习里的探索参数衰减过快导致代理过早放弃了尝试其他动作。Cerebrus 中一般有控制探索噪声的参数类似 epsilon-greedy 里的 epsilon。你可以提高初始探索率让代理在早期多尝试一些看似更差但长期可能有价值的组合。另外如果动作空间值域太窄比如所有动作选项组合下来只有十几种代理很快就会全部试完之后只能原地打转。另一个可能是奖励过于稀疏。综合和 PR 的最终结果差异在几十轮内不够明显模型梯度更新基本没有有效信息。这时可以考虑把奖励改成阶段性奖励比如在综合完成时先基于面积和拥塞评估给一个中间奖励再在 PR 完成后给最终奖励。不过这种改造会增加配置复杂度建议在基本流程跑通之后再尝试。4.5 现象并行 job 频繁耗尽内存导致流程被杀日志中没有 Cerebrus 自身的报错但某个 job 的Out of memory出现很多次对应的输出文件也不完整奖励计算失败甚至整个 Cerebrus 进程被系统 kill。原因是并行度设置过高。单个 PR 流程的内存峰值可能在三四十 GB如果同时跑十六个 job物理内存被占满内核会杀掉部分进程。另一个原因是多个 job 共用同一个临时目录导致文件缓存反复失效内存叠加。解决方法是先测量单流程峰值内存用top或资源记录工具观察然后把PARALLEL_JOBS设置为“单机物理内存 / 单流程峰值内存 × 0.7”的下取整。同时在 Cerebrus 配置里开启 job 超时和重试机制让因资源不足失败的 job 自动重试而不是直接终止。也要留意 license 池是否充足内存没爆但 job 拿不到 license 时会长时间卡在等待状态容易被误判为死机。5. 把 Cerebrus 用进日常流程增量复用与结果验证技巧5.1 从最优轮数导出固定配置避免每次从零开始Cerebrus 训练结束后会有一个最优迭代的参数快照。不要只拿着 PPA 报告去汇报我建议把该轮的参数组合导出成独立的 Tcl 或环境变量文件直接并入你的基准流程脚本。这样今后重新编译这个模块时可以直接采用这份最优配置省去重复搜索。训练好的模型权重也要保留。把 checkpoint 按“设计名 工艺角 SDC 版本”命名归档当库或约束有小幅度更新时可以接着上次的模型继续训练而不是从零开始。这个习惯在团队里长期价值很高积累几轮之后你会发现自己对一些新模块的收敛速度明显变快了。5.2 用交叉验证区分真实提升与噪声当一个模块训练完报告说“面积优化了 6%”先不要急着写总结。我会做一次交叉验证把最优参数和默认参数各独立跑五遍比较两组 PPA 均值差是否大于标准差的两倍。如果达不到这个阈值那 6% 可能只是运气。这个步骤被很多人省略导致换一套库后结果立刻打回原形。把最优参数单独导出配合一个小循环脚本做重复采样用统计眼光确认增益这在 signoff 前非常有用。5.3 并行度与 license 调度别让 Cerebrus 吃光整个集群Cerebrus 的并行 job 数会倍数级消耗 license。如果你们的 license 支持一个进程占一个 license那并行数要谨慎。我建议把 Cerebrus 的 job 数限制在团队总 license 的一半以内留出空间给其他同事的人工迭代。同时把各个 job 的运行目录分散到不同磁盘或 SSD 上避免 I/O 争用变成新的瓶颈。Cerebrus 本身是一个快速演进中的工具它的 user guide 更像一片需要自己探索的森林而不是一条笔直的路径。我第一次使用它时没有先做基准稳定性测试就急着开跑白白烧了两天 license后来才真正明白先稳定再寻优这个顺序绝不能颠倒。希望这篇实战笔记能帮你少走一段弯路。本文还有配套的精品资源点击获取