ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Cerebrus 22.1x数字后端ML优化:配置、验证与避坑

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 月更新)把这件事讲得挺透,但它厚在细节、散在章节,第一次读很容易被 What's 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 上产出一组 metric(WNS、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. 把现有流程包进 Cerebrus:outer 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[mem=32000]" \ -J "cer_${SCENARIO_ID}_syn" \ -o "logs/${SCENARIO_ID}_syn.log" \ source ./run_step.sh syn_opt bsub -q normal -n 8 -R "rusage[mem=32000]" \ -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 的默认流程,再按"单维度验证、小规模探索、确认有效后放量"的顺序推进,宁可多花半天做基线,也不再赌运气。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表