全局配置信息
Verilua 中,cfg 这个全局变量(table 类型)用于存储运行期的全局配置信息。具体实现可参考源码中的 src/lua/verilua/LuaSimConfig.lua。常用的内置字段如下:
-
cfg.top这个变量用于存储当前的一个正在进行仿真的设计的顶层模块的名称,例如:
tb_top。 -
cfg.simulator这个变量用于存储当前的仿真器的名称,可以是
verilator、vcs、xcelium、iverilog、或者wave_vpi。 -
cfg.script这个变量用于存储当前运行的 Lua 入口脚本路径(或文件名),例如:
LuaMain.lua。 -
cfg.seed这个变量用于存储当前的仿真的随机种子的值。
-
cfg.time_precision这个变量用于表示当前仿真的时间精度,使用 10 的指数形式表示,例如
-9表示ns,-12表示ps。 -
cfg.time_unit这个变量用于表示与
cfg.time_precision对应的人类可读时间单位,例如fs、ps、ns、us、ms、s。
这一页介绍的是运行期全局变量 cfg 上的字段;而 xmake.lua 里的 set_values("verilua.xxx", ...) / add_values("verilua.xxx", ...) 是构建期配置项。
两者名字有时会相似,但并不一定是一一对应。例如:
set_values("verilua.top", ...)会影响运行期的cfg.topset_values("verilua.lua_main", ...)对应到运行期看到的是cfg.scriptset_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.value1、cfg.value2 这样的字段,
而不是 cfg.user_cfg.value1。
这个配置文件本身也是一个 Lua 脚本,例如:
用户配置文件会在较早阶段加载,因此并不是所有 Verilua 模块都适合在这里使用;通常建议只依赖 verilua.LuaUtils 这类基础工具模块。
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。
上面的写法里:
- 可以直接写固定参数,例如
cfg.monitor_name = "monitor_0"。 - 也可以通过
utils.get_env_or_else(key, type, default)从环境变量读取配置。
get_env_or_else 的三个参数分别表示:
- 环境变量名,例如
NR_BUF。 - 值类型,目前常用的是
"number"、"string"、"boolean"。 - 默认值,在环境变量未设置时使用。
例如 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 中这样指定:
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 追加:
set_values("verilua.user_cfg", "common/cfg.lua", "case/cfg.lua")
add_values("verilua.user_cfg", "extra/cfg.lua")
合并规则:
- 按声明顺序逐个加载(上例为
common/cfg.lua→case/cfg.lua→extra/cfg.lua),后加载的文件覆盖先前的同名字段。srcs和deps除外,这两个字段是追加。 - 每个文件按完整路径加载,不同目录下都叫
cfg.lua也不会互相覆盖。 - 加载某个配置文件时,
base_path中的路径先于当前配置目录搜索,其中包括 Verilua 自身与deps的路径。全部加载完后,所有配置目录一起保留在package.path中。
Lua 的模块缓存(package.loaded)按模块名索引,不区分来源目录。两个配置目录下都有 helper.lua,且两个配置文件都 require "helper" 时,第二次 require 拿到的仍然是第一次加载的模块。共享模块请用唯一名字,例如 common_helper.lua。
配置文件内部对 package.path 的修改也不会保留到加载结束之后。需要额外搜索路径时,用 add_files 或把模块放在配置文件同目录。
在仿真运行时,用户配置文件中返回的字段会被直接展开到全局变量 cfg 上:
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的来源。