【IC】综合AST示例
AST 可以先粗暴理解成:
“把 Verilog 源码从字符串,变成一棵有层次的语法树。”
它还很像原始代码结构,还没变成门级网表,也还没变成 mux/dff 图。
在 Yosys 里,Verilog frontend 会先把源码变成内部 AST;这个 AST 由很多 AST::AstNode 组成,每个节点至少有:节点类型、子节点、属性、节点内容、源代码位置。Yosys 文档还明确说,这个 AST “closely resembles the structure of the original Verilog code”。([yosyshq.readthedocs.io][1])
你可以把它理解成下面三层区别:
- 源码:给人看的文本
- AST:给编译器/综合前端看的“语法树”
- RTLIL / 网表:更像电路结构的数据表示
也就是说,AST 的重点不是“这个电路怎么实现”,而是“这段 Verilog 语法上是什么意思”。后面 simplifier 和 RTLIL generator 才会继续把它降成更接近电路的表示。Yosys 也明确写了:完整 AST 太复杂,不能直接转 RTLIL,要先 simplify。([yosyshq.readthedocs.io][1])
先看一个最简单的例子
源码:
module m(input a, input b, output y);
assign y = a & b;
endmodule
它对应的 AST,概念上大概像这样:
AST_DESIGN
└── AST_MODULE ("m")
├── AST_WIRE ("a") // input
├── AST_WIRE ("b") // input
├── AST_WIRE ("y") // output
└── AST_ASSIGN
├── AST_IDENTIFIER ("y")
└── AST_BIT_AND
├── AST_IDENTIFIER ("a")
└── AST_IDENTIFIER ("b")
这里每个节点都对应一种 Verilog 构造。
Yosys 文档里列得很清楚,比如:
AST_MODULE对应moduleAST_WIRE对应input/output/wire/regAST_ASSIGN对应连续赋值assignAST_IDENTIFIER对应标识符AST_BIT_AND对应按位与&AST_ADD对应+AST_ALWAYS对应alwaysAST_ASSIGN_LE对应非阻塞赋值<=AST_CASE / AST_COND / AST_DEFAULT对应case/条件分支。([yosyshq.readthedocs.io][1])
这个例子里你能看出 AST 的味道:
- 它保留了“
assign y = ...”这种语法层次 - 右边表达式
a & b还是一个表达式树 - 还没有“门”“网表”“布尔优化”这些概念
再看一个更像你关心的时序例子
源码:
module demo (
input logic clk,
input logic rst,
input logic en,
input logic [1:0] a,
input logic [1:0] b,
output logic [1:0] q
);
always_ff @(posedge clk) begin
if (rst)
q <= 2'b00;
else if (en)
q <= a + b;
else
q <= q + 2'b01;
end
endmodule
先忽略 always_ff 和 always 的语法差异,只看“AST 长什么样”。概念上它会像这样:
AST_DESIGN
└── AST_MODULE ("demo")
├── AST_WIRE ("clk")
├── AST_WIRE ("rst")
├── AST_WIRE ("en")
├── AST_WIRE ("a")
├── AST_WIRE ("b")
├── AST_WIRE ("q")
└── AST_ALWAYS
├── AST_POSEDGE
│ └── AST_IDENTIFIER ("clk")
└── AST_BLOCK
└── AST_CASE // if/else 在内部常常会统一成 case/cond 风格
├── AST_COND
│ ├── AST_IDENTIFIER ("rst")
│ └── AST_ASSIGN_LE
│ ├── AST_IDENTIFIER ("q")
│ └── AST_CONSTANT ("2'b00")
└── AST_DEFAULT
└── AST_CASE
├── AST_COND
│ ├── AST_IDENTIFIER ("en")
│ └── AST_ASSIGN_LE
│ ├── AST_IDENTIFIER ("q")
│ └── AST_ADD
│ ├── AST_IDENTIFIER ("a")
│ └── AST_IDENTIFIER ("b")
└── AST_DEFAULT
└── AST_ASSIGN_LE
├── AST_IDENTIFIER ("q")
└── AST_ADD
├── AST_IDENTIFIER ("q")
└── AST_CONSTANT ("2'b01")
这个树里最值得你注意的是:
always还是一个AST_ALWAYS节点posedge clk还是事件节点,比如AST_POSEDGEif / else if / else还是“条件+分支”的语法树q <= a+b还只是“左边是q,右边是一个AST_ADD表达式”
也就是说,在 AST 这一步,工具还在忠实保存“代码长什么样”,而不是“电路应该怎么搭”。这正是 Yosys 所说的:AST 很接近原 Verilog 结构。([yosyshq.readthedocs.io][1])
AST 不是“最终答案”,它只是前端的中间站
接下来 simplifier 会对 AST 做一系列整理,Yosys 文档列出的典型动作包括:
- inline task/function
- 展开
generate - unroll
for - 常量折叠
- 把 primitive 改写成更普通的赋值形式
- 把数组访问改写成
AST_MEMRD/AST_MEMWR,或者在太复杂时改成 signals + cases - 解析 range
- 把
AST_IDENTIFIER绑定到它真正声明的位置。([yosyshq.readthedocs.io][1])
所以对上面那个时序例子,simplify 之后你可以把它理解成:
- “这棵树更规整了”
- 位宽、常量、标识符引用关系都更明确了
- 更适合继续转 RTLIL
然后 genRTLIL() 再把表达式节点递归变成实现这些表达式所需的电路对象;遇到 always/initial 时,则创建 RTLIL::Process,再在后续 pass 中逐步降成 mux、DFF、memory write 等结构。([yosyshq.readthedocs.io][1])
你可以把 AST 理解成“语法骨架”,不是“电路骨架”
这是最关键的一句。
比如这段:
if (en)
q <= a + b;
else
q <= q + 1;
在 AST 里更像:
条件分支
├── 条件:en
├── 真分支:q <= (a+b)
└── 假分支:q <= (q+1)
但在后面的 RTL/netlist 里,它才会变成你熟悉的:
sum1 = a + b
sum2 = q + 1
q_next = MUX(en, sum1, sum2)
q = DFF(q_next)
所以:
- AST 关心语法和作用域
- RTLIL / process 关心赋值语义
- mux/dff 网表关心硬件结构
- AIG 关心统一布尔表示
一个更直观的类比
同一句话:
q <= a + b;
在不同层次看起来完全不一样:
在源码里
是一行文本
在 AST 里
像这样:
AST_ASSIGN_LE
├── AST_IDENTIFIER("q")
└── AST_ADD
├── AST_IDENTIFIER("a")
└── AST_IDENTIFIER("b")
在 RTL/netlist 里
像这样:
tmp = ADD(a, b)
DFF.D = tmp
DFF.Q = q
在 AIG 里
就已经只剩很多个 AND/NOT 节点了
你自己怎么验证 AST
Yosys 文档明确提到,read_verilog 有 -dump_ast 选项,可以直接打印 abstract syntax tree;-yydebug 可以看 parse tree。([yosyshq.readthedocs.io][1])
例如可以试:
yosys -p 'read_verilog -dump_ast demo.v'
你会看到一个比我上面“概念树”更详细的内部打印版本。
最后帮你压成一句话
AST 就是“把 RTL 源码翻译成一棵树形的语法/语义表示”,它仍然保留 module、always、if、<=、+ 这些源码层次;它还不是电路网表,但已经让综合前端可以系统地做 simplify、符号解析、位宽解析,再继续降成 RTLIL、mux/dff 和 AIG。 ([yosyshq.readthedocs.io][1])
1: https://yosyshq.readthedocs.io/projects/yosys/en/0.40/yosys_internals/flow/verilog_frontend.html “The Verilog and AST frontends - YosysHQ Yosys documentation”
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)