Skip to main content

全局配置信息

Verilua 中,cfg 这个全局变量(table 类型)用于存储运行期的全局配置信息。具体实现可参考源码中的 src/lua/verilua/LuaSimConfig.lua。常用的内置字段如下:

  1. cfg.top

    这个变量用于存储当前的一个正在进行仿真的设计的顶层模块的名称,例如:tb_top

  2. cfg.simulator

    这个变量用于存储当前的仿真器的名称,可以是 verilatorvcsxceliumiverilog、或者 wave_vpi

  3. cfg.script

    这个变量用于存储当前运行的 Lua 入口脚本路径(或文件名),例如:LuaMain.lua

  4. cfg.seed

    这个变量用于存储当前的仿真的随机种子的值。

  5. cfg.time_precision

    这个变量用于表示当前仿真的时间精度,使用 10 的指数形式表示,例如 -9 表示 ns-12 表示 ps

  6. cfg.time_unit

    这个变量用于表示与 cfg.time_precision 对应的人类可读时间单位,例如 fspsnsusmss

与 xmake 配置项的关系

这一页介绍的是运行期全局变量 cfg 上的字段;而 xmake.lua 里的 set_values("verilua.xxx", ...) / add_values("verilua.xxx", ...) 是构建期配置项。

两者名字有时会相似,但并不一定是一一对应。例如:

  • set_values("verilua.top", ...) 会影响运行期的 cfg.top
  • set_values("verilua.lua_main", ...) 对应到运行期看到的是 cfg.script
  • set_values("verilua.user_cfg", ...) 只是用来指定用户配置文件路径,运行期不会自动出现 cfg.user_cfg 这个字段;该文件返回的字段会直接合并到全局 cfg

用户自定义配置

Verilua 允许用户在 xmake.lua 中通过 set_values("verilua.user_cfg", <user cfg file>, ...) 指定一个或多个 Lua 配置文件,并将它们返回的 table 合并到运行期全局变量 cfg 中。

常见误解

set_values("verilua.user_cfg", ...) 里的 verilua.user_cfg 是 xmake 里的配置项名字, 不是运行期全局变量 cfg 上的一个字段。

也就是说,运行期通常访问的是 cfg.value1cfg.value2 这样的字段, 而不是 cfg.user_cfg.value1

这个配置文件本身也是一个 Lua 脚本,例如:

加载时机

用户配置文件会在较早阶段加载,因此并不是所有 Verilua 模块都适合在这里使用;通常建议只依赖 verilua.LuaUtils 这类基础工具模块。

my_cfg.lua
local utils = require "verilua.LuaUtils"

local cfg = {}

-- Fixed values.
cfg.nr_buf = 16
cfg.value_vec = { 1, 2, 0x12 }
cfg.monitor_name = "monitor_0"
cfg.use_random = true
cfg.some_func = function()
print("do something")
end

-- Read from environment variables with defaults.
cfg.nr_buf = utils.get_env_or_else("NR_BUF", "number", 16)
cfg.test_mode = utils.get_env_or_else("TEST_MODE", "string", "Normal")
cfg.use_random = utils.get_env_or_else("USE_RANDOM", "boolean", true)

return cfg

重点在于这个 Lua 脚本最终需要返回一个 key-value 格式的 table。

上面的写法里:

  1. 可以直接写固定参数,例如 cfg.monitor_name = "monitor_0"
  2. 也可以通过 utils.get_env_or_else(key, type, default) 从环境变量读取配置。

get_env_or_else 的三个参数分别表示:

  1. 环境变量名,例如 NR_BUF
  2. 值类型,目前常用的是 "number""string""boolean"
  3. 默认值,在环境变量未设置时使用。

例如 cfg.nr_buf = utils.get_env_or_else("NR_BUF", "number", 16) 的优先级就是“环境变量值优先,其次才是默认值”;如果运行时设置了 NR_BUF=32,那么 cfg.nr_buf 就会是 32,否则为 16

例如,可以这样运行:

# Use the default value 16
xmake run -P . test

# Override nr_buf through environment variable
NR_BUF=32 xmake run -P . test

如果 main.lua 中打印了 cfg.nr_buf,那么第二条命令运行时看到的值就会是 32

然后在 xmake.lua 中这样指定:

xmake.lua
target("test", function()
add_rules("verilua")
add_toolchains("@verilator")
set_values("verilua.top", "Top")
set_values("verilua.lua_main", "main.lua")
set_values("verilua.user_cfg", "my_cfg.lua")
add_files("Top.v")
end)

多个配置文件

可以一次指定多个文件,也可以用 add_values 追加:

xmake.lua
set_values("verilua.user_cfg", "common/cfg.lua", "case/cfg.lua")
add_values("verilua.user_cfg", "extra/cfg.lua")

合并规则:

  1. 按声明顺序逐个加载(上例为 common/cfg.luacase/cfg.luaextra/cfg.lua),后加载的文件覆盖先前的同名字段。srcsdeps 除外,这两个字段是追加。
  2. 每个文件按完整路径加载,不同目录下都叫 cfg.lua 也不会互相覆盖。
  3. 加载某个配置文件时,base_path 中的路径先于当前配置目录搜索,其中包括 Verilua 自身与 deps 的路径。全部加载完后,所有配置目录一起保留在 package.path 中。
同名模块

Lua 的模块缓存(package.loaded)按模块名索引,不区分来源目录。两个配置目录下都有 helper.lua,且两个配置文件都 require "helper" 时,第二次 require 拿到的仍然是第一次加载的模块。共享模块请用唯一名字,例如 common_helper.lua

配置文件内部对 package.path 的修改也不会保留到加载结束之后。需要额外搜索路径时,用 add_files 或把模块放在配置文件同目录。

在仿真运行时,用户配置文件中返回的字段会被直接展开到全局变量 cfg 上:

main.lua
fork {
function ()
print("cfg.nr_buf => ", cfg.nr_buf)
print("cfg.monitor_name => ", cfg.monitor_name)
print("cfg.test_mode => ", cfg.test_mode)

assert(cfg.nr_buf == 16 or cfg.nr_buf == 32)
assert(cfg.monitor_name == "monitor_0")
end
}

相关文档

  • xmake 参数说明:查看 set_values("verilua.xxx", ...) 的构建期配置入口。
  • 编写 xmake.lua:查看用户配置文件在完整工程中的组织方式。
  • HVL 示例:对照最小示例理解运行期 cfg 的来源。