nextpnr 文件损坏或截断:.json 网表与 .asc 产物修复速查
更新时间:2026-10-25。FAQ 速查页,面向用 Yosys + nextpnr 开源流程做 iCE40 / ECP5 / Gowin 开发的同学。典型场景:综合明明跑完了,nextpnr 读 .json 网表却报解析错误;或者布局布线「成功」了,生成的 .asc 拿去烧录,板子毫无反应。这两类看似不相干的故障,背后常是同一个根因——文件在某个环节被写坏或写了一半:构建中断、磁盘写满、两个进程同时写一个文件、拷贝传输中途断掉。坏文件的麻烦在于它不总是立刻报错,有时以「能跑但结果不对」的形态潜伏到烧录之后才暴露。本篇讲怎么识别、怎么定位损坏环节、怎么恢复。
本文要回答的问题
- .json 网表 / .asc 产物损坏有哪些典型症状?
- 写盘中断、磁盘满、并发写、传输截断,各自的特征是什么?
- 怎么用文件大小、尾部内容、校验和快速判断文件是不是好的?
- 坏掉的中间文件和源文件,分别怎么恢复?
- 构建脚本怎么写才能让「半截文件」不再被下游当成好文件用?
一、报错原文与现象
1. 网表侧:yosys 输出的 .json 被截断,nextpnr 解析报错:
ERROR: Failed to parse JSON file 'build/demo.json'.或者更迷惑的形态——JSON 语法恰好「截在一个还能解析的地方」,解析不报错,但网表里缺模块、缺连线,布局布线结果莫名其妙少东西。
2. 产物侧:.asc 写了一半,下游工具或烧录出问题:
$ icepack build/demo.asc demo.bin
icepack: Error: Missing EOF marker in input file.iCE40 的 .asc 是文本格式,正常文件末尾有固定结束标记;截断的文件缺这个标记,icepack 一读就露馅。但如果没有这一层校验,半截文件可能被直接烧进 Flash。
3. 最隐蔽的形态:没有任何报错,板子行为不对。 构建全程绿灯,烧录也「成功」,但功能异常或时好时坏——回头一查,.json 或 .asc 的修改时间停留在某次被 Ctrl-C 掐断的构建上。
先建立一个关键认知:构建工具链里的文件损坏几乎都不是「存储介质坏了」,而是「写入过程没走完」。磁盘硬件故障在开发机上极其罕见,断电、Ctrl-C、磁盘写满、进程被杀才是常态。
二、可能原因总览
| 现象 | 可能原因 | 处置 |
|---|---|---|
| .json 尾部不完整、解析报错 | yosys 写网表时被中断(Ctrl-C / 被杀) | 重新跑综合生成 |
| 文件大小明显偏小 | 磁盘写满,写入中途失败 | 见 磁盘写满速查,清盘后重生成 |
| 文件内容前后风格混杂 | 两个进程并发写同一文件 | Makefile 检查并行依赖,串行化 |
| 构建正常但烧录后异常 | .asc 截断且缺少末端校验 | 用 icepack 转换做校验,重新生成 |
| 拷贝后打不开 | U 盘 / 网络传输截断 | 校验和比对后重传 |
| 修改时间很旧但大小正常 | 构建被跳过,用的是陈旧产物 | 检查 Makefile 依赖时间戳 |
| 源文件本身坏了 | 编辑器崩溃 / 强制关机时正在写 | 从 git 版本库恢复 |
| 偶发、换个目录就好 | 磁盘或文件系统真有坏块 | dmesg 看 IO 错误,换盘并备份 |
三、逐条排查展开
第一步:三十秒识别坏文件。 三个低成本手段按序来:
ls -l build/demo.json build/demo.asc # 大小是否明显异常(比平时小一个量级)
tail -c 200 build/demo.asc # 文本类产物看尾部有没有正常结束标记
sha256sum build/demo.asc # 有参照物时比对校验和.json 网表正常末尾是成对收尾的大括号结构;.asc 末尾有固定的 EOF 标记。文件大小是最快的粗筛:同一个设计昨天产 2.1 MB、今天只有 300 KB,不用打开就知道出事了。有「上一次确认是好的」同型文件时,sha256sum 比对是最硬的证据——注意内容里可能含时间戳,逐字节不同不代表坏,要结合大小与尾部结构判断。
第二步:定位损坏发生在哪个环节。 按文件生命周期倒推:
- 生成环节被中断:yosys / nextpnr 写文件不是原子的——先打开、再一段段写、最后关闭。Ctrl-C、
kill、终端断开、系统 OOM 杀进程,都可能让文件停在半截。特征:修改时间就是构建中断那一刻,大小偏小。 - 磁盘写满:写入中途返回 No space left,很多工具不检查每次写操作的返回值,于是「静默截断」——这是最难发现的一种,因为工具退出码可能还是 0。特征:同目录其他文件也写不进去,
df -h见分晓,处置见 Design Compiler 磁盘写满速查(开源流程同样适用)。 - 并发写同一文件:
make -j并行时两个目标规则都写build/demo.json,或调试时手动跑的工具和后台构建撞车。特征:文件内容前后风格突变、大小古怪、故障不可复现——不可复现这一点和 nextpnr 结果飘忽速查 里讲的随机性问题是两回事,注意区分。 - 传输环节截断:U 盘没等同步完就拔、scp/rsync 中途断网。特征:源机器上文件是好的,只有目标端坏。
第三步:恢复——中间文件重生成,源文件靠版本库。 这是处置上最关键的一条分界线:
- .json / .asc 这类中间产物:永远不要「修」,直接删掉重新生成。它们本来就是源文件(.v、.pcf)的派生物,
make clean && make一分钟的事。修补半截网表没有任何意义。 - 源文件损坏(编辑器崩溃、强制关机时正在保存):第一反应是
git status+git diff看工作区与版本库的差异,git checkout -- <文件>恢复到最后提交版本;没提交的改动看编辑器自己的自动保存/交换文件(vim 的 .swp、VS Code 的 backups)。这条的教训写在下面预防一节。
第四步:修构建脚本,让半截文件无法蒙混过关。 Makefile 的经典缺陷是「目标文件存在就算成功」——半截的 .asc 时间戳比依赖新,下次 make 直接跳过重新生成,坏文件被一路用到烧录。两条修法:
# 1. 用临时文件 + mv,保证目标文件要么完整要么不存在
build/demo.asc: build/demo.json
nextpnr-ice40 --json $< --asc $@.tmp && mv $@.tmp $@
# 2. 生成后立刻做最低成本校验,失败即删
build/demo.bin: build/demo.asc
icepack $< $@ || { rm -f $<; exit 1; }临时文件 + 原子 mv 是通用解法:写入中途被杀,留下的只是 .tmp 残骸,正式目标文件不会被污染。校验后置则利用下游工具(icepack 对 .asc 格式的严格解析)当免费的完整性检查,失败时把可疑的上游产物一并删掉,强制下次重建。
四、排查流程图
这张图把「怀疑文件坏了」之后的动作串成主干:先识别(大小/尾部/校验和),再按损坏环节定位,最后按「中间产物还是源文件」分流恢复路径。红色是根因与坏文件节点,蓝色是排查动作,橙色是修复动作,绿色是恢复完成,紫色是固化进脚本的预防措施。
读这张图抓住一条主线:中间产物与源文件的恢复路径完全不同——.json/.asc 的答案永远是「删了重跑」,不要试图修补;源文件唯一的救命稻草是版本库,这也解释了为什么「勤提交」是 FPGA 工程纪律的第一条。两条路最终都汇入「固化预防」:把原子写入和生成后校验写进 Makefile,让下一次中断不再产生能蒙混过关的半截文件。
五、预防与纪律
- 源文件勤提交:功能每前进一小步就 commit,版本库是源文件损坏时唯一的完整备份。
- 中间产物永远重生成、绝不修补:.json/.asc/.bin 都是派生物,坏了删掉
make重跑。 - Makefile 用「临时文件 + mv」写产物:写入中断只留 .tmp 残骸,正式目标要么完整要么不存在。
- 生成后立刻校验:用下游工具(icepack 解析、烧录工具的校验功能)当免费完整性检查,校验失败连同上游产物一起删。
- 构建脚本开
set -e:任何一步失败立即终止,不让半截结果流向下游;退出码的判读与捕获方法见本系列退出码专题。 - 磁盘留余量:工程分区到 85% 就清理,磁盘写满造成的静默截断是损坏类故障里最隐蔽的一种。
- 传输后比校验和:跨机器拷贝产物后
sha256sum两端比对,U 盘先sync再拔。
这一篇在知识体系里的位置
本篇是 FPGA 开源流程排错速查簇中「构建产物完整性」节点的 FAQ 页:与 nextpnr 结果飘忽速查(每次构建结果不同,但文件本身完整)互为鉴别——文件坏是「内容不完整」,飘忽是「内容完整但每次不同」;磁盘写满这一根因的深入处置见 Design Compiler 磁盘写满速查;网表能打开但解析报语法错时先区分「截断」与「真语法问题」,后者见 nextpnr 语法解析错误速查;系列总览见 FPGA 知识版图。
一句话总结
nextpnr 流程里的文件损坏几乎都不是磁盘坏了,而是写入没走完——中断、磁盘满、并发写、传输截断四类根因;识别靠三招:ls 看大小是否缩水、tail 看尾部结束标记、sha256sum 比对校验和;恢复按文件角色分流:.json/.asc 中间产物删掉重新生成、绝不修补,源文件靠 git 版本库 checkout 恢复;最后把「临时文件 + 原子 mv」和「生成后校验失败即删」写进 Makefile,配合勤提交与磁盘留余量,让半截文件再也无法蒙混到烧录那一步。