SystemVerilog的系统函数和任务
SystemVerilog提供了一些实用的系统函数和系统任务给用户实用,有助于更简单和更高效的完成特定任务。
1. Simulation control system tasks
控制仿真的系统任务有三个:
- $stop [ ( n ) ]:$stop可以用于暂停仿真;
- $finish [ ( n ) ]:$finish会使仿真器退出并将控制权传递回主机操作系统;
- $exit [ ( ) ]:$exit会等待所有程序块(program block)完成,然后隐式调用$finish;
$stop和$finish允许接收一个可选的参数(0,、1或3),该参数决定打印什么类型的诊断消息,如果没有提供参数,默认参数值为1,如下表所示:
参数值 | 诊断消息 |
0 | 不打印任何消息 |
1 | 打印仿真时间和位置 |
2 | 打印仿真时间、位置和关于仿真中使用内存与CPU时间的统计信息 |
2. Simulation time system functions
提供对当前时间访问的系统函数有:
- $time:返回一个64-bit时间的整数,按比例缩放(四舍五入)为调用它的模块的时间单位(time unit);
- $stime:返回一个32-bit时间的无符号整数,按调用它的模块的时间单位进行缩放。如果实际仿真时间不适合32-bit,则返回当前仿真时间的低32-bit;
- $realtime:返回一个实数时间,与$time一样,它被缩放为调用它的模块的时间单位;
3. Timescale system tasks
显示和设置时间打印信息的系统任务有:
- $printtimescale [ ( hierarchical_identifier ) ]:用于显示特定模块的时间单位和时间精度;该系统任务可以指定或不指定参数:
- 如果没有指定参数,它将显示当前作用域模块的时间单位和精度;
- 如果指定参数,它将显示传递给它的模块的时间单位和精度;
- $printtimescale打印的timescale格式为:Time scale of (module_name) is unit / precision;
- $timeformat [ ( units_number , precision_number , suffix_string , minimum_field_width ) ]:它有以下两个功能:
- 它指定了在$write, $display, $strobe, $monitor, $fwrite, $fdisplay, $fstrobe和$fmonitor中,用%t打印时间信息的格式规范,直到另一个$timeformat被调用;
- 它指定了进入交互方式延迟的时间单位;
$timeformat中units_number参数应为0~-15范围内的整数,该参数不同取值表示的时间单位如下表所示:
precision_number用于指定打印时间精度为多少,默认值为0;suffix_string用于指定时间后面跟的字符串,默认为空字符串;minimum_field_width为时间格式最少占用的宽度。
4. Conversion functions
提供了系统函数在值和实数值之间进行转换,并将值转换为有符号值或无符号值。
以下系统函数用于处理实数值(real和shortreal类型),它们也可以用于处理常数表达式:
- Integer $rtoi ( real_val ):$rtoi通过截断实数值将实数值转换为整数类型,比如123.45变成123。这里要记住:$rtoi是直接截断小数点后面的值,而不会四舍五入的,像直接赋值或使用cast转换的场景,它们是会使用四舍五入的;
- Real $itor ( int_val ):$itor将整数值转换为实数值,比如123变成123.0;
- [63:0] $realtobits ( real_val ):$realtobits将real类型的值转换为实数的64-bit向量表示;
- Real $bitstoreal ( bit_val ):$bitstoreal将$realtobits创建的64-bit向量模式转换为实数值;
- [31:0] $shortrealtobits ( shortreal_val ):$shortrealtobits将值从shortreal类型转换为实数的32-bit向量表示;
- Shortreal $bitstoshortreal ( bit_val ):$bitstoshortreal将$shortrealtobits创建的32-bit向量模式转换为shortreal类型的值;
$signed和$unsigned系统函数可用于 强制转换表达式的符号,而不是类型。这些函数对输入表达式求值,并返回与输入表达式具有相同大小的值和函数定义的类型。
- $signed:返回的值是有符号;
- $unsigned:返回的值是无符号;
需要说明的是:cast也可以用于转换表达式的符号位,而是采用动态的cast改变表达式符号类型。
5. Data query functions
提供了查询表达式的一些系统函数,有:
- $typename ( expression )或$typename ( data_type ):$typename返回一个字符串,该字符串表示其参数的解析类型;
- $bits ( expression ) 或$bits ( data_type ):$bits返回参数的需要占据的位数,返回类型为integer,4-state值计为1-bit;
- $isunbounded ( constant_expression ):如果参数为$,$isunbounded将返回true;
$typename返回类型例子如下:
// source code // $typename would return
typedef bit node; // "bit"
node [2:0] X; // "bit [2:0]"
int signed Y; // "int"
package A;
enum {A,B,C=99} X; // "enum{A=32'sd0,B=32'sd1,C=32'sd99}A::e$1"
typedef bit [9:1'b1] word; // "A::bit[9:1]"
endpackage : A
import A::*;
module top;
typedef struct {node A,B;} AB_t;
AB_t AB[10]; // "struct{bit A;bit B;}top.AB_t$[0:9]"
...
endmodule
$bits例子如下:
logic [31:0] v; // $bits(v) shall return 32
typedef struct { // $bits(MyType) shall return 9
logic valid;
bit [8:1] data;
} MyType;
$isunbounded例子如下:
parameter int i = $; // $isunbounded(i) shall return true. Otherwise, it shall return false
6. Array querying functions
SV提供了用于返回有关数组或整型数据类型或一个数据类型的数据对象的特定维度的信息,返回默认类型为integer,可选维度表达式的默认值为1。维度表达式可以指定任何固定大小的维度(packed或unpacked)或任何动态大小的维度(动态、关联或队列)。当用于动态数组或队列维度时,这些函数会返回有关数组当前状态的信息。对于除关联数组维度之外的任何维度:
- $left:$left返回所选维度的左边界。对于packed维度,它会返回most significant element的索引;对于队列或动态数组维度,$left返回0;
- $right:$right返回所选维度的右边界。对于packed维度,它会返回least significant element的索引;对于当前大小为0的队列或动态数组维度,$right返回-1;
- $increment:对于固定大小的维度,如果$left大于等于$right,则$increment返回1;如果$left小于$right,则返回-1。对于队列或动态数组维度,$increment将返回-1;
- $low:如果$increment返回-1,则$low将返回与$left相同的值;当$increment返回1时,$low返回与$right相同的值;
- $high:如果$increment返回-1,则$high将返回与$right相同的值;当$increment返回1时,$high将返回与$left相同的值;
- $size:返回所选维度中元素的个数,相当于$high-$low+1;
- $dimensions:返回数组的总维度(packed和unpacked,动态或静态)。如果是string数据类型或任何其它等效于简单bit vector类型的非数组类型,则返回1;其它类型返回0。
- $unpacked_dimensions:返回数组的总unpacked维度(动态或静态);其它类型返回0。
数组的维度按照如下方式编号:变化最慢的维度(packed或unpacked)为维度1,。变化速度越快,维度越高。在对维度进行编号之前,首先展开中间类型的定义。如下例子:
// Dimension numbers
// 3 4 1 2
logic [3:0][2:1] n [1:5][2:8];
typedef logic [3:0][2:1] packed_reg;
packed_reg n[1:5][2:8]; // same dimensions as in the lines above
Array querying functions在关联数组维度上的使用仅限于具有整数值的索引类型。如果使用整数索引,这些函数将返回以下内容:
- $left返回0;
- $right返回最大可能的索引值;
- $low返回当前分配的最低索引值,但如果当前没有分配元素,则返回’x;
- $hight返回当前分配的最大索引值,但如果当前没有分配元素,则返回’x;
- $increment返回-1;
- $size返回当前分配的元素数量;
7. Math functions
SV提供了整数算术函数和实数算术函数,这些算术系统函数可以在常量表达式中使用。
在整数算术函数中,$clog2系统函数将返回参数以2为基数的log上限(向上舍入为整数值)。参数可以是整数或任意大小的向量值。参数会被视为无符号数,如果参数为0,那么结果为0。$clog2可用于计算寻址戈丁大小的存储器所需的最小地址宽度,或表示给定数量的状态所需的最小位宽。
在实数算术函数中,传入的参数必须是实数值参数,并返回实数类型的结果。它们的行为和C语言标准库中对应函数的功能一致,如下表所示。
8. Bit vector system functions
位向量系统函数可以对位向量进行操作,有如下:
- $countbits ( expression , control_bit { , control_bit } ):$countbits计算位向量中一组特定值(例如:0、1、X、Z)的位的个数,它的参数control_bit可能是常数和变量都行,它的返回值是int类型,该值等于expression与control_bit相匹配的位数;比如:
- $countbits (expression, '1)返回expression中bit值为1的个数;
- $countbits (expression, '1, '0)返回expression中bit值为1或0的个数;
- $countbits (expression, 'x, 'z)返回expression中bit值为x或z的个数;
- $countones ( expression ):等价于$countbits(expression,'1),返回类型是int;
- $onehot ( expression ):等价于$countbits(expression,'1)==1,返回类型是bit;
- $onehot0 ( expression ):等价于$countbits(expression,'1)<=1,返回类型是bit;
- $isunknown ( expression ):等价于$countbits(expression,'x,'z)!=0,返回类型是bit;
9. Severity tasks
SV提供了专门的文本消息处理任务,可用于标识各种异常情况。这些任务有:
- $fatal [ ( finish_number(0 | 1 | 2) [ , list_of_arguments ] ) ]:$fatal将引发一个run-time致命错误,从而终止仿真并以错误代码结束;传递给$fatal函数的第一个参数与传递给$finish的参数含义一致,该参数用于设置工具所报告诊断信息级别。调用$fatal函数等同于隐式调用$finish函数。
- $error [ ( [ list_of_arguments ] ) ]:$error用于上报一个运行错误;
- $warning [ ( [ list_of_arguments ] ) ]:$warning用于上报一个运行警告;
- $info [ ( [ list_of_arguments ] ) ]:$info表示消息没有特定的严重性;
10. Coverage system functions
SV有几个内建的系统任务用于获取或设置覆盖率信息,有如下:
- $coverage_control(control_constant, coverage_type, scope_def, modules_or_instance):该函数用于控制或查询层次结构中指定部分的覆盖率是否可用;
- $coverage_get_max(coverage_type, scope_def, modules_or_instance):该函数获取在层次结构的指定部分上指定覆盖率类型的100%覆盖率的值。在整个仿真过程中,它的值保持不变。该函数返回的值是integer类型,它的值与电路设计尺寸和结构成正比,在假设任何编译选项都不会修改覆盖支持或设计结构的情况下,理论上在多个独立的仿真和编译后,对于相同的设计,它的值保持不变;
- $coverage_get(coverage_type, scope_def, modules_or_instance):该函数在层次结构的给定部分上获得给定覆盖率类型的当前覆盖值。该函数的返回值是integer类型。这个数字可以通过公式(coverage% =(coverage_get() / coverage_get_max()) x 100)转换为覆盖率百分比;
- $coverage_merge(coverage_type, "name"):该函数将指定覆盖率的数据加载并合并到仿真器中。”name”是工具使用的任意字符串,以特定于工具实现的方式。只要能定位到工具允许覆盖率存放的地方就行。如果用户通过该函数去检索名称不存在或覆盖率数据库不对应,就会报错。如果在加载过程中发生错误,那么该仿真生成的覆盖率数字可能没有意义了;
- $coverage_save(coverage_type, "name"):该函数将覆盖率的当前状态保存到工具的覆盖率数据库中,并将其与给定名称相关联。该名称将以特定于实现的方式映射到覆盖率数据库中的某个文件或一组文件中。保存到数据库中的数据可以通过使用$coverage_merge()用相同的名称检索到;在仿真中,保存覆盖率不会对覆盖率状态产生任何影响;
- $set_coverage_db_name ( filename ):设置覆盖率数据库的文件名,在仿真运行结束时将覆盖率信息保存到该数据库中;
- $load_coverage_db ( filename ):从给定的文件名加载所有coverage group类型的累积覆盖率信息;
- $get_coverage:返回0~100范围内所有coverage group类型的总体覆盖率的实数值;
11. Probabilistic distribution functions
SV提供一组标准概率分布函数用于返回整数值,有如下:
- $random [ ( seed ) ]:$random提供了一种生成随机数的机制。该函数每次被调用时都会返回一个新的32-bit有符号随机数。Seed参数控制$random返回的数字,以便不同的种子生成不同的随机流。Seed参数应该是一个整型变量,且在调用$random之前将种子值赋给这个变量;
- dist function:dist系统函数的所有参数都是整数值。对于指数函数(exponential)、泊松函数(poisson)、卡方函数(chi-square)、t函数和erlang函数来说,它们的参数mean、degree_of_freedom和k_stage要大于0;对于每个系统函数,seed参数都是inout参数;也就是说,将一个值传递给函数,然后返回一个不同的值。对于相同的种子,系统函数应该总是返回相同的值。这使得系统的操作可重复,从而便于调试。seed参数应该是一个整型变量,由用户初始化,仅由系统函数更新,以便实现期望的分布。在$dist_normal、$dist_exponential、$dist_poisson和$dist_erlang中指定的整型输入mean参数,它使函数返回的平均值接近指定的mean值。与$dist_chi_square和$dist_t函数一起使用的degree_of_freedom参数是一个整型输入,有助于确定密度功能的形状,较大的数字将返回值分布在更大的范围内。
- $dist_uniform ( seed , start , end ):在$dist_uniform函数中,start和end参数是绑定返回值的整数输入。$dist_uniform返回在其参数指定的间隔内均匀分布的随机数。起始值应小于结束值;
- $dist_normal ( seed , mean , standard_deviation ):在$dist_normal中使用的standard_deviation参数是一个整型输入,它有助于确定正态分布的密度形状,较大的standard_deviation值将返回值扩展到更大的范围;
- $dist_exponential ( seed , mean )
- $dist_poisson ( seed , mean )
- $dist_chi_square ( seed , degree_of_freedom )
- $dist_t ( seed , degree_of_freedom )
- $dist_erlang ( seed , k_stage , mean )
12. Miscellaneous tasks and functions
$system ( [ " terminal_command_line " ] )会调用C语言的函数system(),该C函数执行传递给它的参数,就像从终端执行参数一样。$system可以作为任务或函数调用。当它作为函数调用时,它调用它返回数据类型为int。如果调用$system时没有带字符串参数,则调用c函数system()时将带NULL字符串。如下示例:
module top;
initial $system("mv design.v adder.v");
endmodule
上述例子是调用SV中的$system系统任务来修改文件名,将design.v修改成adder.v。
13. 说明
关于“Assertion control system tasks”、“Sampled value system functions”、“Stochastic analysis tasks and functions”和“Programmable logic array modeling system tasks”这个几类系统函数和系统任务,本文不做介绍。