xmake 的配置参数
Verilua 的 HVL/WAL 场景下的工程管理使用的是 xmake,因此在 xmake 中支持多种可配置的参数,下面将对其进行说明。
必要参数
必要参数为必须在 xmake.lua 中对应的 target 添加的,否则进行编译的时候会报错。
-
add_rules("verilua")对于所有的 HVL/WAL 场景下的工程,都需要在 xmake 的 target 中添加这一句配置,否则将无法正常使用 Verilua。
-
add_toolchains(<toolchain>)添加具体的仿真器(Verilua 中称为仿真后端(Backend))。
- 对于 HVL 场景,目前
<toolchain>的可选值为@verilator、@iverilog、@vcs、@xcelium,分别对应了开源的 Verilator、开源的 Icarus Verilog、商业的 Synopsys VCS、Cadence Xcelium 等仿真器。 - 对于 WAL 场景,目前
<toolchain>的可选值为@wave_vpi,wave_vpi是 Verilua 开发的一个用于仿真波形的仿真后端,目前支持的波形格式为: VCD、FST、FSDB。
- 对于 HVL 场景,目前
-
add_files(...)添加需要进行仿真的文件,可以在一个语句中同时添加多个文件,也可以分为多个语句来添加多个文件。
-
对于 HVL 场景,可以是 Verilog/SystemVerilog 文件、Lua 文件。
xmake.luatarget("test", function()
add_rules("verilua")
add_toolchains("@verilator")
add_files("src/main.sv", "src/main.lua")
add_files("src/other.v")
-- ...
end) -
对于 WAL 场景,可以是波形文件、Lua文件。
xmake.luatarget("test", function()
add_rules("verilua")
add_toolchains("@wave_vpi")
add_files("./test.vcd", "test.lua")
-- ...
end)此时add_files只能添加一个波形文件
-
-
set_values("cfg.top", <top module name>)设置顶层模块的名称,这是 Verilua 访问信号层次结构的根节点,对于 HVL/WAL 场景,这个参数必须设置。
- HVL 场景:通常设置为实际的顶层 DUT 名称(如
Design、Counter) 或 testbench_gen 生成的 testbench 名称(tb_top) - WAL 场景:根据波形文件的层次结构设置,详见下方说明
例如在这个例子 中我们顶层 DUT 模块的名称是
Design,因此可以这么设置:set_values("cfg.top", "Design")。 - HVL 场景:通常设置为实际的顶层 DUT 名称(如
-
set_values("cfg.lua_main", <lua main file>)设置仿真时候执行的 lua 主脚本文件,对于 HVL/WAL 场景,这个参数必须设置,例如在这个例子 中我们的 lua 主脚本文件是
LuaMain.lua,因此可以这么设置:set_values("cfg.lua_main", "LuaMain.lua")。<lua main file>是一个具体的文件,可以包含路径。
cfg.top 在不同场景下的设置指南
HVL 场景(使用 @verilator、@iverilog、@vcs、@xcelium)
通常情况下,cfg.top 应该指向实际的顶层模块名称:
set_values("cfg.top", "Design") -- 直接指定 DUT 名称
如果使用 Verilua 的 testbench_gen 工具(Verilua 会自动生成 testbench), cfg.top 应该指向生成的 testbench 模块:
set_values("cfg.top", "tb_top") -- 指向 testbench_gen 生成的模块
WAL 场景(使用 @wave_vpi)
cfg.top 应该设置为波形文件中的顶层模块名称。这取决于波形是如何生成的:
场景 1:波形由 Verilua 的 HVL 仿真生成
如果波形文件是通过 Verilua 的 HVL 仿真生成的(如 WAL 示例中的 gen_wave),
Verilua 会自动使用 testbench_gen 生成 tb_top 模块,波形文件的顶层是 tb_top:
set_values("cfg.top", "tb_top")
这样可以访问:
- Testbench 信号(时钟、复位等)
- 导出的 DUT 端口
- 通过层次路径访问 DUT 内部信号(如
tb_top.uut.count_reg)
场景 2:波形直接来自 RTL(无 testbench 层)
如果波形文件是直接从 RTL 编译生成的(不通过 Verilua,没有 testbench), cfg.top 应该指向实际的 RTL 顶层模块:
set_values("cfg.top", "top") -- 或者你的实际顶层模块名
- 查看波形文件: 在波形查看器(如 GTKWave、Verdi)中打开波形文件,查看顶层模块名称
- 查看信号路径: 如果信号路径包含
tb_top.前缀,则应使用cfg.top = "tb_top" - 参考生成方式:
- 通过 Verilua 的 HVL 仿真生成 → 通常包含
tb_top层次 - 直接用仿真器编译 RTL(不经过 Verilua)→ 通常是实际的模块名
- 通过 Verilua 的 HVL 仿真生成 → 通常包含
可选参数
-
set_values("cfg.user_cfg", <user cfg file>)设置用户自定义的配置文件,这个配置文件是一个 Lua 脚本,格式如下所示:
my_cfg.lualocal cfg = {}
cfg.value1 = 123
cfg.value2 = "hello"
return cfg重点在于这个 Lua 脚本要返回一个 key-value 格式的 table。
当用户在 xmake.lua 中设置了这个配置文件的时候(
set_values("cfg.user_cfg", "my_cfg.lua")),那么在仿真进行的时候,可以通过全局变量cfg获取到这个 table 中的值,例如:main.luafork {
function ()
print("cfg.value1 => ", cfg.value1)
print("cfg.value2 => ", cfg.value2)
assert(cfg.value1 == 123)
assert(cfg.value2 == "hello")
end
} -
set_values("cfg.tb_gen_flags", <flags for testbench_gen>)/add_values("cfg.tb_gen_flags", "<flags for testbench_gen>")设置需要传递给
testbench_gen的额外参数,具体支持的 flags 可以参考 这里 的介绍。xmake 中set_values和add_values的区别set_values(<key>, <value>)对<key>进行单次赋值,调用多次set_values时,会覆盖之前的值,一个set_values只能有一个<value>;set_values("key", "value1") -- "key" = "value1"
set_values("key", "value2") -- "key" = "value2", the previous value "value1" is overwrittenadd_values(<key>, <value> ...)对<key>进行多次赋值,调用多次add_values时,会合并之前的值,一个add_values可以有多个<value>。add_values("key", "value1") -- "key" = "value1"
add_values("key", "value2") -- "key" = {"value1", "value2"}, the previous value "value1" is merged
-- equivalent to
set_values("key", "value1", "value2")- 也可以参考 xmake 文档中此处的说明。
-
set_values("<sim>.flags", <flags used in compilation>)/add_values("<sim>.flags", "<flags used in compilation>")用来添加需要传递给仿真器进行编译的额外参数,具体支持的 flags 可以与使用的仿真器相关。
注意- 对于 HVL 场景,目前
<sim>可选值为verilator、iverilog、vcs、xcelium。 - 对于 WAL 场景,这一设置不起作用。
- 对于 HVL 场景,目前
-
set_values("<sim>.run_flags", <flags used at runtime>)/add_values("<sim>.run_flags", "<flags used at runtime>")用来添加需要传递给编译后的二进制文件运行时的额外参数。例如 Verilator 编译得到的二进制文件通常叫
Vtb_top,则可以使用set_values("verilator.run_flags", "--help")来添加一个运行时参数,这样在 xmake 执行 run 的时候就会加上这个参数。运行仿真的时候等价于Vtb_top --help。注意- 对于 HVL 场景,目前
<sim>可选值为verilator、iverilog、vcs、xcelium。 - 对于 WAL 场景,这一设置不起作用。
- 对于 HVL 场景,目前
-
set_values("<sim>.run_prefix", <prefix flags used at runtime>)/add_values("<sim>.run_prefix", "<prefix flags used at runtime>")用来添加需要传递给编译后的二进制文件运行时的额外前缀参数。例如 Verilator 编译得到的二进制文件通常叫
Vtb_top,则可以使用set_values("verilator.run_prefix", "gdb --args")来添加一个运行时前缀参数,这样在 xmake 执行 run 的时候就会加上这个参数。运行仿真的时候等价于gdb --args Vtb_top。注意- 对于 HVL 场景,目前
<sim>可选值为verilator、iverilog、vcs、xcelium。 - 对于 WAL 场景,这一设置不起作用。
run_prefix和run_flags的位置区别<run_prefix> <binary> <run_flags> - 对于 HVL 场景,目前
-
set_values("cfg.build_dir_name", <build directory name>)设置构建目录的名称,如果不设置,默认为
set_values("cfg.top", <top module name>)的值。构建目录生成的位置默认情况下为:
./build/<simulator>/<top module name>,如果使用了set_values("cfg.build_dir_name", "SomeName"),那么会使用用户自定义的名称:./build/<simulator>/SomeName。不过请注意,./build/<simulator>是必须存在的,不支持更改。 -
set_values("cfg.build_dir_path", <build directory path>)设置构建目录的父路径。例如:
set_values("cfg.build_dir_path", "/tmp/builds")最终构建目录为
<build_dir_path>/<build_dir_name>,如未设置build_dir_name,则默认为顶层模块名。 -
set_values("cfg.version_required", "<version constraint>")指定最低 Verilua 版本要求。例如:
set_values("cfg.version_required", ">=1.0.0")构建时会自动校验当前 Verilua 版本是否满足要求。
-
set_values("cfg.no_internal_clock", "1")禁用自动时钟生成,适用于需要自定义时钟的场景。此时需在主 Lua 文件中手动生成时钟信号。
示例:
xmake.luatarget("my_test", function()
add_rules("verilua")
add_toolchains("@verilator")
set_values("cfg.top", "Top")
set_values("cfg.lua_main", "main.lua")
add_files("Top.v", "main.lua")
set_values("cfg.no_internal_clock", "1") -- 禁用自动时钟生成
end)对应的 main.lua 需手动生成时钟信号:
main.luafork {
clock_gen_task = function()
local clock = dut.clock:chdl()
while true do
clock:set(1)
await_time_ns(2)
clock:set(0)
await_time_ns(2)
end
end,
another_task = function()
-- ...
end
}