Yosys 脚本文件:.ys 分节组织、-s 执行与 show 出图完整走法
更新时间:2026-11-04。前一篇 Yosys 第一次综合完整流程 把六条命令在终端里逐条敲了一遍,本文解决工程化的下一步:命令多了以后怎么收进一个脚本文件反复执行、怎么分节加注释让别人看得懂、怎么把电路结构导出成图。
synth宏命令内部到底做了什么不是本篇重点,见 synth 命令拆解,全簇索引在 EDA 知识目录。
本文要回答的问题
- Yosys 的
.ys脚本文件用什么语法,注释怎么写,怎样一次执行整份脚本? - 多文件、多模块的工程,脚本按什么顺序组织才不乱?
show命令怎么在没有图形界面的环境里把电路导出成图?- 脚本跑完会产出哪些文件,各自长什么样?
先给一张封面卡,本文的脚本就是五节制:
读这张卡注意一个刻意安排:结构图导了两次,一次在 hierarchy 之后、synth 之前,一次在综合之后。两张图一对照,粗粒度算子怎么被拆成门,肉眼可见。
一、这一步在数字设计流程里的位置
脚本文件本身不改变综合的工序,它改变的是「人与 Yosys 的交互方式」。上游仍是若干份 .v RTL,下游仍是通用门网表;脚本只是把这条链路固化成一个可复跑、可进 Makefile、可进版本管理的文本文件:
图里绿色是输入输出,橙色是唯一需要人工编写和维护的东西——run.ys,蓝色是非交互执行,灰色是派生物。综合在概念上的三段式(翻译、优化、工艺映射)背景知识见 综合是什么。
二、.ys 脚本逐段解读:语法、分节与参数
本次的设计是两层结构:子模块 adder 是参数化位宽的加法器,顶层 acc 例化它做 4 位累加。脚本 run.ys 全文如下:
# ---- 第 1 节:逐个读入 RTL 文件(被例化的子模块放前面)----
read_verilog adder.v
read_verilog acc.v
# ---- 第 2 节:确定顶层,展开参数并检查例化完整性 ----
hierarchy -top acc -check
# 先画一张 RTL 级结构图($add 等粗粒度算子原样可见)
show -format dot -prefix acc_rtl
# ---- 第 3 节:一条宏命令完成 proc/opt/techmap 全流程 ----
synth -top acc
# ---- 第 4 节:打印统计,再画一张通用门级结构图 ----
stat
show -format dot -prefix acc_gate
# ---- 第 5 节:把当前设计写成门级网表落盘 ----
write_verilog -noattr netlist.v脚本语法只有三条规则:一行一条命令,# 到行尾是注释,空行随意;执行用 yosys -s run.ys,-s 即 script,按行顺序跑、遇错即停。与之相对的是 yosys -p 'cmd1; cmd2' 内联方式,适合一两条命令的临时调用,命令一多就该进文件。各命令关键参数如下:
| 命令 | 关键参数 | 本节为什么这样写 |
|---|---|---|
read_verilog | -sv 切 SystemVerilog;-formal 放宽可综合子集 | 两个文件分两行写,比一条命令带多文件更易在日志里定位出错文件 |
hierarchy | -top <名> 指定顶层;-check 例化完整性检查 | 参数化设计靠它把 W 实参展开成专用模块,-check 对漏文件直接报错 |
show | -format dot 只出文本不起图形界面;-prefix <名> 指定文件名 | 容器和服务器上没有显示器,默认的弹出窗口模式必然失败 |
synth | -top acc 内部再定一次顶层;-flatten 打平层次 | 想在图里保留 acc 例化 adder 的层次,故不加 -flatten |
stat | 无参数只看不改 | 出图前留一份门数证据 |
write_verilog | -noattr 不写综合属性注释 | 产物干净,交付给下游工具 |
分节注释的实际收益在日志里就能看到:Yosys 会把命令自动编号,本次运行的日志里第 1、2 节对应 1. 到 4.(含第一次 show),synth 一条命令内部展开成 5.1 到 5.26 二十多个子阶段——脚本层面是五节,执行层面是几十个 pass,注释帮你在这份长日志里快速对回脚本位置。
三、输入输出文件:吃什么、吐什么、长什么样
输入是两份共三十余行的 RTL。产物有三类。第一类是网表 netlist.v,顶层里已经没有行为描述,四段 always 各是一个带使能的触发器原语,加法器被展开成异或加进位链:
always @(posedge clk, negedge rst_n)
if (!rst_n) q[0] <= 1'h0;
else if (en) q[0] <= next[0];
assign _01_ = ~(a[0] & b[0]);
assign y[1] = ~(_01_ ^ _00_);注意网表里子模块的名字:$paramod\adder\W=s32'0...100。这是 hierarchy 做参数展开的结果——通用模板 adder 被例化成一个位宽锁定为 4 的专用副本,原模板随即被当作未使用模块删除。
第二类是两份 Graphviz 文本。acc_rtl.dot 只有 45 行,综合前的图里 u_add 还是一个完整的子模块方框;acc_gate.dot 有 172 行,加法器内部的每个门都是一个 record 节点,且每个模块单独一页:
digraph "$paramod╲adder╲W=...0100" {
c17 [ shape=record, label="{{<p14> A|<p15> B}|$152\n$_XOR_|{<p16> Y}}", ];第三类是 PNG,由 graphviz 渲染:dot -Tpng -o acc_gate.png acc_gate.dot。本文使用的容器镜像内 graphviz 为 2.43.0,渲染时除写入 -o 指定的文件外还会向标准输出再吐一份 PNG 二进制,终端调用时记得加 >/dev/null,否则日志会被二进制冲花。
四、常见错与检查点
脚本化之后的高频问题集中在四处:
| 现象 | 先查什么 | 纠正 |
|---|---|---|
yosys -s 报找不到命令或脚本根本没按预期执行 | 是否误用了 -p;脚本文件是否带 BOM 或 CRLF 行尾 | 文件方式固定用 -s;Windows 编辑过的文件先转 UTF-8 无 BOM、LF 行尾 |
| hierarchy 报模块缺失、有例化无实体 | -check 的输出与文件读入顺序 | 被例化模块先 read_verilog,机理见 hierarchy check 失败;文件路径问题见 Can't open input file |
show 报 xdot 找不到或卡住等显示 | 是不是没给 -format dot | 无显示器环境一律 show -format dot -prefix 名字,再用 dot 渲染 |
| 日志里出现同一模块的两份统计、门数对不上 | 是否重复 read_verilog 同一文件 | 每个文件只读一次,重复读入的症状与处理见 duplicate module definition |
一个脚本组织上的检查点:产物文件名全部用 -prefix/输出参数显式指定,不要依赖默认名。默认前缀通常是 ~yosys_show 这类隐藏文件,换人复跑时极易漏捡。
五、真实跑一遍:从脚本到两张图
在 Yosys 0.33 容器内执行 yosys -s run.ys。日志开头能直接对上脚本的前三节——两次读入各自成功,hierarchy 完成参数化展开并删掉通用模板,第一次 show 落盘:
日志第 60 行的 Removing unused module '\adder' 不是错误而是预期行为:参数展开后通用的 adder 已无人引用。脚本末尾的统计与第二次出图如下:
整份设计最终是 21 个通用门单元:4 个带使能触发器 $_DFFE_PN0P_,加上 XOR 4、XNOR 3、NAND 4、AND 与 ANDNOT 共 6 个组合门;其中参数化加法器副本占 14 个,顶层占 8 个(含 1 个子模块例化),层次合计 21。check pass 报告 0 个问题,随后 acc_gate.dot 按两个模块分两页输出,write_verilog 完成后端写出。stat 各字段的读法在 stat 报告阅读,网表本身的格式细节在 write_verilog 网表导出。
实验环境
- 机器/系统:macOS(Darwin 25.5,Apple Silicon),综合与出图均在 Docker 容器内执行
- 工具版本:Yosys 0.33 (git sha1 2584903a060)、graphviz dot 2.43.0 (0),镜像 geek-eda:0.4-flow(
yosys -V与dot -V照抄) - 日期:2026-11-04
- 完整命令:
docker run --rm -v "$PWD":/work -w /work geek-eda:0.4-flow yosys -s run.ys,随后容器内dot -Tpng -o acc_rtl.png acc_rtl.dot >/dev/null与dot -Tpng -o acc_gate.png acc_gate.dot >/dev/null;等价于实验目录下make run
代码获取
完整 RTL、分节脚本与 Makefile 已同步到公开仓库:geek-doc.cn/experiments/flow-yosys-script-file,克隆后进入该目录执行 make run 即可复现两份 stat、两份 dot 与门级网表,make clean 删除全部派生物;本机原生装有 Yosys 与 graphviz 时可用 make run RUN="" 直接运行。
这一篇在知识体系里的位置
- 第一次接触 Yosys、想看六条命令逐条做了什么:Yosys 第一次综合完整流程;
- 好奇
synth一条宏里二十多个子阶段的顺序:synth 命令拆解; - 想读懂 stat 输出的每一行:stat 报告阅读;交付网表的写法:write_verilog 网表导出;
- 脚本跑不通时按报错对位:文件读入失败看 Can't open input file,例化缺失看 hierarchy check 失败。
总结
Yosys 脚本文件就是把命令按「一行一条、# 注释分节」的规则收进 .ys 文本,用 yosys -s 批量执行;多模块工程按「读入 → hierarchy -top -check 定顶查完整 → synth -top 综合 → stat 看数 → write_verilog 落盘」分五节组织,并在综合前后各插一条 show -format dot -prefix,就能在无显示器的容器或服务器上用 graphviz 的 dot 渲染出 RTL 级与门级两张结构图对照着看。本文的两层参数化设计真实跑出 21 个通用门、两页 dot 与一份网表;记住三个工程化细节:被例化模块先读入、无图形界面必须给 -format dot、产物名一律显式指定。