ARTICLE · 1089117
Verilator 源码深度剖析:内部组件、关系与执行流程
摘要:本文从源代码层面深入剖析 Verilator 的内部架构,涵盖其目录结构、核心类体系(V3Global、V3Options、AstNode、V3Number、V3Graph 等)、编译管线的四大阶段(前端 → 语义分析 → 变换优化 → 后端代码生成),以及 ~50+ 个 AST 变换 Pass 的执行流程。全文以大量流程图、列表和表格为主,每个流程图后均配有列表说明,适合希望理解 Verilator 内部工作机制或准备参与贡献的开发者阅读。
目录:
• 📁 目录结构一览 • 🏛️ 核心组件体系 • V3Global:全局状态中心 • V3Options:配置状态中心 • AstNode:AST 节点基类 • V3Number:四值逻辑数值系统 • V3Graph:图算法基础设施 • 核心组件全景关系图 • ⚙️ 编译管线:四大阶段 • 入口点与初始化 • 阶段一:前端(文本 → AST) • 阶段二:语义分析与展开 • 阶段三:变换与优化 Pass • 阶段四:后端代码生成 • 🔄 变换 Pass 的详细执行序列 • 🧩 Pass 执行架构:Visitor 模式 • 🎯 总结
📁 目录结构一览
Verilator 的源代码组织清晰,各目录职责分明:
bin/ | verilator |
include/ | verilated*.h、verilated*.cpp、verilated.mk) |
src/ | |
test_regress/ | |
examples/ | hello_world_c、hello_world_sc 等) |

📋 说明:
• 根节点 ROOT:代表 Verilator 源码仓库的根目录,所有其他目录都从它展开。• bin/目录:• verilator:用户直接调用的 Perl 包装脚本,负责设置环境变量。• verilator_bin:真正执行编译的核心二进制。• verilator_bin_dbg:调试版本,保留更多断言与调试符号。• src/目录:• V3*.cpp/.h:翻译器的全部核心源代码。• verilog.y:Bison 语法描述文件,定义 Verilog 语法规则。• verilog.l:Flex 词法描述文件,定义 Token 识别规则。• include/目录:• verilated.h:仿真运行时核心头文件,用户 App 必须包含。• verilated.mk:生成的 Makefile 会包含此文件,统一构建规则。• verilated_vcd_c.h:VCD 波形输出支持。• 其他目录: • test_regress/:内部回归测试,保证每次提交不破坏现有功能。• examples/:入门示例,包含 C 与 SystemC 两种风格。• docs/:文档源文件,生成官网上的手册。• bin/verilator:Perl 包装脚本,负责命令参数处理、设置VERILATOR_ROOT环境变量、可选地在调试器中包装执行,然后调用真正的二进制verilator_bin(或调试模式下的verilator_bin_dbg)。• include/:包含全局例程和头文件,用户编译生成的 C++ 模型时需要将这些文件加入编译器的-I路径。• src/:Verilator 翻译器的全部核心源代码,所有V3*开头的文件都在此。• 输出目录:所有生成的文件放在 --Mdir指定的目录中,默认为obj_dir。
🏛️ 核心组件体系
Verilator 的内部实现围绕几个核心类展开,它们构成了整个编译器的骨架。

📋 说明:
• 🌐 全局状态层: • V3Global:全局单例,持有 AST 根节点与所有全局配置。• V3Options:存储命令行解析结果,约 150+ 个选项变量。• 两者关系: V3Global包含V3Options。• 🌳 AST 层: • AstNode:所有 AST 节点的抽象基类。• AstNetList:整棵 AST 的根节点。• AstModule:表示一个 Verilog 模块。• AstVar:表示信号 / 变量。• AstAlways:表示always过程块。• 🔧 工具层: • V3Number:四值逻辑数值系统,用于编译期常量计算。• V3Graph:通用有向图框架,用于数据流分析。• FileLine:源码位置追踪,用于错误报告。• ⚙️ 变换 Pass 层: • VNVisitor:所有 Pass 的基类。• V3Width:宽度推断。• V3Const:常量传播。• V3Order:执行顺序排序。• 📤 后端层: • V3EmitC:C++ 代码发射器,遍历 AST 输出最终代码。• 关键依赖关系: • V3Global持有 AST 根节点。• AstNode使用V3Number表示常量。• VNVisitor遍历AstNode,并构建V3Graph。• V3EmitC遍历 AST 树根进行代码发射。
V3Global:全局状态中心
V3Global 是整个 Verilator 程序的顶层类,作为全局单例(实例名为 v3Global)存在。
• 核心成员: • m_rootp:指向 AST 的根节点AstNetList。• opt:包含V3Options对象,存储所有命令行选项和配置状态。• 关键方法: • boot():初始化子系统。• readFiles():读取并解析输入文件。• 使用模式:在 Verilator 代码中,任何地方都可以通过 v3Global访问全局状态。

📋 说明:
• 单例 VG(V3Global):整个程序生命周期只有一个实例,任何地方都能访问。• 成员 m_rootp:指向 AST 根节点,编译全过程围绕它进行。• 成员 opt:指向V3Options,所有配置从这里读取。• 方法 boot():由main()调用,初始化全局子系统。• 方法 readFiles():由main()调用,读取并解析源文件。• 访问者 ANY:任意 V3 代码都可以通过v3Global.rootp或v3Global.opt访问全局状态。• 外部产物: • AST 树:由 m_rootp指向。• 编译选项:由 opt指向。
V3Options:配置状态中心
V3Options 是 Verilator 的配置中心,使用 Pimpl(Pointer to Implementation)模式隐藏实现细节,包含约 150+ 个成员变量表示不同的配置设置。
• 核心职责: • 解析命令行参数(通过 V3OptionParser)。• 存储所有选项值(如 --cc、--exe、--trace等)。• 提供配置查询接口。 • 访问方式:通过 v3Global.opt访问单例。

📋 说明:
• 输入 CMD:用户在命令行输入的所有参数。• 解析器 VP(V3OptionParser):负责把命令行拆解成结构化选项。• 核心 VO(V3Options):解析后的配置单例,所有模块都从这里读取配置。• 配置项示例: • --cc:选择 C++ 代码生成模式。• --exe:生成可执行文件。• --trace:启用波形追踪。• --top-module:指定顶层模块。• --Mdir:指定输出目录。• ... 150+ 选项:还有大量其他选项。• 消费者: • V3Width:宽度推断时读取配置(如是否有符号扩展)。• V3Order:排序时读取配置(如是否需要多线程)。• V3EmitC:发射代码时读取配置(如输出目录、文件命名)。
AstNode:AST 节点基类
AstNode 是 Verilator 抽象语法树中所有节点的抽象基类,是整个编译过程中核心的中间表示。
• 节点链接结构: • op1p()~op4p():四个子节点指针,用于表示操作数或子语句。• nextp():指向下一个兄弟节点。• backp():指向父节点或前一个兄弟节点。• 类型系统: • type():返回VNType枚举值,标识具体节点子类。• dtypep():指向AstNodeDType,描述节点值的数据类型。• 源码追踪: • fileline():返回FileLine*对象,追踪源文件和行号。• 类型检查宏(避免 RTTI 开销): • VN_IS(nodep, NodeType):类型判断。• VN_CAST(nodep, NodeType):类型转换。• VN_AS(nodep, NodeType):断言类型并转换。

📋 说明:
• 根基类 AstNode:所有 AST 节点的共同祖先,提供统一的类型系统与链接机制。• 子类分类: • AstNetList:整个 AST 的根节点。• AstModule:表示一个 Verilog 模块。• AstNodeExpr:所有表达式的基类,如常量、加法、位选择。• AstNodeStmt:所有语句的基类,如always、if、赋值。• AstNodeDType:数据类型描述节点。• 表达式子类: • AstConst:编译期常量(值存在V3Number中)。• AstAdd:加法运算。• AstSel:位选择(如a[3:0])。• 语句子类: • AstAlways:always块。• AstIf:条件语句。• AstAssign:赋值语句。• 继承层次: AstNode是所有节点的祖先,AstNodeExpr和AstNodeStmt是两大分支。
AST 节点链接结构示意图:

📋 说明:
• 根节点 N1(AstNetList):整棵树的入口。• 模块节点 N2(AstModule):根节点的唯一子模块。• 变量链: N3(clk)→N4(rst)→N5(count),通过nextp连接成兄弟链表。• 过程块 N6(AstAlways):位于变量链之后。• if语句N7:always块的子节点。• 赋值语句 N8(AstAssign):if语句的子节点。• backp反向链接:N2指向N1,N3指向N2,N4指向N3,形成双向链表。• nextp虚线箭头:表示兄弟节点的横向链接。• 实线箭头:表示父子节点的纵向链接。
V3Number:四值逻辑数值系统
V3Number 是 Verilator 内部的数值表示系统,在编译期常量折叠和 AST 中表示常量值。
• 核心能力: • 任意精度整数运算(宽度可配置)。 • 四值逻辑(0、1、X、Z)表示。 • 64 位 IEEE 754 浮点数支持。 • 字符串支持。 • 存储策略(按位宽优化): • 内联存储:宽度 ≤ MAX_INLINE_WIDTH(通常 128 或 256 位)。 • 动态存储:宽度更大的数字使用动态分配的向量。 • 字符串存储:字符串类型存储在 m_string成员中。• 四值逻辑编码:使用双比特编码。 • 00→ 逻辑 0• 10→ 逻辑 1• 01→ Z(高阻)• 11→ X(未知)

📋 说明:
• 核心 NUM(V3Number):任意精度数值表示。• 判断 MODE:根据位宽选择存储策略。• 三种存储策略: • INLINE:位宽较小,直接栈上存储,避免堆分配。• DYN:位宽较大,堆分配向量。• STR:字符串类型,存储在m_string成员。• 四值编码 ENC:• 00:逻辑 0。• 10:逻辑 1。• 01:Z(高阻)。• 11:X(未知)。• 运算符重载 OPS:• OP1算术运算(加减乘除)。• OP2位运算(与或非异或)。• OP3比较运算(大小相等)。• OP4浮点运算。
V3Graph:图算法基础设施
V3Graph 是 Verilator 提供的通用有向图框架,许多优化 Pass 使用图算法来分析数据流并确定安全的变换。
• 核心类: • V3Graph:图容器,管理顶点和边。• V3GraphVertex:顶点基类。• V3GraphEdge:边基类。• 典型用途: • 数据流分析(依赖图构建)。 • 拓扑排序(确定 eval()中语句的执行顺序)。• 弱连通分量分析。 • 输出:支持 GraphViz dot 格式输出,便于可视化。

📋 说明:
• 核心 VG(V3Graph):图容器,管理所有顶点和边。• 顶点与边: • VV(V3GraphVertex):顶点基类,所有顶点继承自此。• VE(V3GraphEdge):边基类,所有边继承自此。• 三种典型用途: • U1数据流分析:构建依赖图,分析信号之间的依赖关系。• U2拓扑排序:确定eval()中语句的执行顺序。• U3弱连通分量:拆分逻辑块以便并行执行。• 输出: • ORDER:拓扑排序结果,决定 C++ 代码中语句顺序。• DOT:GraphViz dot 格式文件,可用图形工具可视化依赖图。
核心组件全景关系图

📋 说明:
• 🌐 顶层控制层: • main():程序入口。• process():编译主流程,负责编排各阶段。• ⚙️ 全局状态层: • V3Global:全局单例,持有 AST 与配置。• V3Options:命令行解析结果。• main()调用process(),process()通过V3Global访问所有状态。• 🌳 AST 中间表示层: • AstNetList:树根,V3Global持有。• AstModule:模块节点。• AstVar、AstAlways:模块内的变量与过程块。• AstNodeStmt、AstNodeExpr:语句和表达式基类。• 🔧 工具支撑层: • V3Number:数值系统,被多个 Pass 使用。• V3Graph:图框架,用于数据流分析。• FileLine:源码位置追踪,用于错误报告。• ⚙️ Pass 变换层: • VNVisitor:所有 Pass 的基类,遍历 AST。• V3Param、V3Width、V3Const、V3Order:典型 Pass。• VNVisitor遍历 AST 根节点,并使用V3Number与V3Graph。• 📤 后端发射层: • V3EmitC:遍历 AST 树根,使用V3Number发射最终 C++ 代码。
⚙️ 编译管线:四大阶段
Verilator 的编译管线分为四个顺序执行的阶段,从 Verilog/SystemVerilog 源代码到最终的可执行仿真模型。

📋 说明:
• 🚪 入口点: • bin/verilator:用户命令行调用的 Perl 脚本。• verilator_bin:真正执行的二进制。• main():C++ 程序入口。• V3Global::boot():初始化全局状态。• process():进入编译主流程。• 📝 阶段一:前端: • V3PreProc:预处理,处理宏与包含。• V3PreLex:基于 Flex 的词法分析。• V3ParseBison:基于 Bison 的语法分析。• 输出: AST抽象语法树。• 🔍 阶段二:语义分析: • Link:链接引用。• V3Param:参数展开。• V3Width:宽度推断。• Elaboration:设计展开。• ⚡ 阶段三:变换优化: • ~50+ 变换 Pass:一系列 AST 变换。• V3Order:调度排序。• 📤 阶段四:后端: • V3EmitC:C++ 代码发射。• 输出: .cpp/.h/.mk文件。• 阶段间数据流: process()⇒ 前端 ⇒ AST ⇒ 语义分析 ⇒ 展开后 AST ⇒ 变换 ⇒ 优化后 AST ⇒ 后端 ⇒ 文件。
四大阶段数据流全景:

📋 说明:
• 输入 SRC:.v或.sv源代码文件。• 中间 AST 表示: • A1:原始 AST(前端输出)。• A2:展开后 AST(语义分析输出)。• A3:优化后 AST(变换优化输出)。• 输出 OUT:.cpp/.h/.mk文件。• 前端数据: • T1:Token 流。• T2:原始 AST。• 语义分析数据: • T3:位宽信息。• T4:参数绑定。• 优化数据: • T5:常量折叠结果。• T6:执行顺序图。• 虚线箭头:表示数据的辅助流动方向。
入口点与初始化
• bin/verilator(Perl 包装脚本):• 处理命令行参数。 • 设置 VERILATOR_ROOT环境变量。• 可选地在调试器(gdb、valgrind、rr)中包装执行。 • 调用核心二进制 verilator_bin(或verilator_bin_dbg)。• src/Verilator.cpp::main():• 初始化 V3Options解析命令行参数。• 创建 V3Global单例存储全局状态。• 调用 V3Global::boot()初始化子系统。• 调用主函数 process()。

📋 说明:
• 输入 START:用户输入的命令行,例如verilator --cc top.v。• Perl 脚本 PERL:bin/verilator,进行环境配置。• 环境变量 ENV:设置VERILATOR_ROOT,让核心二进制找到运行时文件。• 调试分支 DBG:• 是:走 DBGBIN(verilator_bin_dbg),可被 gdb/valgrind 调试。• 否:走 BIN(verilator_bin),普通执行。• 核心入口 MAIN:Verilator.cpp::main()函数。• 参数解析 PARSE:V3Options解析命令行,生成配置。• 单例初始化 INIT:创建V3Global,全局状态就绪。• 子系统启动 BOOT:V3Global::boot()初始化各子系统。• 主流程 PROC:调用process(),进入四大编译阶段。
阶段一:前端(文本 → AST)
前端将文本形式的 HDL 转换为抽象语法树(AST),分为三个子步骤:
V3PreProc | V3PreProc.cpp | include、define、ifdef 等指令,展开宏,管理条件编译 | |
V3PreLex | verilog.l | ||
V3ParseBison | verilog.y |
前端处理流程图:

📋 说明:
• 输入 SRC:top.v源代码文件。• 预处理器 PP(V3PreProc):• PP1:处理include指令,插入被包含文件。• PP2:展开define宏。• PP3:处理条件编译ifdef/ifndef/else/endif。• 输出: TOKToken 流。• 词法分析 LEX(V3PreLex):• 基于 Flex 实现。 • 输出多种 Token 类型: • T1:yaINTNUM整数常量。• T2:yaID__ETC标识符。• T3:yaSTRING字符串。• T4:运算符 Token。• 语法分析 PARSE(V3ParseBison):• 基于 Bison 实现。 • 从 Token 流构造 AST 节点。 • AST 节点输出: • N1:AstModule,模块节点。• N2:AstVar,变量节点。• N3:AstAlways,过程块。• N4:AstAssign,赋值语句。• 最终输出 AST:完整的抽象语法树。• 预处理:维护 FileLine对象进行文件和行号追踪。• 词法分析:返回 yaINTNUM、yaID__ETC、yaSTRING等 token,支持基于状态的扫描以适应不同语言上下文。• 语法分析:创建专门的节点类型( AstModule、AstVar、AstAlways等),管理解析状态。
阶段二:语义分析与展开
• 链接(Link):AST 中的 cell 被链接,读取并解析额外文件,函数、变量引用被链接到定义。 • 参数解析:参数被解析,设计被展开。 • 宽度推断(V3Width):为所有表达式计算位宽,是最复杂的 Pass 之一,处理 SystemVerilog 复杂的类型传播规则。

📋 说明:
• 输入 AST:前端生成的原始 AST。• 链接 LINK:解析所有引用,读取被包含文件,将变量/函数引用链接到定义。• 参数展开 PARAM(V3Param):为每个参数组合克隆模块,消除参数化。• 宽度推断 WIDTH(V3Width):• W1:插入AstCCast,处理类型转换。• W2:插入AstExtend,处理符号/零扩展。• W3:插入AstSel,处理位提取。• WIDTHC(V3WidthCommit):提交宽度推断结果。• 展开 ELAB:生成完整的层次结构,将高层描述展开为低层逻辑。• 输出 AST2:展开后 AST,准备进入变换优化阶段。
阶段三:变换与优化 Pass
Verilator 在 AST 上执行~50+ 个顺序变换 Pass,每个 Pass 实现为一个独立的 Visitor 类,遍历并修改 AST。
阶段四:后端代码生成
• V3EmitC:C++ 代码发射子系统的主协调器。 • 多个专门的发射类生成 C++ 模型的不同方面: emitc()、emitcInlines()、emitcSyms()、emitcTrace()等。• 最终输出 .cpp、.h文件和构建系统文件(Makefile)。

📋 说明:
• 输入 AST:变换优化后的 AST。• 协调器 EMITC(V3EmitC):代码发射主协调器,按类别调用不同发射器。• 六大发射器: • E1(emitc()):主 C++ 代码,输出Vtop.cpp与Vtop.h。• E2(emitcInlines()):内联函数,输出Vtop__Inlines.h。• E3(emitcSyms()):符号表,输出Vtop__Syms.cpp/.h。• E4(emitcTrace()):波形追踪代码,输出Vtop__Trace.cpp/.h。• E5(emitcMakefile()):构建规则,输出Vtop.mk。• E6(emitcCells()):单元层次,输出Vtop__Cell.h。• 输出文件: • OUT1~OUT7:最终用户可编译的文件集合。
🔄 变换 Pass 的详细执行序列
以下是 Verilator 编译管线中主要变换 Pass 的执行序列,按阶段分组:
| 展开完成 | V3ParamV3Width、V3WidthCommit | |
| 插桩 | V3CoverageV3Assert、V3Randomize | |
| 结构变换 | V3InstV3Scope、V3Inline、V3Task | |
| 逻辑优化 | V3ConstV3Gate、V3Unknown、V3Tristate | |
| 调度排序 | V3ActiveV3Delayed、V3Order | |
| 代码准备 | V3ExpandV3Premit、V3Depth、V3Descope |
完整 Pass 序列流程图:

📋 说明:
• 输入 START:展开后 AST,从语义分析阶段进入。• 前置 LINK(V3LinkResolve):符号解析,链接所有引用。• 📦 插桩阶段 G1:• V3Coverage:插入覆盖率统计代码。• V3Assert:插入断言检查。• V3Randomize:插入随机化逻辑。• 🏗️ 结构变换阶段 G2:• V3Inst:实例展开(消除模块实例化)。• V3Scope:作用域展平(消除层次结构)。• V3Inline:模块内联。• V3Task:任务展开。• ⚡ 逻辑优化阶段 G3:• V3Const:常量折叠。• V3Gate:门级优化。• V3Unknown:X 消除(四值转二值)。• V3Tristate:三态消除。• V3Const(再次):第二次常量折叠,处理新暴露的常量。• 📐 调度排序阶段 G4:• V3Active:拆分always块为 active 区域。• V3Delayed:处理非阻塞赋值的延迟语义。• V3Order:确定eval()内的执行顺序。• 📝 代码准备阶段 G5:• V3Expand:展开复杂表达式。• V3Premit:预提交优化。• V3Depth:计算表达式深度。• V3Descope:去除作用域信息。• 输出 DONE:优化完成的 AST,准备进入后端发射。• V3Param:通过为每个唯一的参数组合创建专门的克隆来消除参数化模块。必须在大多数其他变换之前执行,因为参数影响信号位宽、数组大小和条件生成块。 • V3Width:执行类型推断和位宽计算,插入 AstCCast进行类型转换,添加AstExtend进行符号/零扩展,当位宽不匹配时添加AstSel进行位提取。• V3Const:在编译的不同阶段多次调用,执行常量折叠和传播。 • V3Inst:分两阶段进行实例展开—— dearrayAll()移除 cell 数组,instAll()将模块实例转换为线网赋值。
🧩 Pass 执行架构:Visitor 模式
所有变换 Pass 都使用 Visitor 设计模式遍历 AST。
• 基类:每个 Pass 继承 VNVisitor基类,并为特定的 AST 节点类型实现visit方法。• 主执行循环:变换序列由 Verilator.cpp::process()编排。• 优势: • 每个 Pass 只需关注自己关心的节点类型。 • 通过 Visitor 模式实现 AST 的解耦遍历。 • 新 Pass 的添加不影响现有 Pass。
Visitor 模式类关系图:

📋 说明:
• 节点基类 AstNode(抽象):• 提供 op1p()~op4p()四个子节点指针。• nextp()/backp()用于兄弟与父节点链接。• type()返回节点类型(VNType枚举)。• dtypep()返回数据类型描述。• fileline()返回源码位置。• 表达式基类 AstNodeExpr(抽象):所有表达式的祖先,提供width()方法。• 语句基类 AstNodeStmt(抽象):所有语句的祖先。• 访问者基类 VNVisitor(抽象):• visit(AstNode*):处理节点。• iterate(AstNode*):遍历节点。• iterateChildren(AstNode*):遍历子节点。• 典型 Pass: • V3Width:实现visit(AstAdd*)、visit(AstVar*)、visit(AstConst*)。• V3Const:实现visit(AstAdd*)、visit(AstMul*)、visit(AstSel*)。• V3Order:实现visit(AstAlways*)、visit(AstAssign*)。• V3EmitC:实现visit(AstNetList*)、visit(AstModule*)。• 继承关系( <|--):所有 Pass 继承自VNVisitor,所有节点继承自AstNode。• 依赖关系( ..>):VNVisitor依赖AstNode进行遍历。
Pass 编排与 Visitor 遍历流程:

📋 说明:
• 参与者 PROC(process()):主控流程,顺序调用各 Pass。• 参与者 AST:被所有 Pass 遍历和修改。• 步骤 1-2: PROC调用V3Param,后者克隆参数化模块并返回。• 步骤 3-4: PROC调用V3Width,后者计算位宽并插入 Cast。• 步骤 5-6: PROC调用V3Const,后者折叠常量表达式。• 步骤 7-8: PROC调用V3Order,后者确定执行顺序。• 步骤 9-10: PROC调用V3EmitC,后者遍历 AST 生成 C++ 代码。• -->>虚线:表示返回控制权给PROC。
Visitor 遍历 AST 的详细展开图:

📋 说明:
• 访问者 VIS(VNVisitor):从 AST 根节点开始遍历。• 遍历顺序: • ROOT(AstNetList):遍历根。• M1(AstModule):进入模块。• V1(AstVar clk)→V2(AstVar rst)→V3(AstVar count):按nextp横向遍历变量。• A1(AstAlways):进入过程块。• IF(AstIf):进入条件语句。• AS1(AstAssign count=0):then 分支。• AS2(AstAssign count=count+1):else 分支。• visit方法处理(虚线箭头):VIS对每个节点调用对应的visit方法,进行具体处理。• 实线箭头:表示遍历路径( iterate与iterateChildren)。• 虚线箭头:表示访问者对节点的具体处理。
🎯 总结
完整编译流程一图总览:

📋 说明:
• 输入 SRC:Verilog/SystemVerilog 源代码。• 📝 前端 FE:预处理 + 词法 + 语法分析。• 内部组件: V3PreProc、V3PreLex、V3ParseBison。• 输出: AST1原始 AST。• 🔍 语义分析 ME:链接 + 参数展开 + 宽度推断 + 展开。• 内部组件: V3Param、V3Width、V3WidthCommit。• 输出: AST2展开后 AST。• ⚡ 变换优化 OPT:~50+ 个 Pass。• 内部组件: V3Const、V3Gate、V3Order。• 输出: AST3优化后 AST。• 📤 后端发射 BE:C++ 代码生成。• 内部组件: V3EmitC、V3EmitCFunc、V3EmitCMake。• 输出: FILES(.cpp/.h/.mk)。• 🔨 编译 COMPILE:GCC/Clang 编译生成的 C++ 代码。• 🚀 最终产物 EXE:可执行仿真器。• 目录结构: bin/(包装脚本)、src/(核心源代码)、include/(运行时头文件)、test_regress/(回归测试)。• 核心类体系: • V3Global:全局单例,持有 AST 根节点和配置。• V3Options:配置中心,150+ 个选项变量。• AstNode:AST 基类,四子指针 + next/back 链接,VNType 类型系统。• V3Number:四值逻辑数值系统,内联/动态/字符串三种存储策略。• V3Graph:通用有向图框架,用于数据流分析和拓扑排序。• 编译管线: 1. 前端:预处理 → 词法分析(Flex)→ 语法分析(Bison)→ AST。 2. 语义分析:链接 → 参数展开 → 宽度推断 → 展开。 3. 变换优化:~50+ 个 Pass,按依赖关系顺序执行。 4. 后端:V3EmitC 协调多个发射类生成 C++ 代码。 • Pass 架构:Visitor 模式,每个 Pass 继承 VNVisitor,由process()统一编排。
📚 参考资源
• Verilator Internals Manual:https://verilator.org/guide/latest/internals.html • Verilator 官方文档:https://verilator.org/guide/latest/ • GitHub 仓库:https://github.com/verilator/verilator • DeepWiki Verilator 文档:https://deepwiki.com/verilator/verilator