systemverilog系统函数$test$plusargs和$value$plusargs

在IC验证(VCS仿真)中,$test$plusargs$value$plusargs 是两个非常实用的系统函数。它们允许你在不重新编译代码的情况下,通过仿真运行命令行(Runtime)直接向环境传递参数,从而控制测试行为。

1. testplusargs(标志位检测)

这个函数用于检查命令行中是否出现了某个特定的字符串(前缀匹配)。它通常作为一种"开关"来使用。

  • 语法: if ($test$plusargs("STRING")) ...

  • 特点: 只判断"是否存在",不解析具体数值。

  • 匹配规则: 它匹配的是前缀。例如,如果命令行有 +HELLO_WORLD,那么 $test$plusargs("HELLO") 也会返回真。

cpp 复制代码
initial begin
    if ($test$plusargs("DEBUG_MODE")) begin
        $display("Run-time info: Debug mode is ON");
        // 开启额外的打印或波形
    end
end

命令行输入: ./simv +DEBUG_MODE


2. valueplusargs(数值传递)

这个函数不仅检查字符串是否存在,还会将字符串中跟随的值转换并存储到变量中。

  • 语法: $value$plusargs("STRING=%format", variable)

  • 格式符 (%format):

    • %d: 十进制 (Decimal)

    • %h: 十六进制 (Hex)

    • %s: 字符串 (String)

    • %b: 二进制 (Binary)

    • %f: 浮点数 (Real)

cpp 复制代码
int max_packet_count;
string test_name;

initial begin
    // 获取整数值
    if ($value$plusargs("MAX_PKTS=%d", max_packet_count)) begin
        $display("Setting max packets to %0d", max_packet_count);
    end

    // 获取字符串
    if ($value$plusargs("TEST_CASE=%s", test_name)) begin
        $display("Running test: %s", test_name);
    end
end

命令行输入: ./simv +MAX_PKTS=500 +TEST_CASE=my_test_v1


3. 两者的对比总结

特性 testplusargs valueplusargs
主要用途 充当开关 (Enable/Disable) 传递具体配置值 (Value)
返回值 返回布尔值(是否存在) 返回布尔值,并赋值给第二个参数
参数复杂度 仅需指定字符串 需要指定格式符(如 %d, %s
典型场景 开启波形、跳过某段初始化 设置超时时间、指定测试用例名、配置频率

4. 延伸:VCS 中的底层逻辑

在 VCS 仿真运行过程中,当仿真器扫描到命令行字符串时:

  1. 它会维护一个包含所有 + 参数的列表。

  2. 当代码执行到 $value$plusargs 时,仿真器会在这个列表中搜索匹配的字符串。

  3. 找到匹配项后,根据你提供的格式符(如 %d)进行类型转换,然后赋值给你的变量。

在 VCS(以及大多数 EDA 工具)中,参数前缀使用 + 还是 - 有着本质的区别。简单来说:- 是给仿真器软件看的,+ 是给你写的代码看的。


1. 带 - 的参数:仿真器指令 (Tool Options)

这些参数是 VCS 软件内置的开关,用于控制仿真器的行为、性能或功能。

  • 接收者: VCS 引擎(底层 C++/二进制代码)。

  • 作用: 开启/关闭仿真器的原生功能(如日志、波形、覆盖率、界面等)。

  • 是否需要代码支持: 不需要。无论你代码怎么写,这些参数都有效。

  • 常用示例:

    • -gui:启动图形界面。

    • -l sim.log:指定日志文件。

    • -ucli:启用 TCL 交互命令行。

    • -cm line:收集行覆盖率。


2. 带 + 的参数:用户自定义参数 (Plusargs)

这些参数通常是用户自定义的,或者是某些**高级库(如 UVM)**预留的接口。

  • 接收者: 你在 SystemVerilog 中写的测试平台(Testbench)。

  • 作用: 通过 $test$plusargs$value$plusargs 被你的代码读取,从而改变测试逻辑(如修改种子、切换测试用例、配置寄存器地址等)。

  • 是否需要代码支持: 需要 。除非你在代码里调用了相关的系统函数去解析它,否则你在命令行输入 +HELLO,仿真器只会直接忽略它。

  • 常用示例:

    • +SEED=12345:传递随机种子给代码。

    • +UVM_TESTNAME=my_test:告知 UVM 框架运行哪个 Case(UVM 内部通过 $value$plusargs 读取)。

    • +DEBUG_MODE:触发代码里的 if($test$plusargs(...)) 块。

3. 对比总结表
特性 - 参数 (Minus Options) + 参数 (Plus Arguments)
定义者 仿真器厂商 (Synopsys) 用户或库开发者 (UVM/Methodology)
解析方式 仿真器内核自动解析 代码中使用 $test$plusargs 等手动解析
灵活性 固定,由工具版本决定 无限,随你心情定义
冲突处理 输入错误通常会导致仿真报错退出 输入错误(或未匹配)通常被忽略,无影响
典型用途 仿真环境配置(波形、License、性能) 测试逻辑配置(参数化、用例选择、寄存器值)

虽然绝大多数情况遵循这个规律,但 VCS 也有极少数自带的参数使用 + 开头,比如 +vcs+lic+wait(等待 License)和 +v2k(支持 Verilog-2000 标准)。这些可以看作是"系统级"的 plusargs。


5. valueplusargs 这是两个系统函数拼起来的吗

不是。 虽然它的名字看起来像是由 $value$plusargs 组合而成的,但它在 SystemVerilog 标准中是一个独立的、完整的一体化系统函数 。两个 $ 并不是代表两个独立函数的拼接,而是为了语义分隔

1. 拆解命名的含义

我们可以把这个名字看作是三个语义部分的组合:

  • $:代表这是一个系统任务或函数(System Task/Function)。

  • value :代表它的核心功能是提取数值(Value Extraction)。

  • plusargs :代表它作用于命令行中以 + 号开头的参数(Plus Arguments)。

2.为什么中间多了一个 $

你可以把这个命名看作是一个**"分层分类"**的结构:

  • 第一个 $:它是所有系统函数的标志,相当于在说:"注意,我要调用仿真器内置的功能了。"

  • 中间的 $ :它在这里起到了分隔符 的作用,类似于其他编程语言中的下划线 _ 或点 .


6. +MAX_PKTS=500 在解析的时候怎么知道这个500是数字还是字符串?

这是一个非常经典的问题。答案是:仿真器本身并不知道它是数字还是字符串,它完全取决于你在代码中使用的"格式说明符"以及接收变量的类型。

在解析 +MAX_PKTS=500 时,$value$plusargs 会按照你指定的格式进行强制转换

1. 它是数字还是字符串,由你决定

你可以用不同的方式去"解读"这同一个参数:

情况 A:把它当作【数字】解析

如果你在代码里写 %d,仿真器就会尝试把 =号 后面的字符转换成十进制整数。

cpp 复制代码
int pkts;
initial begin
    // 仿真器看到 %d,会尝试将 "500" 转换为整数 500
    if ($value$plusargs("MAX_PKTS=%d", pkts)) begin
        $display("解析为数字: %0d", pkts); 
    end
end
情况 B:把它当作【字符串】解析

如果你在代码里写 %s,仿真器就会直接把 "500" 这三个字符当作字符串存入变量。

cpp 复制代码
string s_pkts;
initial begin
    // 仿真器看到 %s,会直接取字符串 "500"
    if ($value$plusargs("MAX_PKTS=%s", s_pkts)) begin
        $display("解析为字符串: %s", s_pkts); 
    end
end

2. 万一解析失败了怎么办?

解析成功与否遵循以下原则:

  • 格式不匹配: 如果你写了 +MAX_PKTS=abc,但代码里用 %d 尝试解析,解析会失败,$value$plusargs 会返回 0(假),且目标变量 pkts 不会被修改。

  • 部分匹配: 如果你写了 +MAX_PKTS=500abc,使用 %d 解析,通常仿真器会解析出 500 然后停止(具体取决于仿真器实现,建议避免这种写法)。

  • 十六进制: 如果你想传递十六进制,命令行写 +ADDR=A0,代码里必须对应使用 %h

3. 底层原理:一切皆字符串

在操作系统的层面, ./simv +MAX_PKTS=500 传入的所有内容最初都是字符串

$value$plusargs 的作用就像是 C 语言里的 sscanf

  1. 它先在命令行参数中寻找匹配 MAX_PKTS= 的字符串。

  2. 找到后,截取剩下的部分(即 "500")。

  3. 根据你提供的格式符(%d, %s, %h, %f),把这个字符串"翻译"成目标类型。

总结
  • 你想它是数字: 代码用 %d,变量定义为 intbit

  • 你想它是字符串: 代码用 %s,变量定义为 string

经验之谈: 在验证环境(UVM)中,建议始终通过这种方式传递参数,并给变量设置一个默认值 。如果 $value$plusargs 返回 0,就使用默认值,这样即使命令行忘了写参数,仿真也能正常跑下去。

相关推荐
lbt_dvshare3 天前
MTCMOS flow
systemverilog
蓝天下的守望者6 天前
systemverilog中的virtual function
systemverilog
Nick.Q7 天前
$cast用法
systemverilog
不会武功的火柴9 天前
UVM验证入门(18)-Callback机制
systemverilog·ic验证·uvm方法学
不会武功的火柴13 天前
UVM验证入门(15)-uvm_agent代理
systemverilog·ic验证·uvm方法学
zhuangzhunag1 个月前
【SV验证入门】接口在设计和验证中的使用
systemverilog
FPGA_小田老师1 个月前
FPGA语法基础(二):SystemVerilog 数组清零方法详解
fpga开发·systemverilog·数组清零·systemverilog数组·systemverilog语法
谷公子的藏经阁2 个月前
稀疏激励的重要性
芯片验证·testcase·稀疏·验证用例·激励
m0_713541844 个月前
systemverilog如何解决不能使用变量索引来进行位选择的范围指定
算法·systemverilog