Cerebrus 22.1x数字后端ML优化:配置、验证与避坑
简介《Cadence Cerebrus User Guide》面向电子设计自动化领域的工程师与技术人员聚焦Cerebrus工具的实际使用与设计流程优化适合已具备一定EDA基础、希望系统查阅官方操作说明的中高级读者。内容对应产品版本22.1x更新至2023年12月围绕特定指令、功能说明与典型使用案例展开可作为查阅配置方法、理解功能边界和排查操作问题的参考。资源包共1个PDF文件大小约6.19MB单文档结构便于按章节检索并保留了原指南中的版权、商标及使用限制说明由于文本由OCR扫描生成阅读时需结合上下文对个别识别误差作理解与修正。目前已有543人学习下载适合需要快速定位功能要点、补充官方文档依据并提升设计效率与质量的工程师收藏查阅也可为团队内部培训与知识沉淀提供权威依据。1. 拿到 Cerebrus 22.1x 手册先看哪几页一个跑空两天的教训Cerebrus Cadence 这套 ML 优化框架第一次上手的人很容易把它当成一个更聪明的 make写份配置、敲一条命令、等它自己搜出一版更好的 PPA。真跑起来才发现能不能出结果八成取决于动手之前有没有把 primitive、flow phase、scenario 这三个词的含义对齐。我见过一个团队license 挂上去跑了两天Web UI 里 scenario 一片 fail回头翻日志根因只是 path group 没定义timing cost 恒等于零优化器等于在盲选。这份 22.1x 的用户指南2023 年 12 月更新把这件事讲得挺透但它厚在细节、散在章节第一次读很容易被 Whats New 和 Apps 两章牵走注意力。适合拿它的人很明确已经在跑 Genus/Innovus 全流程、手里有能跑通的 Tcl 脚本、想把手工试参数换成自动搜索的数字后端工程师。2. 拆开优化骨架primitive、flow phase 与 scenario 怎么咬合Cerebrus 不是一个独立的实现工具它站在 Stylus Common UI 那套统一脚本接口上面把你的 Genus/Innovus 流程当成一个黑匣子从外面拧旋钮、收结果、算 reward。手册第二章把这件事拆成三层PPA Optimization Building Blocks、Cerebrus Layers、Flow Phases and Scenarios。三层里任何一层没对齐后面所有配置都是白写。2.1 强化学习工作流在数字后端里到底优化什么先把强化学习的说法翻译成后端语言。一轮 run 由若干 scenario 组成每个 scenario 是一次完整的实现流程区别只在于它拿到的 primitive 取值不同。跑完之后每个 scenario 在每个 flow phase 上产出一组 metricWNS、TNS、total power、面积、runtime 之类这些 metric 按权重加权成一个 cost 值cost 越低越好。下一轮的 scenario 就在上一轮 cost 较低的取值附近继续采样这就是所谓的探索与利用。理解这一点之后配置时就有个基本判断凡是影响 cost 的环节都必须能被 Cerebrus 看到。举个常见的问题某个 scenario 里你自己加了一条set_db max_capacitance之类的约束但那条命令写死在流程脚本里、没做成 primitive那 Cerebrus 永远搜不到它报告里看到的就是这一维怎么调都没变化。反过来如果你把一个 primitive 的区间开得极大探索空间被稀释同样轮数下有效样本变少收敛明显变慢。这是我一般会强调的原则primitive 集合是人工设计的先验不是越多越好。手册里还有一层容易被忽略cost function 是在 flow phase 的边界上算的不是在整个流程末尾算一次。所以 phase 的定义直接决定 reward 什么时候产生。Cerebrus 22.14 之后的默认行为有变化先是把 cts 和 postcts 的 primitive 统一在 postcts 阶段评估route 和 postroute 的 primitive 统一在 postroute 阶段评估接着又改成默认只计算 syn_opt、prects、postcts、postroute、signoff_opt 这五个 phase 的 cost而早期版本默认忽略 syn_generic、syn_map、floorplan 和 route 的 cost。这两条改动的实际影响是如果你沿用旧版本的 phase 期望去读报告会觉得某些阶段的数字不见了或者晚了。升级前先确认默认值比事后怀疑工具靠谱。2.2 flow phase 的分层与 scenario 的规模控制手册把 flow phase 大致划成三段综合段syn_generic、syn_map、syn_opt、实现段floorplan、prects、cts、postcts、route、postroute、收尾段signoff_opt。cost 的取点决定你在哪一段结算这跟人工调参的习惯是一致的没人会在 syn_generic 阶段就为最终 WNS 负责但也没人愿意等到 signoff 才发现方向错了。真正让新手翻车的是 scenario 数量。早期版本里max_scenarios的默认值跟 primitive 的数量挂钩primitive 一多scenario 数就跟着涨LSF 队列直接被占满。22.13 之后改成按可用机器资源和时间预算自动调整这个依赖关系被去掉了。听起来省心但仍要自己设上限队列里别人的作业也在排队你一次吃掉几十个 slot第二天大概率收到的是投诉而不是报告。我一般会按这个顺序确定规模先估单个 scenario 的 wall time用 base scenario 的 runtime 乘 1.2再乘上你愿意等的总时长倒推出并行度上限最后才去设max_scenarios。手册里 Advanced Configuration Options 那节讲 Configuring Scenario Progression思路就是分阶段推进先小规模探一轮定方向再放大规模精修。硬要一次开到很大除了把队列占满还有一个副作用——每个 scenario 的模型样本变稀疏收敛反而更差。2.3 用一个最小配置确认三层对齐在把真实设计丢进去之前我习惯先做一次 sanity run只放两三个 primitive只开少量 scenario跑一轮看 cost 有没有区分度。有区分度才说明 metric 采到了、权重生效了、phase 定义没错。# 最小验证脚本骨架属性名以你手上版本的 set_db -help 输出为准 # 1) 声明参与 timing cost 的 path group这一项缺失会导致 timing 项恒为 0 set_db cerebrus_path_groups {clk_core} # 2) 控制第一轮规模先小后大 set_db cerebrus_max_scenarios 4 # 3) 统一输出模型开关22.14 起默认即为 true这里显式写一遍便于审查 set_db cerebrus_ml_generate_unified_model true这段的意义不在命令本身而在于它暴露了三件事path group 必须显式给scenario 数量必须显式收敛模型合并这个开关在新版本里默认值变了老脚本里如果显式写成 false会跟新默认行为打架。参数说明上cerebrus_path_groups收的是 path group 名字的列表名字必须和你在流程里create_clock/set_path_group建立的完全一致大小写都算cerebrus_max_scenarios是这一轮最多并行几个 scenario不是总 scenario 数cerebrus_ml_generate_unified_model为 true 时多份输入模型会被合成为一份统一输出模型这个特性只在使用-in_models的场景下生效。提示跑完 sanity run 先去 HTML 的 QoR 页看每个 metric 是不是有不同的值。全一样就别往下走了先回去查 metric 采集。3. 把现有流程包进 Cerebrusouter control flow 的四个落点手册第四章讲 Flow Wrapping是整本指南里最需要动手的部分。核心思想很简单Cerebrus 不改你的流程脚本它在外面包一层控制流在每个 flow step 执行前把当前 scenario 的 primitive 值注入进去执行后再把 metric 收上来。包得好不好直接决定你能不能复用已有的 Tcl 资产。3.1 outer control flow 与两种包法的取舍手册给了两类包法。一类是 Outer Control Flow Wrapping由外层 Tcl 负责创建 flow step、循环 scenario、控制分支你的原始脚本被当成一个个 step 的 body 调用另一类是 Stylus 的 common UI 方式靠工具自身的统一接口去接管。前者适合流程已经有比较清晰的分段、每段入口是独立 proc 或独立脚本的情况后者适合流程本来就写在 Stylus 风格脚本里、没有明显分段。选择依据我一般看两点一是你的脚本里有没有大量全局变量靠 source 顺序传递有的话 outer wrapping 更安全因为每个 step 的执行边界清楚二是你需不需要在某个 step 内部做条件分支比如 base scenario 走完整流程、探索 scenario 在 postcts 之后跳过某段这种 branching 在 outer control flow 里写起来更直观。下面是一个 outer control flow 的骨架展示 step 创建和注入位置。# outer_flow.tcl —— 外层控制流骨架 # 每个 flow step 对应原流程里一段可独立执行的脚本 create_flow_step -name syn_opt -body ./scripts/01_syn.tcl create_flow_step -name prects -body ./scripts/02_place.tcl create_flow_step -name postcts -body ./scripts/03_cts.tcl create_flow_step -name postroute -body ./scripts/04_route.tcl # 在 step 执行前注入当前 scenario 的 primitive 取值 # $cerebrus_primitives 由 Cerebrus 在每轮注入不要手工赋值 foreach {pname pvalue} $cerebrus_primitives { apply_primitive $pname $pvalue }create_flow_step的-name必须和你在配置里写的 flow phase 名字对得上对不上就会出现primitive 定义了但从未被评估。-body指向的是原始脚本里面不要自带exit否则外层控制流拿不到控制权。注入那段循环是关键它保证每个 step 开始前环境里的设置是当前 scenario 应有的状态而不是上一个 scenario 残留的状态。我见过最隐蔽的一个 bug 就是注入点写在了 step 之后导致所有 scenario 实际跑的都是上一轮的参数报告看上去收敛了其实是滞后一轮的假象。3.2 把 Cerebrus 库注入现有脚本光有外层循环还不够原始脚本里那些set_db需要能被 Cerebrus 覆盖。手册里对应的章节叫 Injecting Cerebrus Libraries into the Existing Flow Scripts做法是在脚本头部引入 Cerebrus 提供的注入逻辑把脚本里硬编码的属性设成可被外部覆盖的形式。# 在原流程脚本头部引入注入逻辑 source $::env(CEREBRUS_HOME)/scripts/cerebrus_inject.tcl # 之后所有可调属性不要写死改为带默认值的写法 # 默认值保留你原来手工调试时的那一版Cerebrus 探索时会覆盖它 if {![info exists ::cerebrus_override(place_density)]} { set_db place_global_density 0.65 }这段的逻辑是默认值保证脚本单独跑也能出结果方便你自己 debug而一旦 Cerebrus 注入了同名变量就走它的值。参数上要注意命名规范primitive 名字跟你脚本里的变量名最好保持一一对应中间不要做二次映射映射层越多出问题时越难定位到底哪个值真正生效了。3.3 scenario branching 与 distribution script分支的需求很现实base scenario 需要完整跑完拿基线探索 scenario 在某些阶段需要跳过否则 runtime 撑不住。手册里叫 Scenario Branching in an Outer Control Flow实现方式就是在外层判断当前 scenario 的类型。# 根据 scenario 类型决定是否执行某个 step if {$::cerebrus_scenario_type eq base} { run_flow_step signoff_opt } else { # 探索 scenario 跳过 signoff 优化省 runtime puts skip signoff_opt for exploration scenario }判断依据用工具注入的 scenario 类型变量不要自己拿 scenario 编号去猜编号在不同 run 之间不稳定。跳过某个 step 之后那个 phase 的 metric 会是空的配置里对应的 cost 项记得设成不参与否则空值参与加权会污染 reward。分发到 LSF 的部分在手册里叫 Distribution Scripts流程是创建脚本、验证脚本、再靠 distribution log 定位失败点。写法上没有统一模板常见做法是拿一个能跑通的单机版脚本把run_flow_step那几行换成bsub提交然后把返回的 job id 记下来做依赖。# 生成并提交一个 scenario 的作业-w 保证按 step 顺序依赖 bsub -q normal -n 8 -R rusage[mem32000] \ -J cer_${SCENARIO_ID}_syn \ -o logs/${SCENARIO_ID}_syn.log \ source ./run_step.sh syn_opt bsub -q normal -n 8 -R rusage[mem32000] \ -J cer_${SCENARIO_ID}_place \ -w done(cer_${SCENARIO_ID}_syn) \ -o logs/${SCENARIO_ID}_place.log \ source ./run_step.sh prects参数说明-J的作业名里带上 scenario id是为了 distribution log 里能一眼看出是哪个 scenario 的哪一步挂了-w done(...)做串行依赖不要用ended(...)因为ended在作业失败时也会放行后面 step 会在残缺数据库上继续跑产出的 metric 是垃圾-R rusage[mem...]按你单 scenario 峰值内存的 1.3 倍给给少了会出现莫名其妙的 killed日志里只有一行TERM_MEMLIMIT。注意手册里专门有一节叫 Identifying a Successful Cerebrus Base Scenario Run。base scenario 没跑成功之前后面所有探索的 cost 都是相对一个错误基线算的数字看着正常但没有意义。4. 配置文件逐段填path group、bootstrap 与 cost weight 的可抄参数配置是整个流程里最容易写出能跑但不对的部分。手册第六章 Typical Configuration File Settings 给了一份完整样例照着填能跑通但要知道每一段为什么在那儿。下面按我实际填写的顺序过一遍。4.1 path group 与 timing cost 的必填项Path Groups for Timing Costing 在手册里被标成了 Required这个 Required 不是建议是硬要求。timing 类的 cost 组件需要知道对哪些 path group 统计 WNS/TNS没有声明就没有统计对象结果就是这一项恒为零。# 声明参与 timing cost 的 path group顺序不重要名字必须精确匹配 set_db cerebrus_path_groups {clk_core clk_ddr clk_peri} # 如果设计里还有异步接口或需要单独盯的路径一并列进来 # 名字写错不会报错只会在报告里表现为该项缺失所以务必人工核对这段的坑在于静默失败。名字写错、大小写不对、或者这个 path group 在你的流程里直到 postcts 才建立都不会抛错只会在 HTML 里表现为 timing 项为空或者恒定。核对方式很简单跑完 base scenario 后去 QoR 页看每个 path group 是不是都有各自的 WNS 数字全都一样或者全空就是没生效。4.2 primitive 的启停与 bootstrap 区间配置里对应的两节是 Settings for Enabling or Disabling Primitives 和 Bootstrap Values or Ranges of Primitives。前者决定哪些系统内置 primitive 参与这一轮后者给每个 primitive 一个起点或区间。一点经验第一轮不要把所有 primitive 都打开。先按你的设计瓶颈挑三到五类比如综合阶段的 effort 档位、place 阶段的 density、cts 阶段的 useful skew 开关把它们跑出方向再逐步加维度。手册 Advanced Configuration Options 里有一节 Disabling All System Primitives配合 User Defined Primitives 用适合你已经很清楚自己要搜什么、不想让内置旋钮干扰的场景。Bootstrap 区间的给法有两种。给固定值列表适合离散型 primitive比如{low medium high}给范围适合连续型比如 density 从 0.55 到 0.75。范围别给太宽宽区间在有限轮数下采样效率很低通常的做法是先用窄区间定位再在下一轮 run 里把区间平移过去。# 离散型直接给候选值列表 set_db cerebrus_primitive_place_density {0.58 0.62 0.66 0.70} # 连续型给上下界由探索策略在区间内采样 set_db cerebrus_primitive_cts_useful_skew {true false}4.3 cost weight、hold costing 与 early exit成本函数是这一章最需要反复调的地方。手册给的形式是若干 metric 的加权和每一项有自己的归一化方式。下面这张表是我常用的一个起点实际权重必须按项目阶段改不能照搬。cost 组件典型权重适用阶段调整理由timing.setup.wns0.45全阶段主目标权重最高timing.setup.tns0.20全阶段防止为了 WNS 牺牲面timing.hold.wns0.10postroute 之后22.14 起 hold 默认参与计算power.total0.15综合到 postcts与 timing 竞价按项目目标调area0.05全阶段通常只做兜底约束runtime0.05全阶段防止搜出跑不动的解有两条版本行为必须记住。第一条Cerebrus 22.14 起scenario 的 hold costing 变成了默认开启对应的 Cost Weights 表格式也跟着更新了。如果你从旧版本升上来会发现 cost 计算里多了一项同样的设计同样的配置最后选出来的解可能和以前不一样——这不是工具抽风是默认值改了。第二条timing.setup.wns 这个 metric 在 22.14 里从 WNS 换成了 WNS(100)也就是取最差 100 条路径的统计口径HTML 的 QoR 页显示的也是这个。WNS(100) 比单点 WNS 稳定但对那些只有一两条极端路径的设计数值会明显好看一些跨版本对比曲线时要先确认口径一致。如果用-objective指定优化目标手册里 Configuring Exploration with cerebrus -objective 那节讲了怎么把它跟配置里的权重配合。我的用法是-objective只写大方向细粒度权重放配置文件两者冲突时以配置为准这样改目标不用动命令行。Early Exit 这块在 22.14 里增强了可以按 base scenario metric 值的变化百分比提前终止。这个功能对省 license 很实在但阈值别设太激进。设成 1% 这种量级很可能在真正收敛之前就退出拿到的是一版平庸解。我一般设在 3% 到 5%并且只在探索轮数已经很多、边际收益明显下降的 run 上开。# 提前退出连续若干轮相对 base 的提升低于阈值就停 # 阈值取 3%~5%太激进会错过后期突破 set_db cerebrus_early_exit_threshold 0.03 set_db cerebrus_early_exit_window 5参数含义threshold是相对 base scenario 的改善比例下限window是连续多少轮不达标才触发退出。window 太小学到一半就停太大等于没开。5. 避坑五类让整轮搜索白跑的问题与排查顺序下面这五条都是看起来在跑、结果不可信的类型比直接报错更难查。每条按现象、原因、解决写。5.1 跑不动和结果不对的前三类第一条base scenario 一直不成功。现象是 Web UI 里 base 那个 scenario 标红或者状态停在进行中不往前走。原因通常是 flow wrapping 里某条命令在你这版工具上不存在或者原脚本依赖的环境变量在外层控制流里没传进去。解决方式很朴素把包好的流程里注入那几行暂时注释掉手工单跑一遍原始脚本能跑通再解注释对比。手册里 Identifying a Successful Cerebrus Base Scenario Run 那一节给的成功判据值得逐条对一遍别只看作业返回码。第二条timing cost 恒为零或所有 scenario 数值一样。现象是 HTML 的 QoR 页里 timing 那一列全空或者全同。原因基本锁定在 path group 没声明、名字写错、或者 path group 在流程里建立得太晚。解决是先把cerebrus_path_groups打印出来再在流程日志里 grep 对应的 path group 名确认两边完全一致如果 path group 是 postcts 才建的那就要把 timing cost 的评估点挪到 postcts 之后而不是硬在前面的 phase 上取数。第三条scenario 数量开太大被队列卡死。现象是 run 启动后大量作业排队进度条几乎不动或者被管理员直接杀。原因是max_scenarios设得远超队列实际能给你的并行额度早期版本还会因为 primitive 数量多而自动放大这个值。解决分两步先把max_scenarios压到队列额度的七成以下再从少量 scenario 起跑用 restart 加上-j逐步放量。手册 Restarting Cerebrus 和 Increasing -j of an ongoing Cerebrus run 两节就是干这个的别一次性开满。5.2 结果漂移和资源爆掉的后两类第四条升级版本后同配置结果不一致。现象是同样的设计、同样的配置换了工具版本后选出的解明显不同cost 曲线形状也变了。原因是 22.14 改了几处默认值hold costing 默认开启、WNS 换成 WNS(100)、非标准 flow phase 的 cost 被自动忽略、多个输入模型合并成统一输出模型变成默认行为。解决是在升级前先固定一个 base 跑一遍把每个 metric 的口径记在项目文档里升级后用同一份配置再跑一遍做对比跨版本比 cost 绝对值没有意义比排序和趋势才有意义。第五条跑一半磁盘满或内存被打爆。现象是某个 step 突然失败日志里只有 killed 或者 write failed。原因是 Cerebrus 目录结构里 TMP 目录会存大量中间数据库多 scenario 并行时占用是指数级上去的模型文件也占空间。解决是把 TMP 目录指到大容量盘定期清理已完成 scenario 的中间产物同时在 LSF 的资源申请里把内存按峰值给足。手册 Cerebrus Directory Structure 和 TMP Directory 两节把目录职责写清楚了值得花五分钟看一眼比事后清盘省事。提示出问题时的排查顺序建议固定成——先看 distribution log 找失败 step再看该 step 的作业日志找第一条 error最后才去翻 Cerebrus 主日志。反着来会在一堆信息里迷路。6. 用 RAK 和 Web UI 收口先跑通再换设计的验证顺序手册第八章和第九章是我认为最被低估的部分。RAK 就是 Rapid Adoption Kit一套可以开箱跑通的示例流程Cerebrus Apps 里则放了几个专项优化器FP-Opt、Margins Optimizer、Voltage-Frequency Optimizer、Clock App、VT Optimizer。新手常犯的错是跳过 RAK直接拿自己的设计上结果卡在环境问题上分不清是配置错还是流程错。我的做法是三步走。第一步跑一遍 Cerebrus RAK命令行输出看一遍浏览器输出看一遍确认这套环境能出完整报告第二步把 RAK 里的 flow wrapping 结构复制过来把你的脚本一段段替换进去每换一段就单跑一次 base scenario第三步才是加 primitive 和调权重。这个顺序看着慢实际比反复 debug 快得多。Scenario Replay 是另一个值得早点用上的功能。它的作用是把你之前某一轮跑出来的某个 scenario 的参数原样再套一遍用来验证这个解是真的好还是采样噪声。手册给了两种 replay 方式一种走 Stylus Common UI 的 flow wrapping一种走 outer control flow wrapping还各有一个禁用某些 primitive 后 replay的变体。最后这个变体在定位问题时特别有用把某一维固定住再 replay如果结果不变说明这一维根本没起作用。验证动作观察位置判断标准base scenario 是否成功Web UI 状态列状态为完成QoR 页各 metric 非空cost 曲线是否收敛Cost Improvement Graph后期轮次增益趋平无剧烈震荡最优解是否可复现Scenario Replay关键 metric 与原始 run 差异在噪声范围内各维度是否生效禁用 primitive 后 replay禁用前后结果应有可见差异Web UI 的 Live Mode 和 Static HTML Mode 都要会用。Live Mode 适合盯着跑能看运行状态、过滤 base 值、看 scenario 完成情况还能做 kill、re-run、push down、decompress 这些交互操作Static HTML 适合跑完之后归档发给别人看它不依赖会话随时能打开。有个细节在 Live Mode 里 push down 一个 scenario 的优先级会让它优先占用空闲 slot这个在你想尽快看到某个方向的结果时很好用但别滥用否则会打乱探索节奏。注意自定义 metric 要显示在 HTML 报告里需要先在配置里定义好 Custom Metrics再改 HTML 的 YAML 配置。只定义不改 YAML报告里是看不到的这一点手册 Displaying New Metrics in Cerebrus HTML 那节写得很清楚。最后说个习惯。早期我做项目喜欢一上来就把所有参数维度全开觉得搜索空间大总能碰到好解实际情况是跑了两天拿到一堆平庸 scenario还占着队列不放。从那以后我每次接新版本或者新设计都强制先走一遍 RAK 的默认流程再按单维度验证、小规模探索、确认有效后放量的顺序推进宁可多花半天做基线也不再赌运气。希望帮到你。本文还有配套的精品资源点击获取