PDN-0191 Pitch does not fit the manufacturing grid 排查:OpenLANE PDN pitch 配置报错修复实录
更新时间:2026-11-06。报错排查篇,属于 EDA 报错排查系列。
[ERROR PDN-0191]是 OpenROAD 电源网络(Power Distribution Network,PDN)生成器在解析 OpenLANE 传入的网格配置时抛出的硬错误:你手写的电源条带间距(pitch)或偏移(offset)除不尽工艺制造网格,几何坐标无法落到晶圆厂允许的落点上,生成器拒绝继续。同属 OpenLANE floorplan 阶段的失败可对照 GRT-0119 布线拥塞失败 一起看——那篇是布局太满,本篇是数值不合法。
首屏答案:Pitch of 13.3370 does not fit the manufacturing grid of 0.0050 这句话的意思是 13.337 / 0.005 = 2667.4,不是整数。sky130A 工艺的制造网格是 0.005um,PDN 的所有 pitch 和 offset 都必须是它的整数倍。本例因为 config.json 里把 FP_PDN_AUTO_ADJUST 关成了 0,OpenLANE 不再替你做舍入,手写的 13.337um 原样送进 OpenROAD 被 PDN-0191 打死。修复只有一步:把 FP_PDN_VPITCH/FP_PDN_HPITCH 改成 13.34(2668 倍网格)、FP_PDN_VOFFSET/FP_PDN_HOFFSET 改成 7.115(1423 倍网格),STEP 6 立刻通过,整条 flow 跑到 STEP 42、Magic DRC 零违例。
本文要回答的问题
[ERROR PDN-0191]这行日志里 pitch、manufacturing grid 两个数值各代表什么?- 为什么同样的 pitch 在别人的设计里不报错,到我这就被打死?
FP_PDN_AUTO_ADJUST到底替我做了什么,关掉之后要自己守什么规矩?- 四个
FP_PDN_*参数(VPITCH/HPITCH/VOFFSET/HOFFSET)各自怎么验才算合法?
先用一张分诊漏斗把排查路径收窄:这个报错不需要猜,日志同时给了违例值和网格值,做一次除法就能定位。
这张漏斗的读法:越往下信息越确定。现象层只告诉你 STEP 6 挂了,日志层直接把违例值和合法网格都打印出来,真正需要人做的只有最后一步除法——PDN-0191 不属于那种要翻报告、开 GUI 的疑难报错,它是一个纯数值合法性问题。
一、报错原文与现场
复现设计是一个小型纯标准单元模块,floorplan 尺寸 38.64 x 38.08um,故意在 config.json 里关闭自动调整并手写一组除不尽网格的 PDN 参数。flow 前五步(综合、STA、初始 floorplan、IO 摆放、tap/decap 插入)全部正常,STEP 6 生成电源网络时中止:
读这段输出抓三个字段。第一,[ERROR]: during executing openroad script /openlane/scripts/openroad/pdn.tcl 说明失败的是 OpenLANE 调起的 OpenROAD 子脚本,主 flow 本身没有语法问题,别去查 config.json 的拼写——配置键名拼写错误是另一个报错家族,见 OpenLANE 未知配置键报错。第二,[ERROR PDN-0191] Pitch of 13.3370 does not fit the manufacturing grid of 0.0050 是核心判定,两个数值都给了:违例 pitch 13.3370um、工艺制造网格 0.0050um。第三,Error: pdn_cfg.tcl, 92 指出错误抛出点在 PDN 配置脚本第 92 行附近的网格校验,随后 child process exited abnormally,OpenLANE 打包 issue_reproducible 后以 exit 255 结束,STEP 7 之后的布局布线全部没有发生。
OpenROAD 子脚本自己的日志只有 16 行,报错行与主日志完全一致,它的价值在于确认这不是 OpenLANE 包装层的误报:
二、工具与版本:谁在判这条错
本条报错涉及三层工具链,职责要分清,否则容易修错地方。
| 层 | 组件与版本 | 在本条报错里的角色 |
|---|---|---|
| flow 编排 | OpenLane d054702b(镜像 efabless/openlane:d054702b...-amd64) | 读 config.json,把 FP_PDN_* 翻译成 Tcl 变量传给 pdn.tcl |
| 电源网络生成 | OpenROAD 41a51eaf(内置 PDN 生成器,报错前缀 PDN) | 执行网格校验,违例即抛 PDN-0191 |
| 工艺数据 | sky130A PDK / sky130_fd_sc_hd(volare 管理) | 提供制造网格 0.005um 这一硬约束 |
关键认知:制造网格不是 OpenROAD 的参数,是工艺事实。sky130A 工艺只承认 0.005um 整数倍的几何坐标,版图里任何一条边、一个通孔的中心都必须落在这个网格上。PDN 条带是按 pitch 等距铺开的:第一条落在 offset 处,之后每加一个 pitch 落一条。只要 pitch 或 offset 不是网格整数倍,后面必然有某根条带的坐标算出非法值——生成器在动手画之前先做这道除法校验,不合法就直接拒绝,宁可 flow 失败也不产出一块没法制造的版图。
三、根本原因:AUTO_ADJUST 关掉之后,舍入的责任回到你身上
OpenLANE 其实自带一道保险。配置项 FP_PDN_AUTO_ADJUST 默认为 1(启用)时,flow 会把你手写的 pitch/offset 自动舍入到制造网格的整数倍再送给 OpenROAD,所以很多教程里随手写的小数 pitch 从不报错。本例的 config.json 显式关了它:
{
"FP_PDN_AUTO_ADJUST": 0,
"FP_PDN_VPITCH": 13.337,
"FP_PDN_HPITCH": 13.337,
"FP_PDN_VOFFSET": 7.113,
"FP_PDN_HOFFSET": 7.113
}关掉自动调整通常是有意的——做自定义电源环、多电压域或者要和宏单元的引脚网格精确对齐时,自动舍入会悄悄改动你的规划值,反而对不上。但开关一关,舍入的责任就完整回到写配置的人身上:四个手写参数每个都要自己保证网格对齐。把违例值代入校验算式:
| 参数 | 违例值 (um) | 除以 0.005 | 判定 |
|---|---|---|---|
| FP_PDN_VPITCH / HPITCH | 13.337 | 2667.4 | 非整数,违例 |
| FP_PDN_VOFFSET / HOFFSET | 7.113 | 1422.6 | 非整数,违例 |
浮点尾数 0.4 和 0.6 就是 PDN-0191 字面意义的来源。还要注意一个连带点:offset 与 pitch 不独立,条带坐标序列是 offset + n × pitch,两者各自对齐网格还不够,实际工程里应让 offset 小于 pitch 且同网格对齐,否则第一条带与核心边界的距离也会非法。floorplan 阶段其他数值类配置(利用率、密度)的调参纪律见 PL_TARGET_DENSITY 布局密度配置,同样是「改 config.json 两行、重跑一次验证」的节奏。
四、排查清单:从 6-pdn.log 到四个参数的整除校验
把排查动作画成流程图,红是报错与根因、蓝是排查动作、橙是修复、绿是通过态。整条路径没有需要 GUI 的环节,一份日志加一次除法就够。
照着图执行,落地成清单是四条:
- 打开
runs/<tag>/logs/floorplan/6-pdn.log,找到PDN-0191行,记下两个数:报错的 pitch/offset 值与 manufacturing grid(sky130A 恒为 0.0050)。 - 核对
FP_PDN_AUTO_ADJUST:在 run 目录落盘的config.tcl里搜这个变量。若是 0,继续手工校验;若根本没设过(默认 1)还报 PDN-0191,说明自定义 PDN 脚本绕过了自动调整,去查你自己的 pdn 配置 Tcl。 - 四个参数逐一做整除:
FP_PDN_VPITCH、FP_PDN_HPITCH、FP_PDN_VOFFSET、FP_PDN_HOFFSET各除以 0.005,全是整数才合法。拿不准浮点尾数时用awk 'BEGIN{print 13.337/0.005}'之类的命令算,别信肉眼。 - 就近舍入并保持 offset < pitch:pitch 往最近的网格倍数靠,offset 同步调整;改完用新
-tag重跑,保留失败 run 做对照。
五、修复与复跑:四个数值对齐网格,全 flow 跑通
修复只动 config.json 的四个数值,自动调整保持关闭(证明手写值本身合法后并不需要重新打开保险):
{
"FP_PDN_AUTO_ADJUST": 0,
"FP_PDN_VPITCH": 13.34,
"FP_PDN_HPITCH": 13.34,
"FP_PDN_VOFFSET": 7.115,
"FP_PDN_HOFFSET": 7.115
}验证算式:13.34 / 0.005 = 2668、7.115 / 0.005 = 1423,两个都是整数,且 offset 7.115 小于 pitch 13.34,第一条带落在核心内部合法位置。同一份 RTL、其余配置不动,以 -tag e39_fix 重跑,STEP 6 一次通过,后续 42 个步骤全部走完:
两个标志确认修复彻底:其一,STEP 40 Magic DRC 之后 No DRC violations after GDS streaming out,电源条带与标准单元、走线之间没有制造规则冲突;其二,结尾 [SUCCESS]: Flow complete. 且 exit 0,与失败 run 的 exit 255 形成干净对照。日志尾部那几条 blackboxed during sta 和 VSRC_LOC_FILES is not defined 是库单元与 IR drop 分析的常规提示,与 PDN 网格无关,不需要为它们回滚配置。
实验环境
- 机器/系统:腾讯云竞价 CVM 16 vCPU / 30GB 内存 / Ubuntu 22.04(docker 运行 OpenLANE 容器)
- 工具版本:OpenLane d054702b2cce04761cc2bc598f6b95c9d8ca7c6c(镜像 tag
efabless/openlane:d054702b...-amd64);OpenROAD 41a51eaf4ca2171c92ff38afb91eb37bbd3f36da;PDK sky130A / sky130_fd_sc_hd(volare 管理,照抄 log 三行头) - 日期:2026-11-06
- 完整命令:
docker run efabless/openlane:d054702b2cce04761cc2bc598f6b95c9d8ca7c6c-amd64 flow.tcl -design /work/e39_design -tag e39_err -overwrite(复现报错,pitch 13.337 / offset 7.113,exit 255);同一命令改-tag e39_fix(验证修复,pitch 13.34 / offset 7.115,exit 0),均带PDK=sky130A
代码获取
复现用设计与两份 config.json(err / fix 配置)在公开仓 https://github.com/derekzhuo/geek-doc.cn/tree/main/experiments/openlane-pdn-pitch-error。按目录内 README 把设计目录挂进 OpenLANE 容器,先跑 err 配置复现 STEP 6 的 PDN-0191,再替换为 fix 配置重跑即可重现「exit 255 → Flow complete、Magic DRC 零违例」的对照。
这一篇在知识体系里的位置
本篇是 EDA 报错排查系列 中 OpenLANE floorplan 阶段错误簇的一员:同阶段的数值类失败有 PL_TARGET_DENSITY 布局密度配置,配置类失败有 OpenLANE 未知配置键报错,下游布线阶段的硬失败见 GRT-0119 布线拥塞失败。本篇管的是「几何合法性失败」——flow 环境正常、设计也不拥塞,纯粹是手写参数除不尽工艺制造网格。
总结
PDN-0191 Pitch does not fit the manufacturing grid 的本质是电源网络参数未对齐工艺制造网格:sky130A 下网格恒为 0.005um,FP_PDN_AUTO_ADJUST=0 后手写的 VPITCH/HPITCH/VOFFSET/HOFFSET 必须各自整除 0.005;排查只需打开 6-pdn.log 抄出违例值做一次除法,把非整数结果就近舍入到网格倍数(本篇实测 13.337→13.34、7.113→7.115),重跑即可让 STEP 6 通过并拿到零 DRC 的完整 flow。