Yosys 找不到 cell/黑盒模块:未知实例与显式黑盒契约排查
答案块 报错:
ERROR: Module \vendor_adder' ... is not part of the design.环境:Yosys 0.33(git sha1 2584903a060),geek-eda:0.2容器。 根因:hierarchy展开顶层时,当前设计里没有vendor_adder的定义;语法解析已经成功,不代表层级完整。 修复:有意保留外部单元时读入带(* blackbox *)的接口声明;需要综合其逻辑时读入真实实现。两条路都必须复跑hierarchy -check、check和stat`。 边界:黑盒路径退出 0 只说明接口与层级可接受,不证明功能正确,也不等于能映射到物理单元。
Yosys 找不到 cell/黑盒模块这个报错,容易把两种完全相反的设计意图混在一起:一种是RTL真的漏了定义,另一种是外部IP本来只提供接口。本文用一个四比特加法器实例对照这两种情况;文件漏读的更多变体见 Yosys 找不到 cell/黑盒模块:子模块未声明。
本文要回答的问题
- 为什么
read_verilog成功后,hierarchy -check仍说模块不在设计中? - 未知模块与有意黑盒在日志和设计上有什么区别?
- 黑盒声明和真实实现分别该怎么写、何时选?
- 两条修复路径的
check、stat各能证明什么?
这张漏斗的关键不是把所有缺模块都补成黑盒,而是在第三层做意图分诊:需要参与逻辑综合的模块必须给实现,只有确实由外部提供的单元才保留黑盒契约。
一、Yosys 找不到 cell/黑盒模块:完整报错现场
最小顶层只例化一次 vendor_adder,第一次命令故意不提供它的定义。-Q -T 只是减少横幅与日志时间戳,不改变检查行为。
日志中的顺序很重要:Successfully finished Verilog frontend 只表示顶层语法和AST转换成功;随后 2.1. Analyzing design hierarchy 才核对实例引用。报错同时给出缺失模块 vendor_adder、父模块 top 和实例 u_adder,所以定位对象是那个模块定义,不是实例端口。由于 hierarchy 已经中止,后面的 check 与 stat 根本没执行,退出码为 1。
二、根因:设计库中没有定义,不等于必须补逻辑
Yosys 只检查已经读入设计的模块,不会按实例名自动到磁盘搜索源文件。对 hierarchy -check 来说,模块体为空但带有黑盒属性的定义,与带算术逻辑的定义,都能回答“这个模块是否存在”;两者对后续流程的承诺却不同。
| 设计状态 | 层级检查看到的对象 | 合理用途 | 不能据此断言 |
|---|---|---|---|
| 未知模块 | 只有实例,没有模块定义 | 无,通常是输入不完整 | 不能继续可靠综合 |
| 显式黑盒 | 有参数、端口和黑盒属性 | 外部IP、宏单元、后续再接入实现 | 功能已验证、已有工艺映射 |
| 真实实现 | 有端口和可综合模块体 | 需要优化、验证或映射内部逻辑 | 已自动匹配某个物理库 |
黑盒(blackbox)在这里是“只公开边界、不公开内部实现”的契约。端口名、方向和参数仍是调用方与提供方必须一致的接口;(* blackbox *) 则明确告诉 Yosys 这种留白是设计意图,不是又一次漏读。
三、排查清单:先定意图,再补定义
按报错中的模块名检查输入清单后,真正决定分支的是“这个cell此刻应不应该有内部逻辑”。可以顺着三项信息判断:交付清单里它是RTL源码还是独立宏单元;集成文档是否允许当前阶段只接接口;后续仿真与映射分别由谁提供模型和库。三项都没有答案时,不要为了赶通流程自行发明黑盒,应先向模块提供方确认契约。
还有两个边界值得在修改前排除。只写一个空 module 而不加黑盒属性,虽然也可能越过层级检查,却会把“无意留空”伪装成正常实现,不应作为修复模板。即使使用了黑盒,参数类型、端口方向和位宽仍应与提供方文档一致;属性不会替你修正接口错误,也不能把错误连接变成正确设计。
下图中红色是故障入口,蓝色是分析动作,橙色是两种修复,绿色是复跑通过,紫色是必须记录的边界。
读图时不要把橙色两条支路当成可随意互换的开关。若缺失的是普通RTL子模块,黑盒只会让错误安静下来,却把逻辑空洞留在网表里;若缺失的是签核流程外部交付的宏单元,强塞一个行为模型又可能让综合结果偏离真实交付物。
四、路径一:显式声明黑盒并复跑
接口文件不需要 assign 或 always,只需保留参数、端口和黑盒属性:
(* blackbox *)
module vendor_adder #(
parameter WIDTH = 4
) (
input wire [WIDTH-1:0] a,
input wire [WIDTH-1:0] b,
output wire [WIDTH-1:0] y
);
endmodule把这份声明与顶层一起读入:
yosys -Q -T -p 'read_verilog top.v blackbox.v; hierarchy -check -top top; check; stat'复跑记录显示,check 报告 0 个问题,stat 中顶层仍保留一个 vendor_adder cell:
3. Executing HIERARCHY pass (managing design hierarchy).
3.1. Analyzing design hierarchy..
Top module: \top
3.2. Analyzing design hierarchy..
Top module: \top
Removed 0 unused modules.
4. Executing CHECK pass (checking for obvious problems).
Checking module top...
Found and reported 0 problems.
5. Printing statistics.
=== top ===
Number of wires: 3
Number of wire bits: 12
Number of public wires: 3
Number of public wire bits: 12
Number of memories: 0
Number of memory bits: 0
Number of processes: 0
Number of cells: 1
vendor_adder 1
EXIT_CODE=0这里的 0 problems 是明显结构问题检查通过,vendor_adder 1 则证明实例没有被展开成内部逻辑。两项证据恰好说明黑盒契约生效;它们不检查加法结果,也不携带时序、功耗或物理单元信息。后续必须用模块提供方的模型做功能验证,并在映射阶段接入匹配的工艺库。
五、路径二:提供真实实现并复跑
如果这个模块本应参与综合,就换成有模块体的实现,而不是加黑盒属性:
module vendor_adder #(
parameter WIDTH = 4
) (
input wire [WIDTH-1:0] a,
input wire [WIDTH-1:0] b,
output wire [WIDTH-1:0] y
);
assign y = a + b;
endmodule这次增加 proc、opt,让参数化模块展开并优化,再做同样的检查:
yosys -Q -T -p 'read_verilog top.v vendor_adder.v; hierarchy -check -top top; proc; opt; check; stat'真实日志中 hierarchy 为 WIDTH=4 派生参数化模块,优化后的实现里出现一个 $add;这与黑盒路径只留下外部cell有本质差别。
6. Executing CHECK pass (checking for obvious problems).
Checking module $paramod\vendor_adder\WIDTH=s32'00000000000000000000000000000100...
Checking module top...
Found and reported 0 problems.
7. Printing statistics.
=== $paramod\vendor_adder\WIDTH=s32'00000000000000000000000000000100 ===
Number of wires: 3
Number of wire bits: 12
Number of public wires: 3
Number of public wire bits: 12
Number of memories: 0
Number of memory bits: 0
Number of processes: 0
Number of cells: 1
$add 1
=== top ===
Number of wires: 3
Number of wire bits: 12
Number of public wires: 3
Number of public wire bits: 12
Number of memories: 0
Number of memory bits: 0
Number of processes: 0
Number of cells: 1
$paramod\vendor_adder\WIDTH=s32'00000000000000000000000000000100 1
EXIT_CODE=0到这里也只能说通用RTL综合已看到真实逻辑。$add 仍是 Yosys 内部算术单元,不是某个工艺库里的加法宏或标准单元;工艺映射还必须提供目标库,映射失败属于另一类问题,可对照 Yosys 找不到 cell/黑盒模块:ABC 缺库支路。
实验环境
- 机器/系统:Mac mini M4 / macOS 15,Docker 容器内 Linux。
- 工具版本:Yosys 0.33(git sha1 2584903a060),镜像
geek-eda:0.2。 - 日期:2026-10-29。
- 完整命令:未知模块、显式黑盒、真实实现分别执行本文三节展示的
yosys -Q -T -p命令;三者退出码依次为 1、0、0。
代码获取:最小工程、三条路径的
run.sh和真实run1.log位于公开仓experiments/ts-yosys-blackbox-cell-unknown/。安装 Yosys 后运行bash run.sh,脚本会核对三次退出码并打印最终 PASS。
这一篇在知识体系里的位置
本篇属于 开源 EDA 报错排查总览 的“层级契约”节点:意外漏读源文件见 Yosys 找不到 cell/黑盒模块:子模块未声明,进入ABC工艺映射后缺真实库则见 Yosys 找不到 cell/黑盒模块:ABC 缺库支路。三篇的分界分别是定义是否存在、是否有意留白、是否具备物理映射输入。
总结
Yosys 找不到 cell/黑盒模块时,先确认 hierarchy 缺少哪个定义,再按设计意图修复:外部单元读入 (* blackbox *) 接口,内部逻辑读入真实实现。黑盒路径的 check 0 problems 和保留cell只证明层级契约成立;真实实现路径出现 $add 才说明内部逻辑进入网表,两者都不能单独证明功能正确或已映射到物理单元。