OpenLANE PL_TARGET_DENSITY 密度报错:GPL-0135 Target density must be in [0, 1] 排查
更新时间:2026-11-05。报错排查篇,属于 EDA 报错排查系列。config.json 里把
PL_TARGET_DENSITY写成 1.5,OpenLANE 启动时一句警告都没有,flow 一路绿灯跑到 STEP 7 Global Placement,才被 OpenROAD 全局布局器用[ERROR GPL-0135] Target density must be in [0, 1].当场拒绝。本篇用同一套 RTL 的对照实测讲清两件事:这个变量的量纲为什么是 0~1 的比例而不是百分数,以及合法但激进的高密度值(如 0.9)和非法值(如 1.5)各自会以什么方式报复你。高密度引发的下游布线拥塞见姊妹篇 GRT-0119 布线拥塞失败实录。
首屏答案:PL_TARGET_DENSITY 的语义是「单元总面积 / 可放置面积」的比例,合法区间闭区间 0 到 1,写成 1.5 等于要求布局器把 150% 的面积塞进芯片,物理上不成立。OpenLane 1.x(2023.07.19)加载 config.json 时不做取值范围校验,非法值被静默注入环境变量,债务一直记到 OpenROAD 的 gpl.tcl 运行期才以 GPL-0135 爆出来。修复只有一个动作:改回 0~1 区间内的值(常用 0.5~0.55),本文实测改回 0.5 后 interactive 模式依次跑过 run_synthesis、run_floorplan、run_placement,STEP 7 到 STEP 11 全部通过。
这张卡按排查时的四个动作面分区:红区先确认变量的量纲与合法区间,蓝区理解非法值为什么能潜伏六个步骤,橙区记住报错签名便于下次一眼认出,绿区是修复后的核验手段。全程最容易踩的坑在红区第二条——同一个 config.json 里 FP_CORE_UTIL 是百分数(本例取 40 表示 40%),PL_TARGET_DENSITY 却是比例,两个密度旋钮量纲不同,顺手按百分数的习惯写 1.5 就会造出本篇的报错。
本文要回答的问题
[ERROR GPL-0135] Target density must be in [0, 1].这行报错每个字段在说什么?PL_TARGET_DENSITY为什么是 0~1 的比例而不是百分数?它和FP_CORE_UTIL的量纲差在哪?- config.json 里的非法值为什么能通过配置加载,直到 STEP 7 才被拦住?
- 改成合法但激进的值(如 0.9、0.99)会不会埋下别的问题?
- 修复后复跑,log 里出现什么才算真正过关?
一、报错原文与现象
复现设计是一个 12 位时钟使能计数器(small_counter),纯标准单元、无宏模块。config.json 里故意把 PL_TARGET_DENSITY 设成 1.5,JSON 语法完全合法,flow 正常启动并依次完成 STEP 6 的 PDN 生成,在 STEP 7 Global Placement 中止:
读这段输出抓四个字段。第一,[ERROR]: during executing openroad script /openlane/scripts/openroad/gpl.tcl 说明失败的不是 OpenLANE 的 Tcl 框架本身,而是它调用的 OpenROAD 子进程,脚本名 gpl 就是 global placement 的缩写。第二,核心判定行 [ERROR GPL-0135] Target density must be in [0, 1].——GPL 是 OpenROAD 全局布局器(RePlAce)的日志前缀,0135 是参数越界错误码,方括号 [0, 1] 明确给出闭区间,0 和 1 本身合法,超出即拒。第三,Error: gpl.tcl, 71 GPL-0135 定位到脚本第 71 行的参数检查,紧接着 child process exited abnormally 表示 OpenROAD 子进程非零退出,OpenLANE 随即中止整个 flow。第四,报错前最后几条 INFO 是布线层约束(met1 到 met5)和 RC 值设置,证明布局器已正常启动、死在开工前的参数校验,不是布局跑到一半收敛失败。
值得注意的是前六个步骤没有任何异常:综合、floorplan、tap/decap、PDN 全部正常完成。这正是这类报错迷惑人的地方——配置错误的潜伏期长达六个步骤,因为 PL_TARGET_DENSITY 在 STEP 7 之前根本没有被任何脚本读取。配置文件整体缺失或键名拼错是另外两条报错路径,分别见 No design configuration found 速查 与 OpenLANE config 键名无效速查,本篇的前提是文件在、键名对、只是值越界。
二、工具与版本
本次复现全部在 OpenLane 官方 Docker 镜像内完成,版本与实验 log 头部记录一致:
| 项 | 实测值 |
|---|---|
| OpenLane 版本 | 2023.07.19(镜像内 commit d054702 系列) |
| Docker 镜像 | efabless/openlane:d054702 |
| 布局器 | OpenROAD(global placement 脚本 gpl.tcl,报错码 GPL-0135) |
| PDK / 标准单元库 | sky130A / sky130_fd_sc_hd |
| 失败步骤 | STEP 7:Global Placement |
| 触发方式 | flow.tcl -design 非交互模式复现报错;修复后用 -interactive 分步复跑确认 |
版本信息之所以要记牢,是因为「加载期不校验取值范围」是 OpenLane 1.x 配置体系的行为:config.json 被当作环境变量注入表处理,没有带 schema 的强类型校验。换到 OpenLane 2.x,配置体系改为 Pydantic 模型,变量的取值范围在加载期就会被 validation error 拦住,症状从「STEP 7 运行期报错」变成「启动即报错」,排查路径完全不同,不要跨版本照搬本篇结论。
三、根本原因:比例量纲与静默透传叠加
把从写错值到报错的完整链条画成一张排错流程图,颜色按角色区分:红是根因与报错两端,蓝是 OpenLANE 的正常处理环节,橙是修复动作,绿是修复后的通过态。
读这张图抓住两条主线。明线是「加载期不校验、运行期才拒绝」:OpenLane 1.x 的配置加载器手里只有变量名表、没有值域表,1.5 和 0.5 在它眼里都是一个合法浮点数,原样 set 进环境变量;真正做边界检查的是 OpenROAD 布局器启动时的参数校验,所以报错位置必然在 STEP 7 而不是更早。暗线是量纲混淆:PL_TARGET_DENSITY 的定义是标准单元总面积占可放置区域面积的比例,0.5 表示单元占一半面积、留一半给走线与优化余量;同一份配置里的 FP_CORE_UTIL=40 却是百分数量纲,两个旋钮并排写在一起,按同一套习惯赋值就会写出 1.5 这种要求「单元面积比芯片还大 50%」的非法值。
还要区分两种「高密度问题」,它们的报错形态完全不同。非法值(大于 1 或小于 0)是硬边界,本篇的 GPL-0135 直接拒绝、flow 当场中止;合法但激进的值(0.9、0.99)能通过 gpl 的参数检查,布局器会真的把单元压成近乎实心的块,然后在全局布线阶段以布线拥塞的形式还债——那条路径的报错是 GRT-0119,实测的旋钮对照与拥塞机理见 GRT-0119 Routing congestion too high 排查。一句话:GPL-0135 管「值合不合法」,GRT-0119 管「合法的值布不布得通」,两篇合起来才是密度参数的完整权衡面。
四、排查清单
遇到 GPL-0135 或任何带 must be in [0, 1] 字样的 OpenROAD 报错,按下面顺序收敛:
| 步骤 | 动作 | 判别 |
|---|---|---|
| 1 | 确认报错前缀是 GPL、位置在 gpl.tcl | 锁定全局布局器的参数校验,不要往综合或布线方向查 |
| 2 | 打开 config.json 搜 PL_TARGET_DENSITY | 值大于 1 或小于 0 即确诊;常见错法是写成 50、1.5 这类百分数形态 |
| 3 | 同屏核对 FP_CORE_UTIL 的量纲 | 后者是百分数(0~100),前者是比例(0~1),确认不是两个旋钮抄串了 |
| 4 | 翻 runs/<tag>/config.tcl 反查生效值 | 该文件落盘本次实际注入的全部变量,确认运行期读到的就是你写的那个值 |
| 5 | 改回 0~1 区间后整 flow 复跑 | 不要只重跑单步,环境变量在启动期一次性注入 |
| 6 | 若原值本就合法(如 0.9)却想再降密度 | 这不是 GPL-0135 场景,按拥塞问题处理,同步评估 FP_CORE_UTIL |
两个容易走的弯路。其一,不要试图找 OpenLANE 的配置开关把这个错误降级——gpl.tcl 的区间检查是 OpenROAD 的硬校验,没有豁免开关,唯一正确的修法是改值。其二,改完值别急着往 1 的方向顶:修复只是回到合法区间,工程上合理的起步值是 0.5~0.55,需要省面积时以 0.05 为一档逐步上调、每档留对照 run,直接改成 0.95 大概率从本篇的硬报错换成下游的拥塞软失败。
五、修复代码与复跑确认
错误配置与正确配置只差一个数值。错误写法把比例值当成百分数赋值:
{
"DESIGN_NAME": "small_counter",
"VERILOG_FILES": "dir::src/small_counter.v",
"CLOCK_PORT": "clk",
"CLOCK_PERIOD": 20,
"FP_SIZING": "relative",
"FP_CORE_UTIL": 40,
"PL_TARGET_DENSITY": 1.5
}把最后一行改回 0~1 闭区间内的比例值,其余键原样不动。实验包的基线配置取 0.5:
{
"DESIGN_NAME": "small_counter",
"VERILOG_FILES": "dir::src/small_counter.v",
"CLOCK_PORT": "clk",
"CLOCK_PERIOD": 20,
"FP_SIZING": "relative",
"FP_CORE_UTIL": 40,
"PL_TARGET_DENSITY": 0.5
}改完用交互模式分步复跑,让流程至少穿过整个 placement 阶段确认新值被正常消费:
printf 'run_synthesis\nrun_floorplan\nrun_placement\nexit\n' | ./flow.tcl -design /designs/lab -tag dens_ok -interactive复跑 log 换成了一副面孔——STEP 7 的 GPL-0135 消失,全局布局及其后续的布局侧步骤顺序推进:
过关信号有两个:一是 [STEP 7] Running Global Placement 之后不再出现 GPL-0135 与 child process exited abnormally,流程继续向 STEP 8 推进;二是 STEP 10 Detailed Placement 与紧随其后的 STEP 11 布局侧 STA 都正常出现在 log 里,说明布局全流程(全局布局 → 布局优化 → 详细布局)完整走通。CASE A 与 CASE B 两次运行的唯一差异,就是 config.json 里 PL_TARGET_DENSITY 那一个数值。
实验环境
- 机器/系统:云主机 / Ubuntu 22.04(OpenLane 官方 Docker 镜像内运行)
- 工具版本:OpenLane 2023.07.19 / OpenROAD(docker efabless/openlane:d054702),PDK sky130A,标准单元库 sky130_fd_sc_hd
- 日期:2026-11-04
- 完整命令:
./flow.tcl -design /designs/lab -tag dens_bad -overwrite(CASE A,PL_TARGET_DENSITY=1.5复现 STEP 7 GPL-0135);printf 'run_synthesis\nrun_floorplan\nrun_placement\nexit\n' | ./flow.tcl -design /designs/lab -tag dens_ok -interactive(CASE B,改回 0.5 后分步复跑,穿过 STEP 7 至 STEP 11)
代码获取
复现用 RTL(12 位时钟使能计数器 small_counter)、基线配置 configs/config.base.json 与对照运行脚本 run.sh 在公开仓 https://github.com/derekzhuo/geek-doc.cn/tree/main/experiments/openlane-pl-target-density。按目录内 README 把设计目录挂进 OpenLANE 容器,执行 ./run.sh 即可重现「STEP 7 GPL-0135 失败 → 密度值改回 0.5 后 run_placement 通过」的完整对照;脚本会自动在基线配置上把值改成 1.5 跑出 CASE A,再恢复基线跑 CASE B。
这一篇在知识体系里的位置
本篇是 EDA 报错排查系列 中 OpenLane 配置错误簇的一员,管的是「文件在、键名对、值越界」这一层:文件层缺失见 No design configuration found 速查,键名层拼错见 OpenLANE config 键名无效速查,环境层的 PDK 与镜像问题见 PDK sky130A not found 速查 与 docker tag 不匹配速查。横向看,本篇是密度参数话题的「硬边界」半边,「合法但激进」的半边由 GRT-0119 布线拥塞失败实录 承接,两篇共享 PL_TARGET_DENSITY 这个旋钮、分别覆盖它的非法值域与高值权衡区。
总结
[ERROR GPL-0135] Target density must be in [0, 1]. 的本质是量纲错误:PL_TARGET_DENSITY 是单元面积占可放置面积的比例(闭区间 0~1),不是百分数,OpenLane 1.x 加载期不校验值域,非法值静默潜伏到 STEP 7 才被 OpenROAD 全局布局器运行期拒绝;排查按报错前缀锁定 gpl.tcl、回 config.json 把值改回 0.5~0.55 量级的合法比例,并对照 FP_CORE_UTIL 的百分数量纲防止再次抄串,复跑见到 STEP 7 之后流程持续推进到 STEP 10 Detailed Placement 即告修复;合法但接近 1 的高密度值不会触发本篇报错,却会在布线阶段以 GRT-0119 拥塞失败的形式还债,调密度永远留对照 run、分档上调。