OpenLANE PDK 版本不匹配报错速查:Failed to compare PDKs 的定位与修复
更新时间:2026-11-05。报错速查页,属于 EDA 报错排查系列。OpenLANE 容器刚起来、一个 flow step 都还没跑,就先扔下一句
[ERROR]: Failed to compare PDKs.主动退出——这是它的启动自检在保护你:环境里声称要用的 PDK 与实际安装物对不上,硬跑下去只会在综合阶段产生一堆无意义的错。同属环境类失败的姊妹篇见 PDK_ROOT 未设置速查 与 OpenLane 镜像 tag 不匹配速查。
首屏答案:先看报错行里 not found 前面的完整路径。路径形如 ~/.volare/sky130C not found. 说明 PDK 变量写了一个 volare 没装的风味名;路径形如 /wrongpdk/sky130A not found. 说明 PDK_ROOT 指到了不含 PDK 的目录。修复只有一个判据:ls $PDK_ROOT/$PDK 必须真实存在。本篇在 OpenLane 2023.07.19 容器里实测了两种错配与一次修复复跑,错配都在任何 flow step 之前退出,改对后 run_synthesis 的 STEP 1/2 顺利通过。
本文要回答的问题
Failed to compare PDKs.与后面的 Python traceback 各自在说什么,失败发生在 flow 的哪个阶段?- OpenLane 的 tag、open_pdks 的 commit、volare 已装的 PDK 风味三者是什么对应关系?
- 报错路径里分别出现
~/.volare/sky130C和/wrongpdk/sky130A,定位手法有何不同? - 修复后凭什么确认这次是真的好了,而不是侥幸越过自检?
一、报错原文与现象
复现设计是一个 12 位带使能的同步计数器(small_counter),纯标准单元、无宏。同一份 RTL 与 config.json,只改容器的两个环境变量 PDK 与 PDK_ROOT,就逼出两种错配签名;二者都在加载设计之前中止:
读这段输出抓住三行。第一行 [ERROR]: Failed to compare PDKs. 是总判定,意思是版本自检程序没法把「你声称要用的 PDK」与「磁盘上实际安装的 PDK」配对。接着的 traceback 指到容器内 /openlane/dependencies/verify_versions.py 第 76 行,抛出的异常文本是 Exception: <路径> not found.——注意它不是版本号越界那种软警告,而是路径根本不存在的硬错误。最后一行 [ERROR]: Please update your environment. OpenLane will now quit. 表明 flow 在 STEP 1 之前就结束了,不会产生任何 run 目录产物。
两个 CASE 的差别全在 not found 前的路径上。CASE A 是 ~/.volare/sky130C:PDK_ROOT 没错(正指向 volare 的家目录),错的是 PDK 风味名 sky130C——volare 在这套环境里只装了 sky130A 与 sky130B。CASE B 是 /wrongpdk/sky130A:风味名 sky130A 是对的,但 PDK_ROOT 被挂到了一个空目录,拼接出来的路径自然不存在。同一句报错模板,两种根因,这也是排查时必须先拆路径的原因。
二、工具与版本:三层版本的对应关系
要读懂这个自检,先理清 OpenLANE 环境里三层容易混淆的版本。
| 层次 | 是什么 | 本篇实测值 | 选错的后果 |
|---|---|---|---|
| OpenLane tag | 容器镜像与 flow.tcl 脚本的版本 | 2023.07.19(镜像 efabless/openlane:d054702) | 脚本与 PDK 接口对不上,见镜像 tag 不匹配篇 |
| open_pdks commit | 构建 PDK 的源码版本,由 volare 按 OpenLane 版本拉取 | volare 管理,对当前 tag 钉死 | 手装别的 commit 会与镜像期望不一致 |
| PDK 风味与根目录 | PDK_ROOT 下的实际安装目录名 | ~/.volare/sky130A(hd 库 sky130_fd_sc_hd) | 目录名写错或根指错,启动即 not found |
关键机制是:每个 OpenLane tag 在依赖清单里钉死了它期望的 open_pdks 版本,volare 据此把对应 commit 构建出的 PDK 装进 ~/.volare/<风味名>;容器启动时 verify_versions.py 做的第一件事,就是检查 $PDK_ROOT/$PDK 这个目录在不在,再比对内部版本文件。也就是说,「PDK 版本不匹配」在日志里有两种烈度:目录不存在直接抛异常退出(本篇的两个 CASE);目录存在但版本文件与镜像期望不符,则会在 compare 阶段报版本差异。本篇命中的是前者,也是新手最常踩的形态——以为 PDK 名可以随便写 sky130、sky130C,实际上它必须与 volare 已安装的目录名逐字符一致。
三、根本原因与分诊流程
把两类错配放进一张四步分诊卡,核心思想是「让报错路径自己说话」:先拆路径,再分别核对变量与磁盘实物,最后才动安装。
这张卡的次序不能颠倒。PDK 与 PDK_ROOT 是两个独立变量,报错路径是它们拼接的结果,不拆路径就分不清谁在撒谎。CASE A 里根目录 ~/.volare 完全正常,去查挂载只会白费时间;CASE B 里风味名 sky130A 本来就装着,去 volare 里反复 enable 也修不好一个指错的根。另外容器场景多一个坑:宿主机上 ls ~/.volare/sky130A 成立,不等于容器里成立——docker run 漏挂 -v $HOME/.volare:$HOME/.volare 时,容器内的同名路径依然是空的,所以核对动作必须在容器内部执行。
四、排查清单与排错路径
按下面的顺序逐条过,每条都给出可直接复制的核对命令与判定标准。
图中红色是入口现象与命中的两类根因,蓝色是排查动作,橙色是修复,绿色是通过态。读图抓住一条分叉:风味名不在 volare ls 清单里,走左支改名;名字在清单里就继续查根目录,走右支修挂载。配套清单如下:
| 序号 | 核对动作 | 正常判据 | 异常时的处置 |
|---|---|---|---|
| 1 | 容器内执行 volare ls | 输出含配置里的 PDK 名(本篇为 sky130A) | 名字写错则改 PDK;没装则 volare enable 对应版本 |
| 2 | 容器内执行 ls $PDK_ROOT/$PDK | 列出 libs.tech、libs.ref 等目录 | 空目录或 not found,进入第 3 步 |
| 3 | 回看 docker run 的 -v 挂载 | volare 家目录挂进容器同路径 | 补挂载重进,不要在容器里重新下载 PDK |
| 4 | 查 echo $PDK $PDK_ROOT | 两变量均非空且拼接路径与第 2 步一致 | 变量为空的情形见 PDK_ROOT 未设置速查 |
| 5 | 仍失败且报的是版本差异而非 not found | 版本文件与镜像期望一致 | 按 OpenLane 镜像 tag 不匹配速查 对齐 tag |
PDK 本身在下载阶段就失败的场景(make pdk 期间 git fetch 超时)不在本篇范围,排查路径见 make pdk git fetch 超时速查。
五、修复与复跑确认
修复动作本身只有两行环境变量:把 PDK 改成 volare 已装的 sky130A,把 PDK_ROOT 指回 volare 家目录,并确保 docker run 带上 volare 目录的挂载。然后用 interactive 模式只跑综合做快速确认:
docker run --rm -it \
-v "$HOME/.volare:$HOME/.volare" \
-e PDK_ROOT="$HOME/.volare" -e PDK=sky130A \
efabless/openlane:d054702 ./flow.tcl -design /designs/lab -interactive进交互提示符后执行 run_synthesis,实测日志如下:
确认修复要看三个标志,而不是只看「没报错」。其一,开头三行 INFO 明确打印 Process Design Kit: sky130A 与标准单元库 sky130_fd_sc_hd,说明自检配对成功、加载的库就是预期风味;其二,Run Directory: /designs/lab/runs/pdk_ok 正常建立,flow 这次真的起跑了——错配时连 run 目录都不会有;其三,[STEP 1] Running Synthesis 与 [STEP 2] 静态时序分析连续执行,LEF 文件按 nom/min/max 三个 corner 依次准备完成。三条同时满足,才能判定环境变量修复有效,而不是换了个地方再出错。
预防纪律:第一,PDK 名永远从 volare ls 的输出里复制,不凭记忆手写;第二,把 docker run 的完整参数(含 -v 挂载与两个 -e 变量)固化成脚本,团队共用同一入口,避免口口相传漏参数;第三,升级 OpenLane tag 时连同 volare 版本一起切,先在交互模式跑一次 run_synthesis 冒烟,再投完整 flow。
实验环境
- 机器/系统:云主机 / Ubuntu 22.04(docker 运行 OpenLANE 容器)
- 工具版本:OpenLane 2023.07.19 / sky130A via volare(镜像
efabless/openlane:d054702,照抄 log 头host-toolchain行) - 日期:2026-11-04
- 完整命令:CASE A
docker run ... -e PDK=sky130C ... ./flow.tcl -design /designs/lab -tag badpdk -overwrite;CASE Bdocker run ... -e PDK_ROOT=/wrongpdk -e PDK=sky130A ... ./flow.tcl -design /designs/lab -tag badroot -overwrite;CASE Cprintf "run_synthesis\nexit\n" | ./flow.tcl -design /designs/lab -tag pdk_ok -interactive(修正PDK_ROOT=~/.volare、PDK=sky130A)
代码获取
复现用 RTL(small_counter 同步计数器)、基线 config.json 与三场景对照脚本 run.sh 在公开仓 https://github.com/derekzhuo/geek-doc.cn/tree/main/experiments/openlane-pdk-version-mismatch。按目录内 README 准备好 OpenLane 镜像与 volare sky130A,执行 ./run.sh 即可依次重现「sky130C 未安装报错 → PDK_ROOT 指空报错 → 改回 sky130A 综合通过」的完整对照。
这一篇在知识体系里的位置
本篇是 EDA 报错排查系列 中 OpenLANE 环境类错误簇的一员,专管「flow 起跑前的 PDK 配对失败」。变量压根没传的情形看 PDK_ROOT 未设置速查,镜像与 PDK 版本世代错位的情形看 OpenLane 镜像 tag 不匹配速查,PDK 还停在构建下载阶段的网络问题看 make pdk git fetch 超时速查。进入 flow 之后的设计类失败(如布线拥塞)则属于另一条线索,不在环境簇内。
总结
Failed to compare PDKs. 加一行 <路径> not found. 就是 OpenLANE PDK 版本不匹配的标准签名,失败发生在任何 flow step 之前:先拆 not found 路径,根目录对、风味名不在 volare ls 清单里就改 PDK(本篇实测的 sky130C 改为 sky130A),风味名对、根目录是空的就修 PDK_ROOT 与容器挂载;修复后以 INFO 打印 sky130A、run 目录建立、STEP 1/2 连续通过三个标志共同确认,不要只看「这次没报错」。