3. Xcelium编译与 elaboration 机制

Xcelium 的编译流程与许多仿真器不同,它把“分析(analysis)”和“精化(elaboration)”明确拆成两个阶段。理解这条工具链,是排查“为什么改了代码没生效”“为什么找不到模块”“为什么增量编译没有加速”这类问题的前提。本节围绕 xmvlog、xmvhdl、xmelab 三个核心工具,讲清它们各自做什么、产物放在哪里、选项如何影响结果,以及库映射与增量编译的实际工作机制。

三阶段工具链:分析、精化、仿真

Xcelium 的编译不是一步完成的。Verilog/SystemVerilog 源码先由 xmvlog 分析,VHDL 源码由 xmvhdl 分析,两者都把源码翻译成中间表示并写入指定的工作库(默认是 work 库,物理上对应一个 xcelium.d 目录)。这一步只做语法、语义和模块接口的检查,不解析层次实例化关系。随后 xmelab 读取工作库中的中间表示,从顶层模块出发解析整个设计层次,绑定实例、解析参数、展开 generate、连接端口,最终生成一个可执行的仿真快照(snapshot)。最后 xrun 或 xmsim 加载该快照运行仿真。

关键点在于:分析阶段按文件独立进行,精化阶段才需要全局信息。这解释了为什么单独编译一个子模块可以通过,但整体精化时才报“模块未定义”或“端口宽度不匹配”。也解释了增量编译为什么能生效——只要某个文件的分析结果没变,精化阶段就可以复用它的中间表示,而不必重新分析。

Xcelium 编译与 Elaboration 数据流 Verilog / SV .v .sv .svh VHDL .vhd .vhdl xmvlog 分析 → 中间表示 xmvhdl 分析 → 中间表示 工作库 work xcelium.d/ 中间表示 + 库映射 xmelab 层次解析 / 绑定 生成 snapshot 增量:仅重新分析变更文件 阶段职责划分: 分析阶段:单文件语法/语义检查,写入工作库,不解析实例层次。 精化阶段:从顶层解析层次、绑定实例、解析参数、展开 generate、生成 snapshot。 仿真阶段:xmsim 加载 snapshot 运行,不再读取源码。

常用编译选项与作用

分析阶段的选项直接影响后续精化能否成功。以下是最常打交道的几类:

  • -sv:启用 SystemVerilog 支持。若源码含 logic、interface、class 等,必须加此选项,否则 xmvlog 会按 Verilog-2001 解析并报错。
  • -work <libname>:指定分析结果写入哪个库。默认 work,多库工程中用于把不同模块分库管理。
  • -incdir <path>:添加 `` `include `` 搜索路径,可多次指定。路径顺序决定同名头文件的优先级。
  • -define <macro>:定义预处理宏,等价于源码中的 `` `define ``,常用于条件编译开关。
  • -v2001 / -v95:指定语言版本,影响关键字集合与语法接受范围。
  • -messages:控制警告/错误输出级别,例如 -messages -warn 打开更多警告。

精化阶段 xmelab 的选项则决定层次解析行为:

  • -top <module>:指定顶层模块名。若设计有多个候选顶层,必须显式指定,否则报“multiple top-level”或选错入口。
  • -snapshot <name>:指定生成的快照名,默认 snapshot。后续 xmsim -snapshot <name> 加载。
  • -elaborate:强制完整精化,即使已有快照也重新生成。
  • -namemap / -defparam:控制参数覆盖与名称映射行为。
  • -timescale <t>:为未指定 timescale 的模块设置默认值,避免时间单位不一致。

库映射与配置文件

当设计被拆到多个库时,精化阶段需要知道“逻辑库名 → 物理目录”的对应关系。Xcelium 通过 cds.lib 文件完成这一映射。典型内容如下:

# cds.lib
DEFINE work ./xcelium.d/work
DEFINE rtl_lib ./libs/rtl
DEFINE vip_lib ./libs/vip
INCLUDE ./project/cds.lib

DEFINE 把逻辑库名绑定到物理路径,INCLUDE 用于引入其他库定义文件,便于团队共享公共库。分析时用 -work rtl_lib 把结果写入对应库,精化时 xmelab 会按 cds.lib 查找所有被引用的库。若某个库未定义,精化会报“library not found”或“module not found”。

库映射的常见坑:分析时写入了 rtl_lib,但 cds.lib 中只定义了 work,精化时就会找不到模块。排查时先确认 cds.lib 是否覆盖了所有 -work 用到的库名。

增量编译机制

Xcelium 的增量编译基于“文件级依赖 + 时间戳/内容比对”。当再次运行 xrun 或 xmelab 时,工具会检查每个源文件的分析结果是否仍然有效:如果文件未修改、其依赖的头文件未修改、编译选项未变化,则跳过 xmvlog/xmvhdl,直接复用工作库中的中间表示;只有变更的文件才重新分析。精化阶段同样可以增量进行——若层次结构和参数未变,可复用部分绑定结果。

要让增量编译真正生效,需要注意几点:

  1. 不要每次都用 -clean 或删除 xcelium.d,否则所有中间结果丢失,退化为全量编译。
  2. 保持编译选项稳定。若两次运行的 -incdir、-define 不同,工具会认为分析环境变化,可能触发重新分析。
  3. 头文件修改会波及所有 `` `include `` 它的文件,因此把稳定接口和频繁变动的宏分开放在不同头文件中,可缩小重编译范围。
  4. 库映射文件 cds.lib 变化时,精化阶段需要重新解析库关系,可能触发更多重算。

一个可复用的编译脚本骨架

下面给出一个多库工程的编译脚本示例,展示分析、精化、仿真三阶段的衔接方式。示例中的库名、路径和顶层模块名均为教学假设,实际使用时替换为工程真实值。

# 1. 分析 Verilog/SystemVerilog 到 rtl_lib
xmvlog -sv -work rtl_lib \
       -incdir ./rtl/include \
       -define SYNTHESIS \
       ./rtl/top.sv ./rtl/alu.sv ./rtl/ctrl.sv

# 2. 分析 VHDL 到 vip_lib
xmvhdl -work vip_lib -v93 ./vip/axi_master.vhd

# 3. 精化,指定顶层与快照名
xmelab -top top -snapshot top_snap \
       -timescale 1ns/1ps \
       rtl_lib.top vip_lib.axi_master

# 4. 运行仿真
xmsim -snapshot top_snap -run

执行后,若分析阶段有语法错误,xmvlog 会输出文件名、行号和错误码,此时精化不会进行。若分析通过但精化报“module 'alu' not found”,应检查 alu 是否被分析到了 rtl_lib,以及 cds.lib 是否定义了该库。若精化报端口宽度不匹配,则说明分析阶段各自通过,但层次绑定失败,需要回到源码核对实例化端口。

增量编译不是“永远正确”的。当修改了模块的端口列表或参数默认值,而依赖它的上层文件未重新分析时,可能出现中间表示不一致。此时应清理相关库或使用 -elaborate 强制全量精化,再判断问题是否消失。

掌握这条工具链后,日常开发中的多数编译类问题都可以按“分析是否通过 → 库映射是否正确 → 精化层次是否完整 → 快照是否最新”的顺序定位。把 cds.lib、编译选项和源文件依赖关系管理好,增量编译才能稳定地缩短迭代时间。