第一章 SystemVerilog导论

SystemVerilog 3.1a语言参考手册
第一章 SystemVerilog导论

本参考手册详细描述了Accellera为使用Verilog硬件描述语言在更高的抽象层次上进行系统的建模和验证所作的扩展。这些扩展将Verilog语言推向了系统级空间和验证级空间。SystemVerilog构建于IEEE Verilog 2001委员会所作的工作之上。

在本参考手册中：

  • “Verilog”或“Verilog-2001”指的是IEEE Std. 1364-2001 Verilog硬件描述语言标准；
  • “SystemVerilog”指的是Accellera对Verilog-2001标准所作的扩展。

在本参考手册中对Verilog语言的几个版本进行了如下的编号：

  • “Verilog 1.0”指的是IEEE Std. 1364-1995 Verilog硬件描述语言标准，也被称作Verilog-1995；
  • “Verilog 2.0” 指的是IEEE Std. 1364-2001 Verilog硬件描述语言标准，一般称之为Verilog-2001。这一版本的Verilog包含了自从Verilog在1990年向公共领域开放以来所作的首次具有革新意义的增强；
  • “SystemVerilog 3.x”指的是Verilog-2001加上为在更高的抽象层次上进行系统建模和验证所作的扩展，也就是在本参考手册中描述的版本；
    • SystemVerilog 3.0在2002年六月被批准为Accellera标准，主要针对高层结构建模进行了增强；
    • SystemVerilog 3.1在2003年五月被批准为Accellera标准，主要针对高级验证和C语言集成进行了增强；
    • SystemVerilog 3.1a在2004年四月被批准为Accellera标准，包括了对SystemVerilog 3.1手册所作的修正和解释。同时对Verilog进行了更多的增强，例如SystemVerilog结构的VCD和PLI规范等。

在Accellera HDL+Technical小组委员会的指导之下，Accellera正在为增强Verilog进行着持续的努力。这个委员会也会在SystemVerilog 3.1a之上继续为Verilog进行更多的增强。

SystemVerilog构建于Verilog-2001之上。SystemVerilog改进了Verilog代码的生产率、可读性以及可重用性。SystemVerilog中的语言增强提供了更加简洁的硬件描述，同时又为SystemVerilog能够使用现存的工具进入当前的硬件实现流程提供了一个简单的途径。这些增强还为被控的测试平台开发、随机约束的测试平台开发、覆盖驱动的验证、以及基于断言的验证提供了广泛的支持。

SystemVerilog为Verilog-2001加入了扩展的结构和新的结构，包括：

  • 对数据类型的扩展，能够产生更好的代码封装，代码也更加简洁，并且能够产生更严格的规范；
    • C语言数据类型：int、typedef、struct、union、enum；
    • 其它数据类型：有界队列、logic（0、1、X、Z）、bit（0、1）以及安全的标签联合体；
    • 动态数据类型：字符串、类、动态队列、动态数组、包含自动存储空间管理的联合数组使得用户从存储单元释放方面的问题中解脱出来；
    • 动态强制类型转换与位流强制类型转换；
    • 基于单个变量实例的自动/静态说明；
  • 为了获得简洁的描述对操作符进行了扩展；
    • 通配等式与通配不等式；
    • 使用内建方法对语言进行了扩展；
    • 操作符过载；
    • 流操作符；
    • 集合成员资格；
  • 扩展的过程语句；
    • 选择语句中作用于标签联合体的模式匹配；
    • 增强的循环语句加上foreach语句；
    • 类似于C的跳转语句：return、break、continue；
    • 在仿真结束时执行的final块（与initial块相反）；
    • 扩展的事件控制和序列控制；
  • 增强的进程控制；
    • 扩展了always块以便使仿真和综合具有一致的结果；
    • 扩展了fork…join以便对流水线建模以及进行增强的进程控制；
    • 精细的进程控制
  • 增强的任务与函数；
    • 类似于C语言的void函数；
    • 通过引用传递；
    • 缺省参数；
    • 通过名字传递；
    • 可选的参数；
    • 为DPI（直接编程接口）导入/导出函数；
  • 类：面向对象的机制提供了抽象、封装和安全指针的能力；
  • 利用随机约束支持自动化的测试平台；
  • 进程间的通信同步；
    • semaphore；
    • mailbox；
    • 事件扩展、事件变量、以及事件定序；
  • 调度语义的解释和扩展；
  • 基于周期的功能性：时钟控制块和基于周期的特性能够简化开发过程、提高可维护性、以及改进可重用性；
    • 基于周期的信号驱动与采样；
    • 同步采样；
    • 无风险的程序语境
  • 为验证设计意图和功能覆盖意图而采用的断言机制；
    • 特性与序列声明；
    • 使用动作块的断言和覆盖语句
  • 支持扩展的层次；
    • 使用为进行可控的访问而具有导入功能的包来封装声明；
    • 编译单元范围内的嵌套模块以及支持分离编译的外部模块；
    • 扩展了端口声明以便支持接口、事件和变量；
    • $root提供了通过层次引用来明确访问的能力；
  • 通过接口来封装通信以及推动“面向通信”的设计；
  • 功能覆盖
  • 使用直接编程接口（DPI）与其它语言（例如C）进行清晰、有效的互操作；
  • 断言API；
  • 覆盖API；
  • 数据读API；
  • 为SystemVerilog结构所作的VPI扩展
  • 并发断言的形式语义
文档版本：v0.0.00Beta 更新日期：2006-05-21

本译文仅为学习及提供更多信息之目的，任何人不得将其用作商业用途。除非特别声明，原文版权归作者所有，如有转摘请注明原作者以及译者（FPGA技术网）信息。本译文会不断更新，要获得本译文的最新版本请查看本文的在线版本SystemVerilog 3.1a 语言参考手册。

由于时间及译者水平所限，译文中的错误在所难免。如果您对本主题有何建议或意见，请登陆FPGA开发者家园提交，让我们共同完善这项工作，您的参与是我们前进的动力。


第二章 文本值

链接
主题
SystemVerilog 3.1a语言参考手册
第二章 文本值
主题
主题
主题 | 描述
2.1 简介（一般信息） | SystemVerilog文本值词法约定是Verilog文本值词法约定的扩展。SystemVerilog加入了文本时间值、文本数组值、文本结构体，并对文本字符串进行了增强。
2.2 文本值语法 |
2.3 整数和逻辑文本 | 文本整数值和文本逻辑值可以是带有尺寸标识的，也可以是不带有尺寸标识的。对于值的符号、截短和向左扩展，SystemVerilog与Verilog-2001遵守相同的规则。 SystemVerilog还加入了一个使用撇号（'）作为前缀来说明无尺寸1位值的能力，此时在撇号（'）与值之间没有基限定符。无尺寸值的所有位均被设置成这个指定的位值。在一个自决的关联文中，这些文本具有1位的宽度，并且值被当作是无符号的。
2.4 实数文本 | 定点格式（例如1.2）和指数格式（例如2.0e10）的缺省类型是real。可以使用强制类型转换将文本real值转换为shortreal类型（例如shortreal'(1.2)）。 强制类型转换在3.14节中描述。
2.5 时间文本 | 时间文本使用整数或定点格式的数紧跟着一个时间单位来表示（fs ps ns us ms s step），在时间单位和数之间没有空格。例如：
2.6 字符串文本 | 字符串文本由引号包围并且拥有自己的数据类型。非打印字符或其它特殊字符都使用一个反斜杠（\）作为开始。SystemVerilog加入了下列特殊字符串字符：
2.7 数组文本 | 数组文本在语法上与C语言的初始化设置类似，但数组文本允许使用复制操作符（{{}}）。
2.8 结构体文本 | 结构体文本在语法上类似于C语言的初始化设置。结构体文本必须具有一个类型，无论是通过上下文关联还是通过强制类型转换。
链接
主题


2.1 简介（一般信息）

链接
第二章 文本值
SystemVerilog 3.1a语言参考手册
2.1 简介（一般信息）
第二章 文本值

SystemVerilog文本值词法约定是Verilog文本值词法约定的扩展。SystemVerilog加入了文本时间值、文本数组值、文本结构体，并对文本字符串进行了增强。

Group

第二章 文本值

链接
第二章 文本值


2.2 文本值语法

链接
第二章 文本值
SystemVerilog 3.1a语言参考手册
2.2 文本值语法
第二章 文本值
Copy Code
time_literal ::=    // 引用自附录A.8.4
    unsigned_number time_unit
  | fixed_point_number time_unit

time_unit ::= s | ms | us | ns | ps | fs | step

number ::=          // 引用自附录A.8.7
    integral_number
  | real_number

integral_number ::=
    decimal_number
  | octal_number
  | binary_number
  | hex_number

decimal_number ::=
    unsigned_number
  | [size]decimal_base unsigned_number
  | [size]decimal_base x_digit{_}
  | [size]decimal_base z_digit{_}

binary_number ::= [size]binary_base binary_value

octal_number ::= [size]octal_base octal_value

hex_number ::= [size]hex_base hex_value

sign ::= + | -

size ::= non_zero_unsigned_number

non_zero_unsigned_number ::= non_zero_decimal_digit{_|decimal_digit}

real_number ::=
    fixed_point_number
  | unsigned_number[.unsigned_number]exp[sign]unsigned_number

fixed_point_number ::= unsigned_number.unsigned_number

exp ::= e | E

unsigned_number ::= decimal_digit{_|decimal_digit}

string_literal ::= "{Any_ASCII_Characters}"    // 引用自附录A.8.8
Group

第二章 文本值

链接
第二章 文本值


2.3 整数和逻辑文本

链接
第二章 文本值
SystemVerilog 3.1a语言参考手册
2.3 整数和逻辑文本
第二章 文本值

文本整数值和文本逻辑值可以是带有尺寸标识的，也可以是不带有尺寸标识的。对于值的符号、截短和向左扩展，SystemVerilog与Verilog-2001遵守相同的规则。

SystemVerilog还加入了一个使用撇号（'）作为前缀来说明无尺寸1位值的能力，此时在撇号（'）与值之间没有基限定符。无尺寸值的所有位均被设置成这个指定的位值。在一个自决的关联文中，这些文本具有1位的宽度，并且值被当作是无符号的。

Copy Code
'0, '1, 'X, 'x, 'Z, 'z  // 将所有位均设置成这个值

考虑一个例子：

Copy Code
module test;

wire  [7:0] test_signal1;
wire  [7:0] test_signal2;
wire  [7:0] test_signal3;

assign test_signal1 = '1;  // 等效于assign test_signal1 = 8'b11111111
assign test_signal2 = '0;  // 等效于assign test_signal2 = 8'b00000000
assign test_signal3 = 'x;  // 等效于assign test_signal3 = 8'bxxxxxxxx

endmodule
Group

第二章 文本值

链接
第二章 文本值


2.4 实数文本

链接
第二章 文本值
SystemVerilog 3.1a语言参考手册
2.4 实数文本
第二章 文本值

定点格式（例如1.2）和指数格式（例如2.0e10）的缺省类型是real。可以使用强制类型转换将文本real值转换为shortreal类型（例如shortreal'(1.2)）。

强制类型转换在3.14节中描述。

Group

第二章 文本值

链接
第二章 文本值


2.5 时间文本

链接
第二章 文本值
SystemVerilog 3.1a语言参考手册
2.5 时间文本
第二章 文本值

时间文本使用整数或定点格式的数紧跟着一个时间单位来表示（fs ps ns us ms s step），在时间单位和数之间没有空格。例如：

Copy Code
0.1ns
40ps

时间文本被解释成realtime类型的值，它按照当前的时间单位按比例缩放，并根据当前的时间精度四舍五入。注意：如果一个时间文本被用作一个模块或接口实例的实形参数，那么当前的时间单位和精度就是模块或接口实例的时间单位和精度。

Group

第二章 文本值

链接
第二章 文本值


2.6 字符串文本

链接
第二章 文本值
SystemVerilog 3.1a语言参考手册
2.6 字符串文本
第二章 文本值

字符串文本由引号包围并且拥有自己的数据类型。非打印字符或其它特殊字符都使用一个反斜杠（\）作为开始。SystemVerilog加入了下列特殊字符串字符：

Copy Code
\v    // 垂直TAB
\f    // 换页
\a    // 响铃
\x02  // 十六进制数

一个字符串文本必须包含在一个单一的行中，除非新的行紧跟着一个反斜杠（\）。在这种情况下，反斜杠和新行字符会被忽略。对字符串文本的长度没有预定义的限制。

与Verilog-2001一样，一个字符串文本可以赋值到一个整数类型。如果尺寸不同，它会进行右调整。

Copy Code
byte c1 = "A";
bit [7:0] d = "\n";
bit [0:11][7:0] c2 = "hello world\n";
    // c2的值为{8'h68, 8'h65, 8'h6c, 8'h6c, 8'h6f, 8'h20,
    //          8'h77, 8'h6f, 8'h72, 8'h6c, 8'h64, 8'h0a}
bit [0:10][7:0] c3 = "hello world\n";
    // c3的值为{8'h65, 8'h6c, 8'h6c, 8'h6f, 8'h20,
    //          8'h77, 8'h6f, 8'h72, 8'h6c, 8'h64, 8'h0a}
bit [0:9][7:0] c4 = "hello world\n";
    // c4的值为{8'h6c, 8'h6c, 8'h6f, 8'h20,
    //           8'h77, 8'h6f, 8'h72, 8'h6c, 8'h64, 8'h0a}
bit [0:12][7:0] c5 = "hello world\n";
    // c5的值为{8'h00, 8'h68, 8'h65, 8'h6c, 8'h6c, 8'h6f, 8'h20,
    //          8'h77, 8'h6f, 8'h72, 8'h6c, 8'h64, 8'h0a}

一个字符串文本可以被赋值到一个非压缩字节数组。如果尺寸不同，它会进行左调整。

Copy Code
byte c6[0:12] = "hello world\n";

FPGA技术网疑问
关于这一处的左调整，ModelSim SE PLUS 6.1a的实现似乎与参考手册的规定不符。在ModelSim SE PLUS 6.1a仍然进行右调整，也就是C6的值为：
{8'h00, 8'h68, 8'h65, 8'h6c, 8'h6c, 8'h6f, 8'h20, 8'h77, 8'h6f, 8'h72, 8'h6c, 8'h64, 8'h0a}

压缩数组和非压缩数组将在第四章中讨论。字符串文本与数组文本的差别将在接下来的2.7节中讨论。

字符串文本还可以被强制转换成一个压缩数组或非压缩数组，这与将字符串文本赋值到一个压缩数组或非压缩数组遵守相同的规则。强制类型转换将在3.14节中讨论。

SystemVerilog 3.1a还包含一个string数据类型，字符串文本可以赋值给这种类型的变量。string类型的变量具有任意的长度，它们可以动态地改变大小以便容纳任意字符串。

字符串文本是一个压缩数组（宽度是8位的整数倍），当字符串文本赋值到一个string类型或在一个使用string类型操作码的表达式中使用（参看3.7节）的时候，它们可以被隐式地转换成string类型。

Group

第二章 文本值

链接
第二章 文本值


2.7 数组文本

链接
第二章 文本值
SystemVerilog 3.1a语言参考手册
2.7 数组文本
第二章 文本值

数组文本在语法上与C语言的初始化设置类似，但数组文本允许使用复制操作符（{{}}）。

Copy Code
int n[1:2][1:3] = {{0, 1, 2},{3{4}}};

与C语言不同的是，括号的嵌套必须符合数组的维数。然而，我们可以嵌套复制操作符。复制嵌套中的内部括号对会被移除。复制表达式仅仅在一维空间上使用。

Copy Code
int n[1:2][1:3] = {2{{3{4, 5}}}};
// 与{{4, 5, 4, 5, 4, 5}, {4, 5, 4, 5, 4, 5}}相同

如果在关联文中没有指定数据类型，那么数组文本必须使用强制类型转换来说明。

Copy Code
typedef int triple [1:3];
$mydisplay(triple'{0, 1, 2});

数组文本还可以使用它们的索引或类型作为操作键，并且可以使用一个缺省键值（参见7.13节）。

Copy Code
b = {1:1, default:0};  // 索引2和3被赋值为0
Group

第二章 文本值

链接
第二章 文本值


2.8 结构体文本

链接
第二章 文本值
SystemVerilog 3.1a语言参考手册
2.8 结构体文本
第二章 文本值

结构体文本在语法上类似于C语言的初始化设置。结构体文本必须具有一个类型，无论是通过上下文关联还是通过强制类型转换。

Copy Code
typedef struct {
    int a;
    shortreal b;
} ab;

ab c;
c = {0, 0.0}; // 结构体文本的类型由左侧关联文（c）确定

嵌套花括号必须能够反映结构体的结构，例如：

Copy Code
ab abarr[1:0] = {{1, 1.0}, {2, 2.0}};

注意：C语言中可以使用的{1, 1.0, 2, 2.0}在SystemVerilog中是不允许使用的。

结构体文本还可以使用成员名和值，或者是数据类型和缺省值（参见7.14节）：

Copy Code
c = {a:0, b:0.0};  // 成员名及成员名的值
c = {default:0};   // 结构体c的所有元素均被设置成0
d = ab'{int:1, shortreal:1.0};  // 数据类型以及这种类型的所有成员的缺省值

当一个结构体数组被初始化的时候，嵌套括号必须能够反映数组和结构体，例如：

Copy Code
ab abarr[1:0] = {{1, 1.0}, {2, 2.0}};

复制操作符可以用来为完全相同数目的成员设置值，复制表达式中内层括号对会被移除。

Copy Code
struct {
    int X, Y, X;
} XYZ = {3{1}};

typedef struct {
    int a, b[4];
} ab_t;

int a, b, c;
ab_t v1[1:0][2:0];
v1 = {2{{3{a,{2{b,c}}}}}};
    /* 扩展成{{3{{a,{2{b,c}}}}},{3{{a,{2{b,c}}}}}} */
    /* 扩展成{{{a,{2{b,c}}},{a,{2{b,c}}},{a,{2{b,c}}}},
              {{a,{2{b,c}}},{a,{2{b,c}}},{a,{2{b,c}}}}}*/
    /* 扩展成{{{a,{b,c,b,c}},{a,{b,c,b,c}},{a,{b,c,b,c}}},
         {{a,{b,c,b,c}},{a,{b,c,b,c}},{a,{b,c,b,c}}}}*/
Group

第二章 文本值

链接
第二章 文本值


第三章 数据类型

链接
主题
SystemVerilog 3.1a语言参考手册
第三章 数据类型
主题
主题
主题
描述
3.1 简介（一般信息）
为了能够平滑地从/向C语言移植，SystemVerilog支持C语言内建的数据类型，并具有C编译器给出的含义。然而，为了避免int和long数据类型的重复所带来的混淆，在SystemVerilog中，int是32位的，longint是64位的。C语言中float类型在SystemVerilog中称为shortreal，这样就不会与Verilog-2001的real类型混淆。

Verilog-2001具有线网数据类型，它具有0、1、X或Z的值，加上7种强度，具有120个值。Verilog-2001还具有诸如reg（具有0、1、X或Z这四种值）一类的变量数据类型。它们不仅仅是不同的数据类型，而且在使用上也是不同的。SystemVerilog加入了另外一个四值数据类型，这个数据类型被称为logic（参见3.3.2节和5.6节）。

SystemVerilog加入了字符串、chandle和class数据类型，并且增强了Verilog的event数据类型。

Verilog-2001通过使用reg数据类型提供了任意固定长度的算术运算。reg类型的各个位可能具有X或Z的值，然而相对于一个位数组来讲，因为这种数据类型的操作符计算必须检查X和Z，并且需要两倍的数据存储空间，它相对来说缺乏效率。SystemVerilog加入了一个bit数据类型，这种数据类型仅具有0或1两种值。参见3.3.2节中有关两态数据类型的内容。

在从一个较少位数向较多位数自动转换的时候，如果是无符号数则会引起0扩展，如果是有符号数则会引起符号扩展，并且这种情况不会引起警告信息。而从一个较多位数向较少位数自动转换的时候，则会引起警告信息。在logic和bit之间自动转换的时候不会引起警告信息。在从logic值转换到bit值的时候，1转换成1，其它值均转换成0。

typedef可以引入用户定义的数据类型，用户定义的数据类型必须在其使用之前定义。数据类型还可以作为模块或接口的参数，这就使得他们可以像面向对象编程中的类模板一样使用。一个例程在写入的时候可以反转任何数组中元素的顺序，而这在C语言和Verilog中是不可能的。

由于结构体标签和联合体标签具有分离的命名空间，因此它们在C语言中较为复杂。SystemVerilog遵从C的语法，但没有可选的结构体标签。

参见第四章中有关数组的说明。
3.2 数据类型语法
3.3 整数数据类型
SystemVerilog提供了几种整数数据类型，它们是Verilog和C数据类型的结合：

表格3-1：整数数据类型

3.4 real与shortreal数据类型
real1数据类型来自于Verilog-2001，与C语言中的double数据类型相同。shortreal数据类型是一个SystemVerilog数据类型，与C语言中的float数据类型相同。
3.5 void数据类型
void数据类型代表数据不存在。这种类型可以用作函数的返回类型，表示没有返回值。这种数据类型还可以用于标签联合体的成员（参见3.11节）。
3.6 chandle数据类型
chandle数据类型代表使用DPI直接编程接口传递的指针的存储空间（参见第二十七章）。这种类型的尺寸依赖于使用的平台，但在工具运行的机器上应该至少大到能够容纳一个指针。

chandle数据类型的声明语法如下：
3.7 string数据类型
SystemVerilog包含一个string数据类型，它是一个可变尺寸、动态分配的字节数组。SystemVerilog还包含许多特殊的方法来对字符串进行操作。

Verilog也支持字符串文本，但这种支持仅仅是在词法级别上。在Verilog中，字符串文本表现为一个具有宽度为8位整数倍的压缩数组。当一个字符串文本被赋值到一个具有不同尺寸的integral类型的压缩数组变量的时候，它或者被截短到变量的尺寸或者必要时在左侧填补0。

在SystemVerilog中，字符串文本的表现行为与Verilog相同。然而，SystemVerilog还支持string数据类型，我们可以将一个字符串文本赋值到这种数据类型。当使用string数据类型来替代一个integral变量的时候，字符串可以具有任意的长度并且不会发生截短现象。当文本字符串赋值到一个string数据类型或者在一个使用string类型操作数的表达式中使用的时候，它会被隐式地转换成string数据类型。

string类型的变量可以从0到N-1（数组的最后一个元素）进行索引，而且可以作用于一个特殊的空字符串：""。从一个字符串读取一个元素会产生一个字节。
3.8 event数据类型
event数据类型是Verilog命名事件的增强。SystemVerilog事件为一个同步对象提供了一个句柄。与Verilog一样，事件变量可以被显式地触发以及等待。更进一步，SystemVerilog事件还具有一个稳固的触发状态，它在整个时间步值间隔内持续。此外，一个事件变量可以被赋值为另外一个事件变量或者被赋值为特殊的null值。当赋值为另外一个事件变量的时候，这两个事件变量均指向相同的同步对象。当赋值为null的时候，同步对象与事件变量之间的关系被切断。事件还可以作为任务的参数传递。

event的声明语法如下：
3.9 用户定义的类型
3.10 枚举
3.11 结构体与联合体
3.12 类
类是数据以及一组对数据进行操作的子程序的集合。类中的数据被称为类属性，它的子程序被称为方法。类属性和方法一起定义了一个类实例或对象的内容和能力。
3.13 单一类型与集合类型
数据类型可以分为两类：单一类型与集合类型。一个单一类型应该是除非压缩结构体、非压缩联合体、或非压缩数组（参见第四章有关数组的内容）之外的任何数据类型。一个集合类型应该是任何非压缩结构体、非压缩联合体、或非压缩数组数据类型。一个单一变量或表达式代表一个单一的值、符号、或句柄。集合表达式和变量代表一组单一值。integral类型总是单一的，即使它们可以被分片成多个单一值。

通过定义这些类别，操作符和函数能够简单地将这些数据类型当作一个集合组来引用。例如：某些函数能够递归地解析一个集合类型直到获得一个单一值，然后就可以对每一个单一值进行操作。

注意：虽然类是一种数据类型，但没有直接的类变量或表达式，而仅仅存在类对象的句柄，并且类对象的句柄为单一值。因此，类不需要按这种方式分类（参见第十一章有关类的内容）。
3.14 强制类型转换
3.15 $cast动态强制类型转换
在由于不同的数据类型而导致变量不能正常赋值的情况下，SystemVerilog提供了$cast系统任务来进行赋值操作。$cast可以作为任务或函数来调用。

$case的语法如下：
3.16 位流强制类型转换
强制类型转换还可以应用于非压缩数组以及非压缩结构体。这样就使得通过显式强制类型转换在位流类型之间自由地转换成为可能。可以压缩成一个位流的类型称为位流类型。位流类型包含下列的类型：

  • 任何integral、压缩、或字符串类型
  • 非压缩数组、结构体、或上述类型的类
  • 任何上述类型的动态尺寸数组（动态的、联合的、或队列）

这个定义是递归的，例如，一个包含int队列的结构体是一个位流类型。

假定A具有source_t的位流类型，B具有dest_t的位流类型，那么我们可以使用显式强制类型转换将A转换到B：

链接
主题


3.1 简介（一般信息）

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.1 简介（一般信息）
第三章 数据类型

为了能够平滑地从/向C语言移植，SystemVerilog支持C语言内建的数据类型，并具有C编译器给出的含义。然而，为了避免int和long数据类型的重复所带来的混淆，在SystemVerilog中，int是32位的，longint是64位的。C语言中float类型在SystemVerilog中称为shortreal，这样就不会与Verilog-2001的real类型混淆。

Verilog-2001具有线网数据类型，它具有0、1、X或Z的值，加上7种强度，具有120个值。Verilog-2001还具有诸如reg（具有0、1、X或Z这四种值）一类的变量数据类型。它们不仅仅是不同的数据类型，而且在使用上也是不同的。SystemVerilog加入了另外一个四值数据类型，这个数据类型被称为logic（参见3.3.2节和5.6节）。

SystemVerilog加入了字符串、chandle和class数据类型，并且增强了Verilog的event数据类型。

Verilog-2001通过使用reg数据类型提供了任意固定长度的算术运算。reg类型的各个位可能具有X或Z的值，然而相对于一个位数组来讲，因为这种数据类型的操作符计算必须检查X和Z，并且需要两倍的数据存储空间，它相对来说缺乏效率。SystemVerilog加入了一个bit数据类型，这种数据类型仅具有0或1两种值。参见3.3.2节中有关两态数据类型的内容。

在从一个较少位数向较多位数自动转换的时候，如果是无符号数则会引起0扩展，如果是有符号数则会引起符号扩展，并且这种情况不会引起警告信息。而从一个较多位数向较少位数自动转换的时候，则会引起警告信息。在logic和bit之间自动转换的时候不会引起警告信息。在从logic值转换到bit值的时候，1转换成1，其它值均转换成0。

typedef可以引入用户定义的数据类型，用户定义的数据类型必须在其使用之前定义。数据类型还可以作为模块或接口的参数，这就使得他们可以像面向对象编程中的类模板一样使用。一个例程在写入的时候可以反转任何数组中元素的顺序，而这在C语言和Verilog中是不可能的。

由于结构体标签和联合体标签具有分离的命名空间，因此它们在C语言中较为复杂。SystemVerilog遵从C的语法，但没有可选的结构体标签。

参见第四章中有关数组的说明。

Group

第三章 数据类型

链接
第三章 数据类型


3.2 数据类型语法

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.2 数据类型语法
第三章 数据类型
Copy Code
data_type ::=     // 引用自附录A.2.2.1
    integer_vector_type [signing] {packed_dimension}
  | integer_atom_type [signing]
  | non_integer_type
  | struct_union [packed [signing]] {struct_union_member {struct_union_member}}
        {packed_dimension}
  | enum [enum_base_type] {enum_name_declaration{, enum_name_declaration}}
  | string
  | chandle
  | virtual [interface] interface_identifier
  | [class_scope | package_scope] type_identifier {packed_dimension}
  | class_type
  | event
  | ps_covergroup_identifier

enum_base_type ::=
    integer_atom_type [signing]
  | integer_vector_type [signing] [packed_dimension]
  | type_identifier [packed_dimension]

enum_name_declaration ::=
    enum_identifier [[integral_number[:integral_number]]][=constant_expression]

class_scope ::= class_type ::

class_type ::=
    ps_class_identifier [parameter_value_assignment]
        {:: class_identifier [parameter_value_assignment]}

integer_type ::= integer_vector_type | integer_atom_type

integer_atom_type ::= byte|shortint|int|longint|integer|time

integer_vector_type ::= bit|logic|reg

non_integer_type ::= shortreal|real|realtime

net_type ::= supply0|supply1|tri|triand|trior|tri0|tri1|wire|wand|wor

signing ::= signed|unsigned

simple_type ::= integer_type | non_integer_type | ps_type_identifier

struct_union_member ::=
    {attribute_instance} data_type_or_void list_of_variable_identifiers;

data_type_or_void ::= data_type | void

struct_union ::= struct|union [tagged]

variable_decl_assignment ::=     // 引用自附录A.2.4
    variable_identifier variable_dimension[= expression]
  | dynamic_array_variable_identifier[][= dynamic_array_new]
  | class_variable_identifier[= class_new]
  | [covergroup_variable_identifier] = new [(list_of_arguments)]

语法 3-1 — 数据类型（摘录自附录A）

Group

第三章 数据类型

链接
第三章 数据类型


3.3 整数数据类型

链接
第三章 数据类型, 主题
SystemVerilog 3.1a语言参考手册
3.3 整数数据类型
第三章 数据类型 | 主题

SystemVerilog提供了几种整数数据类型，它们是Verilog和C数据类型的结合：

表格3-1：整数数据类型

shortint | 两态SystemVerilog数据类型，16位有符号整数
int | 两态SystemVerilog数据类型，32位有符号整数
longint | 两态SystemVerilog数据类型，64位有符号整数
byte | 两态SystemVerilog数据类型，8位有符号整数或ASCII码字符
bit | 两态SystemVerilog数据类型，用户定义的向量尺寸
logic | 四态SystemVerilog数据类型，用户定义的向量尺寸
reg | 四态Verilog-2001数据类型，用户定义的向量尺寸
integer | 四态Verilog-2001数据类型，32位有符号整数
time | 四态Verilog-2001数据类型，64位无符号整数
Group

第三章 数据类型

主题
主题 | 描述
3.3.1 integral类型 | 在本参考手册中，术语integral指的基本的整数数据类型、压缩数组、压缩结构体、压缩联合体、枚举类型和时间类型。
3.3.2 两态（两值）与四态（四值）数据类型 | 具有未知值（X）和高阻值（Z）的类型称为四态类型，包括logic、reg、integer和time。其它不具有未知值及高阻值的类型称为两态类型，例如bit和int。 int和integer的区别是：int是两态逻辑而integer是四态逻辑。四态值需要一个额外的位来编码X和Z状态。两态数据类型的仿真速度更快一些，而且占用更少的内存，因而在某些设计风格中成为首选数据类型。
3.3.3 有符号与无符号数据类型 | 整数类型使用整数算术，并且可以是有符号的也可以是无符号的。这些会影响某些操作码的含义，例如“<”等。
链接
第三章 数据类型, 主题


3.3.1 integral类型

链接
3.3 整数数据类型
SystemVerilog 3.1a语言参考手册
3.3.1 integral类型
3.3 整数数据类型

在本参考手册中，术语integral指的基本的整数数据类型、压缩数组、压缩结构体、压缩联合体、枚举类型和时间类型。

Group

3.3 整数数据类型

链接
3.3 整数数据类型


3.3.2 两态（两值）与四态（四值）数据类型

链接
3.3 整数数据类型
SystemVerilog 3.1a语言参考手册
3.3.2 两态（两值）与四态（四值）数据类型
3.3 整数数据类型

具有未知值（X）和高阻值（Z）的类型称为四态类型，包括logic、reg、integer和time。其它不具有未知值及高阻值的类型称为两态类型，例如bit和int。

int和integer的区别是：int是两态逻辑而integer是四态逻辑。四态值需要一个额外的位来编码X和Z状态。两态数据类型的仿真速度更快一些，而且占用更少的内存，因而在某些设计风格中成为首选数据类型。

Group

3.3 整数数据类型

链接
3.3 整数数据类型


3.3.3 有符号与无符号数据类型

链接
3.3 整数数据类型
SystemVerilog 3.1a语言参考手册
3.3.3 有符号与无符号数据类型
3.3 整数数据类型

整数类型使用整数算术，并且可以是有符号的也可以是无符号的。这些会影响某些操作码的含义，例如“<”等。

Copy Code
int unsigned ui;
int signed si;

缺省情况下，byte、shortint、int、integer和longint是有符号的。bit、reg、logic以及这几种类型的数组在缺省情况下是无符号的。

注意：signed关键字是Verilog-2001的一部分。unsigned关键字在Verilog-2001中是保留关键字，但未被使用。

参看第七章中有关操作码和表达式的说明。

Group

3.3 整数数据类型

链接
3.3 整数数据类型


3.4 real与shortreal数据类型

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.4 real与shortreal数据类型
第三章 数据类型

real1数据类型来自于Verilog-2001，与C语言中的double数据类型相同。shortreal数据类型是一个SystemVerilog数据类型，与C语言中的float数据类型相同。

Notes

1. real和shortreal类型在IEEE 754-1985中描述，IEEE-754-1985是一个有关浮点数的IEEE标准（参见附录K中的[K1]）。

Group

第三章 数据类型

链接
第三章 数据类型


3.5 void数据类型

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.5 void数据类型
第三章 数据类型

void数据类型代表数据不存在。这种类型可以用作函数的返回类型，表示没有返回值。这种数据类型还可以用于标签联合体的成员（参见3.11节）。

Group

第三章 数据类型

链接
第三章 数据类型


3.6 chandle数据类型

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.6 chandle数据类型
第三章 数据类型

chandle数据类型代表使用DPI直接编程接口传递的指针的存储空间（参见第二十七章）。这种类型的尺寸依赖于使用的平台，但在工具运行的机器上应该至少大到能够容纳一个指针。

chandle数据类型的声明语法如下：

Copy Code
chandle variable_name;

其中variable_name是一个有效的标识符。chandle类型的变量总是被初始化成null值，它在C语言中具有0的值。chandle类型的使用是非常受限的，仅仅在下列情况下能够合法使用：

  • chandle变量仅仅能够使用下列操作符：
    • 与另外一个chandle变量或与null进行相等（==）和不等（!=）操作；
    • 与另外一个chandle变量或与null进行条件相等（===）和条件不等（!==）操作（与==和!=具有相同的语义）；
  • 可以作为一个布尔值进行检测，如果chandle变量为null则为0，否则为1。
  • chandle变量仅能执行如下的赋值操作：
    • 赋值为另外一个chandle变量；
    • 赋值成null；
  • chandle变量可以插入到联合数组（参看4.9节）中，但这样的联合数组中的任意两个条目的相对顺序都是变化的，甚至在相同工具的两次连续运行中也是如此；
  • 可以在类中使用chandle；
  • chandle可以作为参数传递给函数或任务；
  • chandle可以从函数中返回；

在下列情况中chandle的使用是受限的：

  • 端口中不应该有chandle数据类型；
  • chandle不能被赋值到其它任何数据类型的变量；
  • 在下列情况中不能使用chandle：
    • 除了上面说明的表达式外的任何其它表达式；
    • 作为端口；
    • 在敏感列表或事件表达式中；
    • 在连续赋值语句中；
    • 在联合体中；
    • 在压缩类型中；
Group

第三章 数据类型

链接
第三章 数据类型


3.7 string数据类型

链接
第三章 数据类型, 主题
SystemVerilog 3.1a语言参考手册
3.7 string数据类型
第三章 数据类型 | 主题

SystemVerilog包含一个string数据类型，它是一个可变尺寸、动态分配的字节数组。SystemVerilog还包含许多特殊的方法来对字符串进行操作。

Verilog也支持字符串文本，但这种支持仅仅是在词法级别上。在Verilog中，字符串文本表现为一个具有宽度为8位整数倍的压缩数组。当一个字符串文本被赋值到一个具有不同尺寸的integral类型的压缩数组变量的时候，它或者被截短到变量的尺寸或者必要时在左侧填补0。

在SystemVerilog中，字符串文本的表现行为与Verilog相同。然而，SystemVerilog还支持string数据类型，我们可以将一个字符串文本赋值到这种数据类型。当使用string数据类型来替代一个integral变量的时候，字符串可以具有任意的长度并且不会发生截短现象。当文本字符串赋值到一个string数据类型或者在一个使用string类型操作数的表达式中使用的时候，它会被隐式地转换成string数据类型。

string类型的变量可以从0到N-1（数组的最后一个元素）进行索引，而且可以作用于一个特殊的空字符串：""。从一个字符串读取一个元素会产生一个字节。

FPGA技术网提示：
string类型变量的索引从字符串的左侧开始排列，例如：对字符串"Hello World!"，索引0对应"H"，索引1对应"e"，依此类推...。

string类型变量的声明语法如下：

Copy Code
string variable_name [= initial_value];

这里的variable_name是一个有效的标识符，可选的initial_value可以是一个字符串文本也可以是一个空字符串（""）。例如：

Copy Code
string myName = “John Smith”;

如果在声明中没有指定初始值，变量会被初始化成空字符串（""）。

SystemVerilog提供了一组操作符，这些操作符可以用来处理字符串变量和字符串文本的组合。string数据类型的基本操作符在表格3-2中给出。

一个字符串文本可以被赋值到一个string或integral类型的变量。如果它们的尺寸不同，字符串文本会进行右调整，并且在必要的时候在左侧进行截短或者在左侧填补0。例如：

Copy Code
byte c = "A";                  // 将c赋值为”A”
bit [10:0] a = "\x41";         // 将a赋值为’b000_0100_0001
bit [1:4][7:0] h = "hello";    // 将h赋值为”ello”

一个string、字符串文本、或压缩数组可以被赋值到一个string变量。string变量可以增长或缩减以便容纳压缩数组。如果压缩数组的尺寸（以位为单位）不是8的整数倍，那么压缩数组会在左侧填入0。例如：

Copy Code
string s1 = "hello";   // 将s1设置为"hello"
bit [11:0] b = 12'ha41;
string s2 = b;         // 将s2设置为'h0a41

第二个例子：

Copy Code
reg [15:0] r;
integer i = 1;
string b = "";
string a = {"Hi", b};
r = a;           // OK
b = r;           // OK （隐式强制类型转换，可以发布一个警告）
b = "Hi";        // OK
b = {5{"Hi"}};   // OK
a = {i{"Hi"}};   // OK（非常量复制）
r = {i{"Hi"}};   // 无效（非常量复制）
a = {i{b}};      // OK
a = {a, b};      // OK
a = {"Hi", b};   // OK
r = {"H",""};    // 产生"H\0"，""被转换成8'b0
b = {"H",""};    // 产生"H"，""是空字符串
a = {a, b};      // OK
a[0] = "h";      // OK, 与a[0] = "hi"相同

表格 3-2：字符串操作符

操作符 | 语义
Str1 == Str2 | 相等。检查两个字符串是否相等。如果相等则结果为1，否则结果为0。两个字符串的类型可以都是string，或者其中一个为字符串文本。如果两个均为字符串文本，那么表达式与Verilog中对整数类型的相等操作符相同。可以使用空字符串（""）。
Str1 != Str2 | 不等。==的逻辑否。
Str1 < Str2 Str1 <= Str2 Str1 > Str2 Str1 >= Str2 | 比较，关系操作符。使用两个字符串的词典编撰顺序比较，如果对应的条件为真则返回1。比较类似于ANSI C的strcmp函数（或字符串比较方法）（以词汇顺序），并且包含嵌入的空字节。两个操作数可以都是string类型，或者其中一个是字符串文本。
{Str1, Str2, …, Strn} | 串联。每一个操作符都可以是string类型或一个字符串文本（它会被隐式地转换成string类型）。如果至少一个操作数为string类型，那么表达式计算成串联字符串并且具有string的类型。如果所有的操作数都是字符串文本，那么表达式的行为就像Verilog中integral类型的串联一样。如果结果接着使用在一个调用string类型的表达式中，那么它被隐式地转换成string类型。
{multiplier{Str}} | 复制。Str可以是string类型或者是字符串文本。multiplier必须是integral类型并且可以是非常量。如果multiplier是非常量或者Str是string类型，那么结果就是包含N个Str串联的字符串，其中N由multiplier指定。如果Str是一个文本并且multiplier是常量，那么表达式的行为就类似于Verilog中的数值复制（如果结果被使用在另一个调用string类型的表达式中，那么它被隐式地转换成string类型）。
Str[index] | 索引。返回一个字节，值为给定索引的ASCII码。索引的范围从0到N-1，其中N为字符串中字符的数目。如果给定的索引超出了范围，那么返回0。在语义上等价于Str.getc(index)，参见3.7.3节。
Str.method(…) | 圆点（.）操作符用来调用字符串的一个特定方法。

SystemVerilog还包含许多特殊的方法来对字符串进行操作。这些方法使用内建的方法符号。这些方法将在接下来的几节中描述。

Group

第三章 数据类型

主题
主题 | 描述
3.7.1 len() |
3.7.2 putc() |
3.7.3 getc() |
3.7.4 toupper() |
3.7.5 tolower() |
3.7.6 compare() |
3.7.7 icompare() |
3.7.8 substr(int i, int j) |
3.7.9 atoi(), atohex(), atooct(), atobin() |
3.7.10 atoreal() |
3.7.11 itoa() |
3.7.12 hextoa() |
3.7.13 octtoa() |
3.7.14 bintoa() |
3.7.15 realtoa() |
链接
第三章 数据类型, 主题


3.7.1 len()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.1 len()
3.7 string数据类型
Copy Code
function int len()
  • str.len()返回字符串的长度，也就是字符串中字符的数目（不包括任何终结字符）。
  • 如果str是""，那么str.len()返回0。
Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.2 putc()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.2 putc()
3.7 string数据类型
Copy Code
task putc(int i, string s)
task putc(int i, byte c)
  • str.putc(i, c)将str中的第i个字符替换成指定的integral值；
  • str.putc(i, s)将str中的第i个字符替换成s中的第一个字符；
  • s可以是赋值为一个字符串的任何表达式；
  • putc不会改变str的尺寸，如果i < 0或i >= str.len()，那么str不会发生改变；

注意：str.putc(j, x)在语义上等价于str[j] = x。

Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.3 getc()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.3 getc()
3.7 string数据类型
Copy Code
function int getc(int i)
  • str.getc(i)返回str中的第i个字符的ASCII码值；
  • 如果i < 0或i >= str.len()，那么str.getc(i)返回0；

注意：x = str.getc(i)在语义上等价于x = str[j]。

Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.4 toupper()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.4 toupper()
3.7 string数据类型
Copy Code
function string toupper()
  • str.toupper()返回一个字符串并将str中的字符转换成大写形式；
  • str不会发生变化；
Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.5 tolower()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.5 tolower()
3.7 string数据类型
Copy Code
function string tolower()
  • str.tolower()返回一个字符串并将str中的字符转换成小写形式；
  • str不会发生变化；
Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.6 compare()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.6 compare()
3.7 string数据类型
Copy Code
function int compare(string s)
  • str.compare (s)将str与s进行比较，就像ANSI C strcmp函数一样，并且包含嵌入的空字节；

参见3.7节，表格3-2中有关字符串关系操作符的内容。

Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.7 icompare()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.7 icompare()
3.7 string数据类型
Copy Code
function int icompare(string s)
  • str.icompare(s)将str与s进行比较，就像ANSI C strcmp函数一样，但这种比较是大小写敏感的并且包含嵌入的空字节；
Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.8 substr(int i, int j)

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.8 substr(int i, int j)
3.7 string数据类型
Copy Code
function int substr(int i, int j)
  • str.substr (i, j)返回一个由str中位置i到位置j之间的字符组成的一个新的字符串；
  • 如果i < 0, j < i, 或者j >= str.len()，那么substr()返回""（空字符串）。
Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.9 atoi(), atohex(), atooct(), atobin()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.9 atoi(), atohex(), atooct(), atobin()
3.7 string数据类型
Copy Code
function integer atoi()
function integer atohex()
function integer atooct()
function integer atobin()
  • str.atoi()返回一个str中由ASCII码字符表示的十进制数。例如：
Copy Code
str = “123”;
int i = str.atoi(); // 将i赋值为123

在转换过程中会扫描所有的前几位阿拉伯数字以及下划线字符（_），只要遇到任何其它字符或到达字符串的结尾则停止扫描。它不会分析整数文本的完整语法（符号、尺寸、撇号、基）。

  • str.atohex()将字符串解释成十六进制数；
  • str.atooct()将字符串解释成八进制数；
  • str.atobin()将字符串解释成二进制数；
Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.10 atoreal()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.10 atoreal()
3.7 string数据类型
Copy Code
function real atoreal()
  • str.atoreal()返回一个str中由ASCII码字符表示的实数。

转换过程会分析实数常量的Verilog语法。只要它遇到与这个语法不一致的任何字符，或到达字符串的尾部则停止扫描。如果没有遇到阿拉伯数字则返回0。

Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.11 itoa()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.11 itoa()
3.7 string数据类型
Copy Code
task itoa(integer i)
  • str.itoa(i)将i的ASCII码十进制表示存储到str（与atoi相反）。
Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.12 hextoa()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.12 hextoa()
3.7 string数据类型
Copy Code
task hextoa(integer i)
  • str.hextoa(i)将i的ASCII码十六进制表示存储到str（与atohex相反）。
Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.13 octtoa()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.13 octtoa()
3.7 string数据类型
Copy Code
task octtoa(integer i)
  • str.octtoa(i)将i的ASCII码八进制表示存储到str（与atooct相反）。
Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.14 bintoa()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.14 bintoa()
3.7 string数据类型
Copy Code
task bintoa(integer i)
  • str.bintoa(i)将i的ASCII码二进制表示存储到str（与atobin相反）。
Group

3.7 string数据类型

链接
3.7 string数据类型


3.7.15 realtoa()

链接
3.7 string数据类型
SystemVerilog 3.1a语言参考手册
3.7.15 realtoa()
3.7 string数据类型
Copy Code
task realtoa(real r)

str.realtoa(r)将r的ASCII码实数表示存储到str（与atoreal相反）。

Group

3.7 string数据类型

链接
3.7 string数据类型


3.8 event数据类型

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.8 event数据类型
第三章 数据类型

event数据类型是Verilog命名事件的增强。SystemVerilog事件为一个同步对象提供了一个句柄。与Verilog一样，事件变量可以被显式地触发以及等待。更进一步，SystemVerilog事件还具有一个稳固的触发状态，它在整个时间步值间隔内持续。此外，一个事件变量可以被赋值为另外一个事件变量或者被赋值为特殊的null值。当赋值为另外一个事件变量的时候，这两个事件变量均指向相同的同步对象。当赋值为null的时候，同步对象与事件变量之间的关系被切断。事件还可以作为任务的参数传递。

event的声明语法如下：

Copy Code
event variable_name [= initial_value];

其中variable_name是一个有效的标识符，可选的initial_value可以是另外一个事件变量或null值。

如果在声明事件变量的时候没有指定初始值，那么事件变量会被初始化成一个新的同步对象。

如果事件变量被赋值为null，那么事件变成非阻塞的，就好像它被永久触发一样。例如：

Copy Code
event done;             // 声明一个新的命名为done的事件
event done_too = done;  // 将done_too声明为done的别名
event empty = null;     // 没有同步对象的事件变量

事件的操作和语义将在13.5节中详细讨论。

Group

第三章 数据类型

链接
第三章 数据类型


3.9 用户定义的类型

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.9 用户定义的类型
第三章 数据类型
Copy Code
type_declaration ::=            // 引用自附录A.2.1.3
    typedef data_type type_identifier variable_dimension;
  | typedef interface_instance_identifier.type_identifier type_identifer;
  | typedef [enum|struct|union|class] type_identifier;

语法3-2 — 用户定义的类型（摘录自附录A）

象C语言一样，用户可以使用typedef定义一个新的数据类型。

Copy Code
tyepdef int intP;

这个新类型可以进行如下的实例化操作：

Copy Code
intP a, b;

如果一个类型首先使用空的typedef标识为类型，那么它就可以在其定义之前使用。

Copy Code
typedef foo;
foo f = 1;
typedef int foo;

注意：这种方法不适合于枚举值，枚举类型必须在使用之前定义。

除了不允许层次化地引用用户定义的类型标识符之外，用户定义的类型标识符与数据标识符具有相同的作用范围规则。SystemVerilog允许通过端口引用在接口内定义的类型标识符，只要它们在使用之前在本地重新定义。

Copy Code
interface intf_i;
    typedef int data_t;
endinterface

module sub (intf_i p)
    typedef p.data_t mydata_t;
    my_data_t data;
    // 当'data'连接到上述接口的时候，它的类型是int
endmodule

因为强制类型转换（参见3.14节）中仅允许使用简单类型名，因此对强制类型转换中的复合数据类型必须使用用户定义的类型名。另外，当使用非压缩数组的时候，用户定义的数据类型必须作为类型参数值使用。

有时一个用户定义的类型需要在类型的内容被定义之前声明。这对于由enum、struct、union和class派生出的用户定义类型很有用处。对于这种应用的例子参看11.24节。这种方式通过下列的typedef格式来提供支持。

Copy Code
tyepdef enum type_declaration_identifier;
tyepdef struct type_declaration_identifier;
tyepdef union type_declaration_identifier;
tyepdef class type_declaration_identifier;
tyepdef type_declaration_identifier;

注意：这种方式在11.24节中展示的类耦合定义中很有用，但它不能使用在结构体的耦合定义中，因为结构体是静态声明的，并且不支持结构体的指针。

最后一个形式表明，用户定义类型中的类型不必在提前声明中定义。

在generate内部的typedef不应该定义一个在提前定义范围外的提前定义的真实类型。

Group

第三章 数据类型

链接
第三章 数据类型


3.10 枚举

链接
第三章 数据类型, 主题
SystemVerilog 3.1a语言参考手册
3.10 枚举
第三章 数据类型 | 主题
Copy Code
data_type ::=             // 引用自附录A.2.2.1
    ...
  | enum [enum_base_type] {enum_name_declaration{, enum_name_declaration}}

enum_base_type ::=
    integer_atom_type [signing]
  | integer_vector_type [signing] [packed_dimension]
  | type_identifier [packed_dimension]24

enum_name_declaration ::=
    enum_identifier [[integral_number[:integral_number]]][=constant_expression]

语法3-3 — 枚举类型（摘录自附录A）

枚举类型用来声明一组integral类型的命名常量。枚举数据类型能够抽象地声明具有强烈类型含义的变量，在声明的时候不需要声明一个数据类型或数据值，我们可以在以后设计需要更详细定义的时候加入要求的数据类型和值。枚举数据类型还可以使用枚举名字而不是枚举值来方便地引用或显示。

当没有数据类型声明的时候，缺省的数据类型是int。在枚举类型中使用的任何其它数据类型都要求一个显式的数据类型声明。

一个枚举类型定义了一组具有名字的值。在下面的例子中，light1和light2被定义成一个匿名（无名字的）枚举int类型，它包含了三个成员：read、yellow和green。

Copy Code
enum {red, yellow, green} light1, light2; // 匿名int类型

对于没有显式数据类型的枚举类型或者一个具有显式两态声明的枚举类型，如果将x或z赋值给枚举名字，那么它在语法上是错误的。

Copy Code
// 语法错误：IDLE=2'b00, XX=2'bx <错误>, S1=2'b01, S2=2'b10
enum {IDLE, XX='x, S1=2'b01, S2=2'b10} state, next;

对于一个四态类型（例如integer）的枚举声明，允许包含具有x或z赋值的一个或多个名字。

Copy Code
// 正确：IDLE=0, XX='x, S1=1, S2=2
enum integer {IDLE, XX='x, S1=2'b01, S2=2'b10} state, next;

如果在一个具有x或z赋值的枚举名字后跟着一个未赋值的枚举名字，那么在语法上是错误的。

Copy Code
// 语法错误：IDLE=2'b00, XX=2'bx, S1=??, S2=??
enum integer {IDLE, XX='x, S1, S2} state, next;

值可以被强制转换成integer类型，并且从初始值0开始递增。它还可以被覆盖。

Copy Code
enum {bronze=3, silver, gold} medal; // silver=4, gold=5

在枚举类型中可以设置某些名字的值，而其他的不设置。一个枚举命名常量的可选值是一个确立时的常量表达式（参见5.3节），它可以包含参数、本地参数、genvar、其它枚举命名常量、以及这些类型的常量函数。但不允许使用层次化的名字和const变量。一个没有值的名字被自动地赋值为前一个名字的值的递增。

Copy Code
// c被自动地赋值为8的递增值
enum {a=3, b=7, c} alphabet;

如果一个自动递增的值在相同枚举声明中的其他地方被赋值，那么会产生一个语法错误。

Copy Code
// 语法错误：c和d均被赋值为8
enum {a=0, b=7, c, d=8} alphabet;

如果第一个名字没有赋值，那么它具有0的初始值。

Copy Code
// a=0, b=7, c=8
enum {a, b=7, c} alphabet;

在枚举可表示范围之外的任何枚举编码都是错误的。如果任何一个枚举成员被定义成不同尺寸的常量，那么会产生一个语法错误。

Copy Code
// 正确的声明 – bronze和gold是无尺寸的
enum bit [3:0] {bronze='h3, silver, gold='h5} meda14;

// 正确的声明 – bronze和gold的尺寸是冗余的
enum bit [3:0] {bronze=4'h3, silver, gold=4'h5} meda14;

// bronze和gold成员的声明是错误的
enum bit [3:0] {bronze=5'h13, silver, gold=3'h5} meda14;

// c的声明是错误的，要求至少两位
enum bit [0:0] {a, b, c} alphabet;

赋值中的枚举类型、作为参数的枚举类型以及操作符中的枚举类型的类型检查在3.10.3节中描述。像C一样，枚举类型中没有文本的过载，因此，medal和medal4不能够在相同的范围内定义，因为它们包含了相同的名字。

Group

第三章 数据类型

主题
主题 | 描述
3.10.1 将新的数据类型定义成枚举类型 | 我们可以为枚举类型指定一个类型名，这样相同的类型可以在许多地方使用。
3.10.2 枚举类型的排列 | 枚举元素的排列可以使用下列的语法自动指定。 表格 3-3：枚举元素的排列
3.10.3 类型检查 | SystemVerilog枚举类型是一种强类型，因此，一个enum类型的变量不能被直接赋值为一个位于枚举集范围之外的值，除非使用强制类型转换或者除非这个枚举变量是一个联合体的成员。这种强大的类型检查能够防止用户偶然地将枚举类型变量赋值为不存在的值。这个限制仅仅适用于被显式地声明成一个类型的枚举。枚举值仍然可以在表达式中作为常量使用，并且运算结果也可以赋值到任何一个具有兼容的integral类型的变量。 无论是枚举名还是它们的整数值都必须是唯一的。它们的值可以被设置为任意integral常量值，或者从初始值0开始递增。如果将两个值设置到相同的枚举名，或者设置的值与递增值冲突都是错误的。 枚举变量在赋值、传递和关系操作符中进行类型检查。枚举变量可以自动转换成integral值，然而，将任何表达式赋值到枚举变量均要求一个显式的强制类型转换。例如：
3.10.4 数值表达式中的枚举类型 | 枚举变量的元素可以使用在数值表达式中。表达式中使用的值是与枚举值相关的数值。例如：
链接
第三章 数据类型, 主题


3.10.1 将新的数据类型定义成枚举类型

链接
3.10 枚举
SystemVerilog 3.1a语言参考手册
3.10.1 将新的数据类型定义成枚举类型
3.10 枚举

我们可以为枚举类型指定一个类型名，这样相同的类型可以在许多地方使用。

Copy Code
typedef enum {NO, YES} boolean;
boolean myvar; // 命名的类型
Group

3.10 枚举

链接
3.10 枚举


3.10.2 枚举类型的排列

链接
3.10 枚举
SystemVerilog 3.1a语言参考手册
3.10.2 枚举类型的排列
3.10 枚举

枚举元素的排列可以使用下列的语法自动指定。

表格 3-3：枚举元素的排列

name | 将下一个连续的数与name关联起来
name = C | 将常量C与name关联起来
name[N] | 以下列顺序产生N个命名的常量：name0、name1、…、nameN-1。N必须是一个integral常量。
name[N] = C | 可选地，一个常量可以被赋值到产生的命名常量以便将常量与第一个产生的命名常量关联起来。后续产生的命名常量与连续的值相关联。N必须是一个integral常量。
name[N:M] | 产生一系列的命名常量，它起始于nameN，然后递增或递减直到到达命名常量nameM。
name[N:M] = C | 可选地，一个常量可以被赋值到产生的命名常量以便将常量与第一个产生的命名常量关联起来。后续产生的命名常量与连续的值相关联。N和M必须是一个integral常量。

例如：

Copy Code
typedef enum {add=10, sub[5], jmp[6:8]} E1;

在这个例子中定义了一个枚举类型E1，它将10赋值给枚举命名常量add。它还产生了枚举命名常量sub0、sub1、sub2、sub3、sub4，并将它们分别赋值为11…15。最后，这个例子还产生了枚举命名常量jmp6、jmp7和jmp8，并分别赋值为16 – 18。

Copy Code
enum {register[2]=1, register[2:4]=10} vr;

上面的例子声明了枚举变量vr，它产生了枚举命名常量register0和register1，并分别赋值为1和2。然后，它产生了枚举命名常量register2、register3和register4，并分别赋值为10、11和12。

Group

3.10 枚举

链接
3.10 枚举


3.10.3 类型检查

链接
3.10 枚举
SystemVerilog 3.1a语言参考手册
3.10.3 类型检查
3.10 枚举

SystemVerilog枚举类型是一种强类型，因此，一个enum类型的变量不能被直接赋值为一个位于枚举集范围之外的值，除非使用强制类型转换或者除非这个枚举变量是一个联合体的成员。这种强大的类型检查能够防止用户偶然地将枚举类型变量赋值为不存在的值。这个限制仅仅适用于被显式地声明成一个类型的枚举。枚举值仍然可以在表达式中作为常量使用，并且运算结果也可以赋值到任何一个具有兼容的integral类型的变量。

无论是枚举名还是它们的整数值都必须是唯一的。它们的值可以被设置为任意integral常量值，或者从初始值0开始递增。如果将两个值设置到相同的枚举名，或者设置的值与递增值冲突都是错误的。

枚举变量在赋值、传递和关系操作符中进行类型检查。枚举变量可以自动转换成integral值，然而，将任何表达式赋值到枚举变量均要求一个显式的强制类型转换。例如：

Copy Code
typedef enum {red, green, blue, yellow, white, black} Colors;

上面的例子将一个唯一的数值赋值到每一个颜色标识符，并产生一个新的数据类型Colors。接着我们可以产生这种类型的变量。

Copy Code
Colors c;
c = green;
c = 1;      // 无效赋值
if (1==c)   // 有效。c被自动转换成integer

在上面的例子中，值green被赋值到类型为Colors的变量c。第二个赋值是无效的，因为枚举类型必须遵守严格的类型规则。强制类型转换可以将一个不同的数据类型、或超出范围的值赋值到一个枚举类型。强制类型转换将在3.10.4节、3.14节和3.15节中讨论。如果一个枚举变量被赋值为一个超出范围的值，那么之后有关这个枚举变量的任何操作结果都是未定义的。

Group

3.10 枚举

链接
3.10 枚举


3.10.4 数值表达式中的枚举类型

链接
3.10 枚举, 主题
SystemVerilog 3.1a语言参考手册
3.10.4 数值表达式中的枚举类型
3.10 枚举 | 主题

枚举变量的元素可以使用在数值表达式中。表达式中使用的值是与枚举值相关的数值。例如：

Copy Code
typedef enum {red, green, blue, yellow, white, black} Colors;
Colors col;
integer a, b;
a = blue * 3;
col = yellow;
b = col + green;

在前面的声明中，blue的值为2。上面的例子将a赋值为6（2*3），将b赋值为4（3+1）。

在表达式中使用的枚举变量或标识符自动地转换成枚举声明的基类型（或者显式地，或者使用int作为缺省类型）。从一个表达式而不是相同的枚举类型对枚举变量赋值要求强制的类型转换。当强制转换到枚举类型的时候，表达式会转换到它的基本类型而不会检查值的有效性（除非使用动态强制类型转换，见3.15节的描述）。

Copy Code
typedef enum {Red, Green, Blue} Colors;
typedef enum {Mo, Tu, We, Th, Fr, Sa, Su} Week;
Colors C;
Week W;
int I;

C = Colors'(C+1); // C被强制转换成一个整数，然后加1，接着转换回Colors类型

C = C + 1; C++; C+=2; C=I; // 非法。因为它们都是没有强制类型转换的表达式复制。

I = C + W; // 有效。C和W被自动地强制转换成int类型。

SystemVerilog包含了一组特定的方法对枚举类型的值进行操作。

Group

3.10 枚举

主题
主题 | 描述
3.10.4.1 first() | first()方法的原型为：
3.10.4.2 last() | last()方法的原型为：
3.10.4.3 next() | next()方法的原型为：
3.10.4.4 prev() | prev()方法的原型为：
3.10.4.5 num() | num()方法的原型为：
3.10.4.6 name() | name()方法的原型为：
3.10.4.7 使用枚举类型的方法 | 下面的代码片断展示了如何显示一个枚举变量所有成员的名字和值。
链接
3.10 枚举, 主题


3.10.4.1 first()

链接
3.10.4 数值表达式中的枚举类型
SystemVerilog 3.1a语言参考手册
3.10.4.1 first()
3.10.4 数值表达式中的枚举类型

first()方法的原型为：

Copy Code
function enum first();

first()方法返回枚举变量第一个成员的值。

Group

3.10.4 数值表达式中的枚举类型

链接
3.10.4 数值表达式中的枚举类型


3.10.4.2 last()

链接
3.10.4 数值表达式中的枚举类型
SystemVerilog 3.1a语言参考手册
3.10.4.2 last()
3.10.4 数值表达式中的枚举类型

last()方法的原型为：

Copy Code
function enum last();

last()方法返回枚举变量最后一个成员的值。

Group

3.10.4 数值表达式中的枚举类型

链接
3.10.4 数值表达式中的枚举类型


3.10.4.3 next()

链接
3.10.4 数值表达式中的枚举类型
SystemVerilog 3.1a语言参考手册
3.10.4.3 next()
3.10.4 数值表达式中的枚举类型

next()方法的原型为：

Copy Code
function enum next(int unsigned N = 1);

next()方法返回指定变量当前值之后的第N个枚举值（缺省为下一个值）。当到达枚举的尾部时会返回到枚举的起始处。如果指定的值不是枚举的成员，next()方法返回第一个成员。

Group

3.10.4 数值表达式中的枚举类型

链接
3.10.4 数值表达式中的枚举类型


3.10.4.4 prev()

链接
3.10.4 数值表达式中的枚举类型
SystemVerilog 3.1a语言参考手册
3.10.4.4 prev()
3.10.4 数值表达式中的枚举类型

prev()方法的原型为：

Copy Code
function enum prev(int unsigned N = 1);

prev()方法返回指定变量当前值之前的第N个枚举值（缺省为前一个值）。当到达枚举的起始处时会返回到枚举的尾部。如果指定的值不是枚举的成员，prev()方法返回最后一个成员。

Group

3.10.4 数值表达式中的枚举类型

链接
3.10.4 数值表达式中的枚举类型


3.10.4.5 num()

链接
3.10.4 数值表达式中的枚举类型
SystemVerilog 3.1a语言参考手册
3.10.4.5 num()
3.10.4 数值表达式中的枚举类型

num()方法的原型为：

Copy Code
function enum num();

num()方法返回指定枚举中成员的数目。

Group

3.10.4 数值表达式中的枚举类型

链接
3.10.4 数值表达式中的枚举类型


3.10.4.6 name()

链接
3.10.4 数值表达式中的枚举类型
SystemVerilog 3.1a语言参考手册
3.10.4.6 name()
3.10.4 数值表达式中的枚举类型

name()方法的原型为：

Copy Code
function enum name();

name()方法返回指定枚举值的字符串表示。如果指定的值不是一个枚举的成员，name()返回空字符串。

Group

3.10.4 数值表达式中的枚举类型

链接
3.10.4 数值表达式中的枚举类型


3.10.4.7 使用枚举类型的方法

链接
3.10.4 数值表达式中的枚举类型
SystemVerilog 3.1a语言参考手册
3.10.4.7 使用枚举类型的方法
3.10.4 数值表达式中的枚举类型

下面的代码片断展示了如何显示一个枚举变量所有成员的名字和值。

Copy Code
typedef enum {red, green, blue, yellow} Colors;
Colors c = c.first;
forever begin
    $display(“%s : %d”, c.name, c);
    if (c == c.last()) break;
        c = c.next;
end
Group

3.10.4 数值表达式中的枚举类型

链接
3.10.4 数值表达式中的枚举类型


3.11 结构体与联合体

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.11 结构体与联合体
第三章 数据类型
Copy Code
data_type ::=       // 引用自附录A.2.2.1
    ...
  | struct_union [packed [signing]] {struct_union_member {struct_union_member}}
        {packed_dimension}

struct_union_member ::=
    {attribute_instance} data_type_or_void list_of_variable_identifiers;

data_type_or_void ::= data_type | void

struct_union ::= struct | union [tagged]

语法3-4 结构体与联合体（摘录自附录A）

结构体和联合体的声明遵从C语言的语法，但在“{”之前没有可选的结构体标签。

Copy Code
struct {
    bit[7:0] opcode;
    bit[23:0] addr;
} IR //匿名结构体，定义变量IR。

IR.opcode = 1; // 设置IR的域

其它一些声明结构体和联合体的例子如下：

Copy Code
typedef struct {
    bit[7:0] opcode;
    bit[23:0] addr;
} instruction;    // 命名的结构体类型

instruction IR;   // 定义变量

typedef union {
    int i;
    shortreal f;
} num;            // 命名的联合体类型

num n;

n.f = 0.0;        // 以浮点数格式设置n

typedef struct {
    bit isfloat;
    union {
        int i;
        shortreal f;
    } n;          // 匿名类型
} tagged_st;      // 命名结构体

tagged_st a[9:0]; // 结构体数组

一个结构体可以作为一个整体赋值，并且可以作为一个整体向/从一个函数或任务传递。

第2.8节讨论了如何为结构体赋初始值。

一个压缩结构体包含了位域，它们在存储器中被无缝地压缩在一起。这也就意味着，它们可以方便地转换到位向量，或从位向量转换。一个非压缩结构体具有独立于实现的压缩形式，通常与C编译器相匹配。

与压缩数组类似，在使用算术和逻辑操作符时，一个压缩结构体可以当作一个整体使用。第一个指定的成员成为最高有效位，后续的成员以降序排列。结构体在声明的时候可以使用packed关键字，根据期望的算术行为，packed关键字之后可以跟着signed或unsigned关键字。缺省情况下，结构体是无符号的。

Copy Code
struct packed signed {
    int a;
    shortint b;
    byte c;
    bit [7:0] d;
} pack1; // 有符号的两态值

struct packed unsigned {
    time a;
    integer b;
    logic [31:0] c;
} pack2; // 无符号的四态值

只要压缩结构体内的数据类型存在4态数据类型，那么整个结构体就被当作是4态数据类型，并且其中的任何2态成员都会使用强制类型转换进行转换。压缩结构体的一个或更多的位可以使用[n-1:0]的编号方法来选择，就好像它是一个压缩数组一样。

Copy Code
pack1[15:8] // c

非整数数据类型（例如real和shortreal）以及非压缩数组不允许在压缩结构体或压缩联合体中使用。

一个压缩结构体可以与typedef一起使用。

Copy Code
typedef struct packed { // 缺省是无符号的
    bit [3:0] GFC;
    bit [7:0] VPI;
    bit [11:0] VCI;
    bit CLP;
    bit [3:0] PT;
    bit [7:0] HEC;
    bit [47:0][7:0] Payload;
    bit [2:0] filler;
} s_atmcell;

一个压缩联合体所包含的成员只能是压缩结构体、压缩数组或者是整数数据类型，并且所有的成员必须具有相同的尺寸（而对于一个非压缩联合体，其成员可以具有不同的尺寸）。这就可以保证你可以读回作为另外一个成员写入的联合体成员。在使用算术和逻辑操作符时，一个压缩联合体可以当作一个整体使用，并且它的行为由signed或unsigned关键字确定。如果没有显式指明signed或unsigned关键字，那么它缺省是unsigned的。如果一个压缩联合体包含了2态成员和4态成员，那么整个联合体是4态的。此时，如果读取2态成员，那么它具有一个隐式的4态到2态的转换；如果写入2态成员，则具有一个隐式的2态到4态的转换。

例如，一个联合体可以使用不同的访问宽度进行访问：

Copy Code
typedef union packed { // 缺省是无符号的
    s_atmcell acell;
    bit [423:0] bit_slice;
    bit [52:0][7:0] byte_slice;
} u_atmcell;

u_atmcell u1;

byte b;
bit [3:0] nib;
b = u1.bit_slice[415:408];    // 与b = u1.byte_slice[51];相同
nib = u1.bit_slice[423:420];  // 与nib = u1.acell.GFC;相同

注意：对一个成员的写入与对另外一个成员的读出独立于计算机的字节顺序，这与一个普通的联合体或普通的结构体不同，这些普通的联合体或普通的结构体与C语言兼容并且以降地址的顺序排列成员。

在非压缩结构体中不允许使用符号，因此下面的声明被认为是非法的。

Copy Code
typedef struct signed {
    int f1;
    logic f2;
} sIllegalSignedUnpackedStructType; // 非法声明

联合体中声明中具有限定词tagged的联合体声明为标签联合体，它是一个类型检查的联合体。一个普通的（不带有标签的）联合体可以使用一个成员类型的值进行更新，而以另外一个成员类型进行读取，这有可能成为类型漏洞。一个标签联合体既储存了成员值也储存了一个标签，也就是说，使用额外的位来表示当前的成员名字。标签和值仅仅能够通过一个静态的类型检查标签联合体表达式来（参见7.15节）一起更新。成员值仅仅可以通过与当前标签值一致的类型来读取（也就是成员名）。这样，我们就不可能以一种类型来存储值，而以另外一种类型来错误地解释成员的各位。

除了类型的安全性之外，相对于使用显式标签来跟踪联合体的代码而言，将成员名以标签的方式使用也可以使代码更加简单并且更小。标签联合体还可以用在模式匹配（参见8.4节）当中，这会更进一步改进代码的可读性。

在标签联合体中，当所有信息都存在于标签本身的时候，成员还可以使用void类型来声明。就像在下面的例子中包含一个整数和一个有效位一样：

Copy Code
typedef union tagged {
    void Invalid;
    int Valid;
} VInt;

在上面的例子中，一个VInt类型的值或者是无效的并没有包含任何东西，或者是有效的并包含一个int类型的值。7.15节描述了如何构建这种类型的值，并且描述了怎样才能够确保不会从一个当前具有Invalid标签的VInt值中读出一个整数值。

例子：

Copy Code
typedef union tagged {
    struct {
        bit [4:0] reg1, reg2, regd;
    } Add;

    union tagged {
        bit [9:0] JmpU;
        struct {
            bit [1:0] cc;
            bit [9:0] addr;
        } JmpC;
    } Jmp;
} Instr;

一个Instr类型的值或者是一个Add指令或者是一个Jmp指令。如果是Add指令，它包含了三个5位寄存器域；如果是Jmp指令，它或者是一个无条件跳转或者是一个有条件跳转。如果是无条件跳转，它包含了一个10位的目的地址。如果是有条件跳转，它包含了一个2位的条件码寄存器域和一个10位的目的地址。7.15节描述了如何构建Instr类型的值 ，并且描述了如何才能使指令必须具有Jmp操作码和JmpC子操作码（例如为了读取cc域）。

当packed限定词使用在标签联合体的时候，所有的成员必须是压缩数据类型，但它们不必具有相同的尺寸。一个压缩标签联合体的标准表示方法如下：

  • 尺寸总是等于所需的位的数目以便表示标签加上最大的成员尺寸；
  • 标签的尺寸是编码所有成员名字所需的最小的位数目（例如5到8个成员需要3个标签位）；
  • 标签位总是向左调整（也就是向最高有效位的方向调整）；
  • 对于每一个成员，成员位总是向右调整（也就是向最低有效位的方向调整）；
  • 在标签位与成员位之间的位是未定义的。在具有void成员的极端情况下，只有标签位是有意义的，所有其它的位都是未定义的。

这种表示机制递归地适用于任何嵌套的标签联合体。

例子：如果VInt类型定义具有packed限定词，那么InValid和Valid值分别具有如下的布局。

标签为0表示无效，标签为1表示有效。

例子：如果Instr类型具有packed限定词，那么它的值具有如下的布局：

对外层标签来讲，0表示Add，1表示Jmp；

对内层标签来讲，0表示JmpU，1表示JmpC。

Group

第三章 数据类型

链接
第三章 数据类型


3.12 类

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.12 类
第三章 数据类型

类是数据以及一组对数据进行操作的子程序的集合。类中的数据被称为类属性，它的子程序被称为方法。类属性和方法一起定义了一个类实例或对象的内容和能力。

Copy Code
class_declaration ::=   // 引用自附录A.1.3
    [virtual] class [lifetime] class_identifier [parameter_port_list]
        [extends class_type [(list_of_arguments)]];
        {class_item}
    endclass [: class_identifier]

语法 3-5 — 类（摘录自附录A）

面向对象的类扩展允许动态地产生和销毁对象。类实例或者说对象能够通过对象句柄进行传递，这就为语言加入了一个安全指针的能力。一个对象可以声明成具有input、output、inout或ref方向的自变量。在每一种情况中，拷贝的自变量是对象句柄而不是对象的内容。

一个类使用class...endclass关键字进行声明。例如：

Copy Code
class Packet;
    int address;     // address、data和crc属性
    bit [63:0] data;
    shortint crc;
    Packet next;     // 另一个Packet的句柄
    function new();  // send和new方法
    function bit send();
endclass : Packet

任何数据类型都可以声明成一个类成员。类将会在第十一章进行更详细的讨论。

Group

第三章 数据类型

链接
第三章 数据类型


3.13 单一类型与集合类型

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.13 单一类型与集合类型
第三章 数据类型

数据类型可以分为两类：单一类型与集合类型。一个单一类型应该是除非压缩结构体、非压缩联合体、或非压缩数组（参见第四章有关数组的内容）之外的任何数据类型。一个集合类型应该是任何非压缩结构体、非压缩联合体、或非压缩数组数据类型。一个单一变量或表达式代表一个单一的值、符号、或句柄。集合表达式和变量代表一组单一值。integral类型总是单一的，即使它们可以被分片成多个单一值。

通过定义这些类别，操作符和函数能够简单地将这些数据类型当作一个集合组来引用。例如：某些函数能够递归地解析一个集合类型直到获得一个单一值，然后就可以对每一个单一值进行操作。

注意：虽然类是一种数据类型，但没有直接的类变量或表达式，而仅仅存在类对象的句柄，并且类对象的句柄为单一值。因此，类不需要按这种方式分类（参见第十一章有关类的内容）。

Group

第三章 数据类型

链接
第三章 数据类型


3.14 强制类型转换

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.14 强制类型转换
第三章 数据类型
Copy Code
constant_cast ::=   // 引用自附录A.8.4
    casting_type'(constant_expression)
  | casting_type'constant_concatenation
  | casting_type'constant_multiple_concatentation

cast ::=
    casting_type'(expression)
   | casting_type'concatenation
   | casting_type'multiple_concatentation

casting_type ::= simple_type | size | signing  // 引用自附录A.2.2.1

simple_type ::= integer_type | non_integer_type | ps_type_identifier

语法 3-6 — 强制类型转换（摘录自附录A）

我们可以使用强制类型转换操作符（'）来改变一个表达式的数据类型。需要进行强制类型转换的表达式必须包含在圆括号内，或者必须包含在串联或复制花括号内，并且它们必须是自决的。

Copy Code
int'(2.0*3.0)
shortint'{8'hFA,8'hCE}

如果将一个正的十进制数作为数据类型，那么这意味着需要改变数据的位数。

Copy Code
17'(x - 2)

数据的符号也可以改变。

Copy Code
signed'(x)

也可以使用用户定义的数据类型。

Copy Code
mytype'(foo)

如果强制类型转换中的表达式需要改变尺寸或符号，那么这个表达式必须具有integral值。当改变尺寸的时候，符号不会发生变化。当改变符号的时候，尺寸不会发生变化。

当强制转换到一个预定义的数据类型的时候，强制类型转换操作符的前缀必须是预定义的类型关键字。当强制转换到一个用户定义的数据类型的时候，强制类型转换操作符的前缀必须是用户定义类型标识符。

如果一个shortreal类型转换到一个int或32位数据类型，它的值会进行四舍五入，就象Verilog的规定一样。因此，转换会丢失信息。如果将shortreal转换到它的底层位表示而不会丢失信息，那么可以使用23.6节中定义的$shortrealtobits。如果从一个shortreal值的位表示转换回shortreal，可以使用23.6节中定义的$bitstoshortreal。

结构体可以转换成保留位模式的位，这意味着它可以转换回相同的值而不会丢失信息。当非压缩数据转换到它们的压缩表示形式的时候，压缩表示形式中的数据顺序是结构体的第一个域占据最高有效位。这与数据元素（结构体域或数组元素）的串联具有相同的效果。为了将一个非压缩结构体或数组的压缩表示强制转换成任何其它类型（无论是压缩的还是非压缩的），非压缩结构体或数组中的元素类型必须是有效的。

压缩类型间的类型转换并不要求显式转换，因为它们都被当作是integral值，但工具可以使用强制类型转换来执行更强的类型检查。

下面的例子展示了如何使用$bits属性来获得结构体的位尺寸（$bits系统函数将在23.4节中讨论），它使结构体转换到一个压缩数组更加方便。

Copy Code
typedef struct {
    bit isfloat;
    union {
        int i;
        shortreal f;
    } n;     // 匿名类型
} tagged_st; // 命名的结构体

typedef bit [$bits(tagged_st)-1 : 0] tagbits; // tagged_st在上面定义

tagged_st a[7:0];           // 非压缩结构体数组

tagbits t = tagbits'(a[3]); // 将结构体转换成位数组

a[4] = tagged_st'(t);       // 将位数组转换回结构体

注意：bit数据类型会丢失X值。为了保留X值，需要使用logic类型。

联合体的位尺寸是其最大成员的尺寸。logic类型的位尺寸是1。

为了保持兼容性，也可以使用Verilog函数：$itor， $rtoi， $bitstoreal， $realtobits， $signed， $unsigned。

Group

第三章 数据类型

链接
第三章 数据类型


3.15 $cast动态强制类型转换

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.15 $cast动态强制类型转换
第三章 数据类型

在由于不同的数据类型而导致变量不能正常赋值的情况下，SystemVerilog提供了$cast系统任务来进行赋值操作。$cast可以作为任务或函数来调用。

$case的语法如下：

Copy Code
function int $cast(singular dest_var, singular source_exp);

或者

Copy Code
task $cast(singular dest_var, singular source_exp);

dest_var是需要赋值得变量。

sorce_exp是将要赋值到目的变量的表达式。

将$cast作为任务还是函数调用确定了无效赋值是如何处理的。

当作为任务调用时，$cast试图将源表达式赋值给目的变量。如果赋值是无效的，会出现运行时错误并且目的变量保持不变。

当作为函数调用时，$cast试图将源表达式赋值给目的变量，如果赋值成功则返回1。如果赋值失败，$cast不会进行赋值操作而是返回0。当作为函数调用时，不会出现运行时错误，并且目的变量保持不变。

必须注意：$cast执行的是运行时检查。除了检查目的变量和源表达式是否为单一类型外，编译器不会进行类型检查。

例如：

Copy Code
typedef enum {red, green, blue, yellow, white, black} Colors;
Colors col;
$cast(col, 2+3);

这个例子将表达式（5，black）赋值给枚举类型。如果不使用$cast或者下面描述的静态编译时强制类型转换，这种类型的赋值是无效的（参见3.10.3 类型检查 ）。

下面的例子显示了如何使用$cast检查一个赋值操作是否成功：

Copy Code
if (!$cast(col, 2+8))  // 10: 无效的强制类型转换
    $display("Error in cast");

作为一种选择，前一个例子还可以使用静态SystemVerilog强制类型转换操作符来进行类型转换，例如：

Copy Code
col = Colors'(2+3);

然而，这是一种编译时的强制类型转换，也就是说，它在运行时总是成功的，并且即使表达式不在枚举值的范围之内，它也不会提供错误检查或警告。

这两种类型的强制类型转换为用户提供了完全的控制能力。如果用户知道将某个表达式赋值给一个枚举变量是安全的，那么可以使用较快的静态编译时强制类型转换。如果用户需要检查表达式是否位于枚举值范围内，那么用户没有必要手工编写一个冗长的开关语句，通过使用$cast函数，编译器自动提供了这种功能。通过这两种类型的强制类型转换，用户能够控制时间和安全性之间的平衡。

注意：$cast类似于C++中的dynamic_cast函数，然而，$cast允许用户检查操作是否成功，而dynamic_cast总是会引起一个C++异常。

Group

第三章 数据类型

链接
第三章 数据类型


3.16 位流强制类型转换

链接
第三章 数据类型
SystemVerilog 3.1a语言参考手册
3.16 位流强制类型转换
第三章 数据类型

强制类型转换还可以应用于非压缩数组以及非压缩结构体。这样就使得通过显式强制类型转换在位流类型之间自由地转换成为可能。可以压缩成一个位流的类型称为位流类型。位流类型包含下列的类型：

  • 任何integral、压缩、或字符串类型
  • 非压缩数组、结构体、或上述类型的类
  • 任何上述类型的动态尺寸数组（动态的、联合的、或队列）

这个定义是递归的，例如，一个包含int队列的结构体是一个位流类型。

假定A具有source_t的位流类型，B具有dest_t的位流类型，那么我们可以使用显式强制类型转换将A转换到B：

Copy Code
B = dest_t'(A);

从source_t类型的A转换到dest_t类型的B以下面两个步骤执行：

  1. 从source_t转换到一个通用的压缩值，这个压缩值与source_t具有相同的位数目。如果source_t包含任何四态数据，那么整个压缩值是四态的，否则它就是两态的。
  2. 从通用的压缩值转换到dest_t。如果通用的压缩值是四态类型并且dest_t的部分值是两态的，那么对这些两态类型的赋值被强制转换成两态的。

当一个动态数组、队列、或字符串被转换成压缩表示方式的时候，在索引0处的元素占据最高有效位。当一个联合数组被转换成压缩表示方式的时候，那么按索引顺序排列的第一个索引元素占据最高有效位。

无论是source_t还是dest_t都可以在任何位置包含一个或多个动态尺寸的数据（例如，一个包含紧跟着一个字节对列的动态数组的结构体）。如果源类型source_t包含了动态尺寸的变量，那么它们全部包含在位流当中。如果目的类型dest_t包含了许多动态尺寸类型，那么整个转换过程是很庞大的：计算source_t的尺寸，减去目的类型中具有固定尺寸的数据的尺寸，接着将目的类型中第一个动态尺寸元素的尺寸调整到剩余的尺寸；任何剩余的动态尺寸元素均被留空。

为了实现位流强制类型转换，一个字符串被认为是动态的字节数组。

无论目的类型是否只包含固定尺寸的元素还是包含了动态尺寸的元素，数据都会以从左到右的顺序提取到目的类型。因此，从一个压缩表示方式的中间部分提取数据来填充一个动态尺寸的元素是合法的。

如果source_t和dest_t都是固定尺寸的非压缩类型，但它们具有不同的尺寸，那么强制类型转换会产生一个编译时错误。如果source_t和dest_t包含了动态尺寸类型，那么只要能够确定它们在尺寸上的不匹配，它们在尺寸上的不一致就会产生一个编译时错误或运行时错误。例如：

Copy Code
// 从24位结构体转换成int（32位）是不合法的，- 编译时错误
struct {
    bit[7:0] a;
    shortint b;
} a;
int b = int'(a);

// 从20位结构体转换到int（32位）是不合法的 - 运行时错误
struct {
    bit a[$];
    shortint b;
} a = {{1,2,3,4}, 67};
int b = int'(a);

// 从int（32位）转换到dest_t结构体（25位或33位）是不合法的
// 编译时错误
typedef struct {
    byte a[$];
    bit b;
} dest_t;

int a;
dest_t b = dest_t'(a);

位流强制类型转换可以用来在不同的集合类型间转换，例如两个结构体类型，或者一个结构体与一个数组或队列类型之间。对于在串行通信流上传输包数据的建模，这种转换非常有用：

Copy Code
typedef struct {
    shortint address;
    reg [3:0] code;
    byte command [2];
} Control;

typedef bit Bits [36:1];

Control p;

Bits stream[$];

p = ... // 初始化Control包

stream = {stream, Bits'(p)} // 将包附加到非压缩位队列

Control q;

q = Control'(stream[0]);   // 将位流转换回一个Contorl包

stream = stream[1:$];      // 从流中删除包

下面的例子使用位流强制类型转换来建模在字节流上传输数据包：

Copy Code
typedef struct {
    byte length;
    shortint address;
    byte payload[];
    byte chksum;
} Packet;

上面的类型定义了一个普通的数据包，它的净荷的尺寸存储在length域。下面的函数随机地初始化包并产生校验和。

Copy Code
function Packet genPkt();
    Packet p;
    void'(randomize(p.address, p.length, p.payload)
    with {p.length>1 && p.payload.size == p.length});
        p.chksum = p.payload.xor();
    return p;
endfunction

字节流使用一个队列建模，一个位流强制类型转换被用来在流上发送包。

Copy Code
typedef byte channel_type[$];
channel_type channel;
channel = {channel, channel_type'(genPkt())};

下面的代码用来接收包。

Copy Code
Packet p;
int size;
size = channel[0] + 4;
p = Packet'(channel[0:size-1]); // 将流转换成包
channel = channel[size, $];     // 从流中删除包
Group

第三章 数据类型

链接
第三章 数据类型


第四章 数组

链接
主题
SystemVerilog 3.1a语言参考手册
第四章 数组
主题
主题
主题 | 描述
4.1 简介（一般信息） | 数组是变量的集合，这些变量具有相同的数据类型，并可以使用相同的名字加上一个或多个索引来访问。 在C语言中，数组从0开始并以整数的形式进行索引，或者将其转换成指针。尽管整个数组可以作为一个整体被初始化，但在过程语句中，它的每一个元素必须被分离地读或写。 在Verilog-2001中，数组使用从左边界到右边界的顺序进行索引。如果它们是向量，它们还可以作为一个整体赋值，而如果他们是数组则不允许这样做。在Verilog-2001中允许多维数组。 在Verilog-2001中，所有的数据类型都可以声明成数组。reg、wire以及所有其它线网类型还可以具有向量宽度。在对象名字之前声明的尺寸被称作是“向量宽度”尺寸。在对象名字之后声明的尺寸被称为“数组”尺寸。
4.2 压缩与非压缩数组 | 压缩数组提供了一种将向量细分成子域的机制，这些子域可以作为数组元素方便地访问。这就可以保证压缩数组能够被表示成一个连续的位组（FPGA技术网提示：是指可以在内存中连续分配存储空间）。一个非压缩数组既可以这样表示也可以不这样表示（FPGA技术网提示：是指仿真器可以选择如何安排存储空间）。压缩数组与非压缩数组的不同之处在于：当一个压缩数组作为一个整体出现的时候，它被当作是单一的向量。 如果一个压缩数组被声明成有符号的，那么作为单一向量看待的数组也是有符号的。数组的单个元素是无符号的，除非它们的类型是被声明成有符号的命名类型。一个压缩数组的部分选择也是无符号的。 压缩数组可以是任意长度的整数类型（关于整数类型参见3.3节），因此，尺寸为48的压缩数组可以由48位组成，然后这个压缩数组就可以使用在48位算术表达式中。一个压缩数组可以实现的最大尺寸可以是有限制的，但最少应该可以实现65536（216）的长度。 压缩数组可以仅由单位整数数据类型（bit、logic、reg、wire以及其他线网类型）组成，也可以由其它能够递归成单位整数类型的压缩数组和压缩结构体组成。 具有预定义宽度的整数类型不能声明成压缩数组。这些类型是：byte、shorting、int、longint、以及integer。一个具有预定义宽度的整数类型可以被看作是一个一维的压缩数组。这些整数类型的压缩尺寸应该以趋向0的方向编号，并且最右边的索引是0。
4.3 多维数组 | 于Verilog的存储器类型类似，在类型之后声明的尺寸设置压缩尺寸，在实例之后的尺寸设置非压缩尺寸。
4.4 数组的索引与分片 | 一个表达式可以选取压缩数组的一部分，或者选取任何整数类型，并假定具有趋向0的编号方式。 SystemVerilog使用术语“部分选择（part selet）”来表示从一个单维压缩数组中选取一个或多个连续的位。这与Verilog中对术语“部分选择”的使用是一致的。
4.5 数组查询函数 | SystemVerilog提供了新的系统函数来返回有关数组的信息。包括：$left、$right,、$low,、$high,、$increment、$size、以及$dimensions。这些函数将在23.7节中描述。
4.6 动态数组 | 动态数组是一维的非压缩数组，它的尺寸可以在运行时设置或改变。动态数组的存储空间只有当数组在运行时被显式产生之后才会存在。 动态数组的声明语法如下：
4.7 数组赋值 | 对固定尺寸的非压缩数组赋值要求源数组和目的数组都具有相同非压缩维数，并且每一维的长度都必须相同。赋值通过将源数组的每一个元素赋值给目的数组的对应元素来实现，它要求源数组与目的数组具有兼容的类型。兼容类型是指在赋值操作上能够兼容的类型。在尺寸不等的固定尺寸非压缩数组间赋值会导致类型检查错误。
4.8 将数组作为自变量 | 数组可以作为自变量传递给任务或函数。数组自变量通过值进行传递的规则与数组赋值的规则相同（参见10.4节）。当数组自变量通过值传递的时候，一个数组的拷贝被传递给调用任务或函数。这条规则适用于所有的数组类型：固定尺寸数组、动态数组、或联合数组。 注意：未定义尺寸的维数只能出现在动态数组中，或者出现在导入DPI函数的形式变量中。如果一个形式变量的一维是未定义尺寸的，那么真实变量中对应维数具有任意尺寸也是可以接受的。 例如：
4.9 联合数组 | 对于处理成员数目会动态改变的连续变量集合而言，动态数组非常有用。然而，当集合的尺寸是未知的或者数据空间紧缺的时候，联合数组则是更好的选择。联合数组在使用之前不会分配任何存储空间，并且索引表达式不再被限制成integral表达式，而是可以具有任何数据类型。 联合数组实现了一个所声明类型的元素的查找表。用作索引的数据类型作为查找表的查找键值，并强制了一种顺序。 联合数组的声明语法如下：
4.10 联合数组方法 | 除了索引操作符之外，SystemVerilog提供了几个内建方法来允许用户分析和处理联合数组，同时提供了对联合数组的索引或键值的迭代处理。
4.11 联合数组赋值 | 联合数组只能被赋值为另外一个具有兼容类型并且具有相同索引类型的联合数组。其它的数组类型不能赋值给一个联合数组，而联合数组也不能赋值给其它类型的数组，无论是固定尺寸数组还是动态动态数组。 将联合数组赋值给另外一个联合数组会先将目的数组中所有现存条目清除，然后再将源数组中的每一个条目拷贝到目的数组。
4.12 联合数组自变量 | 作为自变量的联合数组只能传递给具有兼容类型并具有相同索引类型的联合数组。其它类型的数组，无论是固定尺寸数组还是动态数组，都不能传递给使用联合数组作为自变量的子程序。同样，联合数组也不能传递给使用其它类型的数组作为自变量的子程序。 通过值传递一个联合数组会产生联合数组的本地拷贝。
4.13 联合数组文本 | 联合数组文本值使用{index:value}这样的语法并带有可选的缺省索引。与所有其它数组一样，联合数组可以一次只写一个条目，或者使用数组文本替代整个数组内容。
4.14 队列 | 队列是一个相同元素的可变尺寸的有序集合。队列能够以常量时间访问它的所有元素，也能够以常量时间在队列的尾部和头部插入和删除元素。队列中的每一个元素都通过一个序号来标识，这个序号代表了元素在队列内的位置，0代表第一个元素，$代表最后一个元素。队列类似于一个一维的非压缩数组，它可以自动地增长和缩减。因此，与数组一样，队列可以使用索引、串联、分片、相等操作符进行处理。 队列使用与非压缩数组相同的语法声明，但可以使用$作为数组尺寸。队列的尺寸可以通过指定可选的右边界（最后一个索引）进行限制。
4.15 数组处理方法 | SystemVerilog提供了几个内建的方法来方便数组的搜索、排序和缩减。 调用这些数组方法的基本语法如下：
链接
主题


4.1 简介（一般信息）

链接
第四章 数组
SystemVerilog 3.1a语言参考手册
4.1 简介（一般信息）
第四章 数组

数组是变量的集合，这些变量具有相同的数据类型，并可以使用相同的名字加上一个或多个索引来访问。

在C语言中，数组从0开始并以整数的形式进行索引，或者将其转换成指针。尽管整个数组可以作为一个整体被初始化，但在过程语句中，它的每一个元素必须被分离地读或写。

在Verilog-2001中，数组使用从左边界到右边界的顺序进行索引。如果它们是向量，它们还可以作为一个整体赋值，而如果他们是数组则不允许这样做。在Verilog-2001中允许多维数组。

在Verilog-2001中，所有的数据类型都可以声明成数组。reg、wire以及所有其它线网类型还可以具有向量宽度。在对象名字之前声明的尺寸被称作是“向量宽度”尺寸。在对象名字之后声明的尺寸被称为“数组”尺寸。

Copy Code
reg [7:0] r1 [1:256]; // [7:0]是向量宽度，[1:256]是数组尺寸

SystemVerilog使用术语“压缩数组”来指代在对象名字之前声明尺寸（在Verilog-2001中称为向量宽度）的数组。而在对象名字之后声明尺寸的数组则称为“非压缩数组”。

Copy Code
bit [7:0] c1;  // 压缩数组
real u [7:0];  // 非压缩数组

通过允许使用多个数组维数，SystemVerilog增强了压缩数组。SystemVerilog提供了过程化地改变一个非压缩数组某一维尺寸的能力。固定尺寸的非压缩数组可以是多维的，并为所有元素都分配固定的存储空间。非压缩数组的每一维都可以声明成固定尺寸的数组或非固定尺寸的数组。动态数组在运行时为元素分配存储空间并提供了选项来改变某一维的尺寸。联合数组在写入的时候独立地为元素分配存储空间。联合数组可以使用任意数据类型进行索引。队列类型的数组可以在运行时根据写入元素的数目自动增长或缩减。

Group

第四章 数组

链接
第四章 数组


4.2 压缩与非压缩数组

链接
第四章 数组
SystemVerilog 3.1a语言参考手册
4.2 压缩与非压缩数组
第四章 数组

压缩数组提供了一种将向量细分成子域的机制，这些子域可以作为数组元素方便地访问。这就可以保证压缩数组能够被表示成一个连续的位组（FPGA技术网提示：是指可以在内存中连续分配存储空间）。一个非压缩数组既可以这样表示也可以不这样表示（FPGA技术网提示：是指仿真器可以选择如何安排存储空间）。压缩数组与非压缩数组的不同之处在于：当一个压缩数组作为一个整体出现的时候，它被当作是单一的向量。

如果一个压缩数组被声明成有符号的，那么作为单一向量看待的数组也是有符号的。数组的单个元素是无符号的，除非它们的类型是被声明成有符号的命名类型。一个压缩数组的部分选择也是无符号的。

压缩数组可以是任意长度的整数类型（关于整数类型参见3.3节），因此，尺寸为48的压缩数组可以由48位组成，然后这个压缩数组就可以使用在48位算术表达式中。一个压缩数组可以实现的最大尺寸可以是有限制的，但最少应该可以实现65536（216）的长度。

压缩数组可以仅由单位整数数据类型（bit、logic、reg、wire以及其他线网类型）组成，也可以由其它能够递归成单位整数类型的压缩数组和压缩结构体组成。

具有预定义宽度的整数类型不能声明成压缩数组。这些类型是：byte、shorting、int、longint、以及integer。一个具有预定义宽度的整数类型可以被看作是一个一维的压缩数组。这些整数类型的压缩尺寸应该以趋向0的方向编号，并且最右边的索引是0。

Copy Code
byte c2;     // 与bit [7:0] c2相同;
integer i1;  // 与logic signed [31:0] i1相同;

非压缩数组可以由任何类型组成。SystemVerilog增强了固定尺寸非压缩数组的能力：除了所有变量类型外，非压缩数组还可以由对象句柄（参见11.4节）和事件（参见13.5节）组成。

除了可以使用一个范围值来指定非压缩数组的尺寸外，SystemVerilog还可以像C一样使用单个数值来指定非压缩数组的尺寸。也就是说，[size]与[0:size-1]相同。例如：

Copy Code
int Array[8][32]; // 与int Array[0:7][0:31];相同

下面的操作可以对所有的数组（压缩的或非压缩的）进行操作。例子假定A和B是具有相同形状和相同类型的数组。

  • 读和写数组，例如，A = B
  • 读和写数组的片断，例如，A[i:j] = B[i:j]
  • 读和写数组的可变片断，例如，A[x+:c] = B[y+:c]
  • 读和写数组的一个元素，例如，A[i] = B[i]
  • 数组或数组片断的相等操作，例如，A==B, A[i:j] != B[i:j]

下面的操作只能用于压缩数组而不能作用于非压缩数组。例子假定A是一个数组。

  • 从一个整数赋值，例如， A = 8'b11111111；
  • 作为一个整数在表达式中使用，例如，(A + 3)

如果一个非压缩数组被声明成有符号的，那么数组的单个元素也是有符号的，因为非压缩数组不能被看作单个向量。

当为一个非压缩数组赋值的时候，源数组和目的数组必须具有相同的非压缩尺寸，并且每一维的长度也必须是相同的。非压缩数组的赋值可以通过将源数组的每一个元素赋值到目的数组的对应元素来实现。注意：非压缩数组的元素可以是一个压缩数组。

为了进行赋值，一个压缩数组可以当作一个向量来使用。任何压缩数组都可以赋值为任意向量表达式。目的压缩数组的边界不会影响赋值。如果不使用显式的强制类型转换，一个压缩数组不能够直接赋值到一个非压缩数组。

Group

第四章 数组

链接
第四章 数组


4.3 多维数组

链接
第四章 数组
SystemVerilog 3.1a语言参考手册
4.3 多维数组
第四章 数组

于Verilog的存储器类型类似，在类型之后声明的尺寸设置压缩尺寸，在实例之后的尺寸设置非压缩尺寸。

Copy Code
bit [3:0][7:0] joe [1:10]; // 10个4字节的条目（压缩成32位）

上面声明的数组可以作如下的使用：

Copy Code
joe[9] = joe[8] + 1;       // 四字节加
joe[7][3:2] = joe[6][1:0]; // 两字节拷贝

注意：在类型之后、名字之前声明的维数（上面例子中的[3:0][7:0]）比在名字之后声明的维数（上面例子中的[1:10]）变化要快。在使用的时候，第一维（[3:0]）之后跟着第二维（[1:10]）。

与C语言一样，在一系列维数中，最右边的一维变化的最快。然而，压缩维数要比非压缩维数变化的快。

Copy Code
bit [1:10] foo1 [1:5];          // 1到10变化最快，兼容于Verilog-2001数组
bit foo2 [1:5][1:10];           // 1到10变化最快，兼容于C
bit [1:5][1:10] foo3;           // 1到10变化最快
bit [1:5][1:6] foo4 [1:7][1:8]; // 1到6变化最快，然后是1到5，再然后是1到8，
                                // 最后是1到7

多个压缩维数还可以使用typedef定义。

Copy Code
typedef bit [1:5] bsix;
bsix [1:10] foo5; // 等价于bit [1:10][1:5]，1到5变化最快

多个非压缩维数也可以使用typedef定义。

Copy Code
typedef bsix mem_type [0:3]; // 四个’bsix’元素的数组
mem_type bar [0:7];          // 八个’mem_type’元素的数组

当数组以较少数目的维数使用的时候，它们必须是变化最慢的那些维数。

Copy Code
bit [9:0] foo6;
foo6 = foo1[2]; // 一个10位的粒度

就像Verilog-2001一样，可以使用逗号来分割一个数组声明的列表。列表中的所有数组具有相同的数据类型和相同的压缩数组维数。

Copy Code
bit [7:0][31:0] foo7 [1:5][1:10], foo8 [0:255]; // 声明了两个数组

如果索引表达式超出了地址边界或者地址中的任一位是X或Z，那么这个索引是无效的。如果使用无效索引读取数组，那么会返回数组元素类型的缺省值。使用无效索引写入数组不会引起任何操作。如果使用无效索引进行数组的读写操作，EDA工具在实现的时候可以返回一个警告信息。

Group

第四章 数组

链接
第四章 数组


4.4 数组的索引与分片

链接
第四章 数组
SystemVerilog 3.1a语言参考手册
4.4 数组的索引与分片
第四章 数组

一个表达式可以选取压缩数组的一部分，或者选取任何整数类型，并假定具有趋向0的编号方式。

SystemVerilog使用术语“部分选择（part selet）”来表示从一个单维压缩数组中选取一个或多个连续的位。这与Verilog中对术语“部分选择”的使用是一致的。

Copy Code
reg [63:0] data;
reg [7:0] byte2;
byte2 = data[23:16]; // 从data中进行8位的部分选择

SystemVerilog使用术语“分片（slice）”来表示从一个数组中选取一个或更多的连续的元素。Verilog仅允许选择数组的单个元素，并且对这种选择没有专用的术语。

压缩数组或非压缩数组的单个元素可以使用被索引的名字来选择。

Copy Code
bit [3:0][7:0] j; // j是一个压缩数组
byte k;
k = j[2];         // 从j中选择单个8位元素

SystemVerilog可以使用一个分片名字来选择一个或多个连续的元素。一个压缩数组的分片名字就是一个压缩数组。一个非压缩数组的分片名字就是一个非压缩数组。

Copy Code
bit busA [7:0][31:0];  // 包含8个32位向量的非压缩数组
int busB [1:0];        // 两个整数的非压缩数组
busB = busA[7:6];      // 从busA中选择一个分片

部分选择或分片的尺寸必须是一个常量，但其位置可以发生变化，并使用与Verilog-2001相同的语法。

Copy Code
int i = bitvec[j +: k]; // k必须是一个常量
int a[x:y], b[y:z], e;
a = {b[c -: d], e};     // d必须是常量

一个数组的分片仅仅适用于一个维数，但其它的维数可以在表达式中具有单个索引值。

Group

第四章 数组

链接
第四章 数组


4.5 数组查询函数

链接
第四章 数组
SystemVerilog 3.1a语言参考手册
4.5 数组查询函数
第四章 数组

SystemVerilog提供了新的系统函数来返回有关数组的信息。包括：$left、$right,、$low,、$high,、$increment、$size、以及$dimensions。这些函数将在23.7节中描述。

Group

第四章 数组

链接
第四章 数组


4.6 动态数组

链接
第四章 数组, 主题
SystemVerilog 3.1a语言参考手册
4.6 动态数组
第四章 数组 | 主题

动态数组是一维的非压缩数组，它的尺寸可以在运行时设置或改变。动态数组的存储空间只有当数组在运行时被显式产生之后才会存在。

动态数组的声明语法如下：

Copy Code
data_type array_name [];

其中data_type是数组元素的数据类型。 动态数组与固定尺寸数组支持相同的数据类型。例如：

Copy Code
bit [3:0] nibble[]; // 4位向量的动态数组
integer mem[];      // integer类型的动态数组

new[]操作符用来设置或改变数组的尺寸。

size()内建方法返回数组的当前尺寸。

delete()内建方法清空数组的所有元素以便产生一个空数组（零尺寸）。

Group

第四章 数组

主题
主题 | 描述
4.6.1 new[] | 内建函数new为动态数组分配存储空间，并使用缺省值或可选参数提供的值对最新分配的数组元素进行初始化。 new函数的原型如下：
4.6.2 size() | size()方法的原型如下：
4.6.3 delete() | delete()方法的原型如下：
链接
第四章 数组, 主题


4.6.1 new[]

链接
4.6 动态数组
SystemVerilog 3.1a语言参考手册
4.6.1 new[]
4.6 动态数组

内建函数new为动态数组分配存储空间，并使用缺省值或可选参数提供的值对最新分配的数组元素进行初始化。

new函数的原型如下：

Copy Code
blocking_assignment ::=   // 来自附录A.6.2
    ...
  | hierarchical_dynamic_array_variable_identifier = dynamic_array_new
    ...

dynamic_array_new ::=    // 来自附录A.2.4
    new[expression] [(expression)]

语法4-1：动态数组new的声明（摘录自附录A）

[expression]:

数组中元素的数目。必须是一个非负的integral表达式。

(expression):

可选的。一个数组使用它来初始化新的数组。如果没有指定，那么最新分配的数组元素被初始化成它们的缺省值。数组标识符必须与左侧的数组具有相同的数据类型，但不必具有相同的尺寸。如果这个数组的尺寸小于新数组的尺寸，那么多余的元素会被初始化成它们的缺省值。如果这个数组的尺寸大于新数组的尺寸，那么多余的元素会被忽略。

这个参数在增加或缩减现存数组的时候很有用。在这种情况下，表达式的值与左侧的相同，这样数组元素的前一个值会被保留。例如：

Copy Code
integer addr[];  // 声明动态数组
addr = new[100]; // 产生具有100个元素的数组
...
// 加倍数组的尺寸，但保留以前的值。
addr = new[200](addr);

new操作符遵从SystemVerilog的优先规则。因为方括号[]与圆括号()具有相同的优先规则，所以new操作符按从左到右的顺序计算：首先是[expression]，然后是(expression)。

Group

4.6 动态数组

链接
4.6 动态数组


4.6.2 size()

链接
4.6 动态数组
SystemVerilog 3.1a语言参考手册
4.6.2 size()
4.6 动态数组

size()方法的原型如下：

Copy Code
function int size();

size()方法返回动态数组的当前尺寸，如果数组还没有产生，则返回0。

Copy Code
int j = addr.size;
addr = new[addr.size()*4] (addr); // 将addr数组的尺寸扩大为4倍

注意：size方法等价于$length(addr, 1)。

Group

4.6 动态数组

链接
4.6 动态数组


4.6.3 delete()

链接
4.6 动态数组
SystemVerilog 3.1a语言参考手册
4.6.3 delete()
4.6 动态数组

delete()方法的原型如下：

Copy Code
function void delete();

delete()方法清空数组，产生一个0尺寸的数组。

Copy Code
int ab [] = new[N];      // 产生一个尺寸为N的临时数组
// 使用ab
ab.delete;               // 删除数据内容
$display("%d", ab.size); // 打印0
Group

4.6 动态数组

链接
4.6 动态数组


4.7 数组赋值

链接
第四章 数组
SystemVerilog 3.1a语言参考手册
4.7 数组赋值
第四章 数组

对固定尺寸的非压缩数组赋值要求源数组和目的数组都具有相同非压缩维数，并且每一维的长度都必须相同。赋值通过将源数组的每一个元素赋值给目的数组的对应元素来实现，它要求源数组与目的数组具有兼容的类型。兼容类型是指在赋值操作上能够兼容的类型。在尺寸不等的固定尺寸非压缩数组间赋值会导致类型检查错误。

Copy Code
int A[10:1]; // 具有10个元素的固定尺寸数组
int B[0:9];  // 具有10个元素的固定尺寸数组
int C[24:1]; // 具有24个元素的固定尺寸数组
A = B;       // 正确。兼容类型并具有相同的尺寸
A = C;       // 类型检查错误：不同的尺寸

wire数组可以赋值为具有相同的非压缩维数并且每一维都具有相同长度的变量数组，反之亦然。

Copy Code
wire [31:0] W[9:0];
assign W = A;
initial #10 B = W;

如果一个动态数组与一个固定尺寸数组维数的长度相同，那么这个动态数组可以被赋值为一个具有兼容类型的一维固定尺寸数组。与固定尺寸数组的赋值不同，这个操作在运行时进行类型检查，这可能会导致一个错误。

Copy Code
int A[100:1];       // 具有100个元素的固定尺寸数组
int B[] = new[100]; // 具有100个元素的动态数组
int C[] = new[8];   // 具有8个元素的动态数组
A = B;              // 兼容类型并具有相同的尺寸
A = C;              // 类型检查错误：不同的尺寸

一个动态数组或一维固定尺寸数组可以被赋值到一个具有兼容类型的动态数组。在这种情况下，赋值会产生一个新的动态数组，这个新的动态数组的长度等于固定尺寸数组的长度。例如：

Copy Code
int A[100:1];     // 具有100个元素的固定尺寸数组
int B[];          // 空的动态数组
int C[] = new[8]; // 具有8个元素的动态数组
B = A;            // 正确，B具有100个元素
B = C;            // 正确，B具有8个元素

最后一条语句等价于：

Copy Code
B = new[C.size](C);

相似地，赋值的源可以是一个调用数组分片或串联的复杂表达式。例如：

Copy Code
string d[1:5] = {"a", "b", "c", "d", "e"};
string p[];
p = {d[1:3], "hello", d[4:5]};

上面的例子产生动态数组p，并具有“a”, “b”, “c”, “hello”, “d”, “e”的内容。

Group

第四章 数组

链接
第四章 数组


4.8 将数组作为自变量

链接
第四章 数组
SystemVerilog 3.1a语言参考手册
4.8 将数组作为自变量
第四章 数组

数组可以作为自变量传递给任务或函数。数组自变量通过值进行传递的规则与数组赋值的规则相同（参见10.4节）。当数组自变量通过值传递的时候，一个数组的拷贝被传递给调用任务或函数。这条规则适用于所有的数组类型：固定尺寸数组、动态数组、或联合数组。

注意：未定义尺寸的维数只能出现在动态数组中，或者出现在导入DPI函数的形式变量中。如果一个形式变量的一维是未定义尺寸的，那么真实变量中对应维数具有任意尺寸也是可以接受的。

例如：

Copy Code
task fun(int a[3:1][3:1]);

上面的例子声明了具有一个变量的任务fun，它的变量是一个两维的数组，并且每一维的尺寸都是3。对fun的调用必须传递一个两维的数组，并且每一维的尺寸都是3。例如，根据上面有关fun的描述，考虑以下事实：

Copy Code
int b[3:1][3:1];   // 正确：相同的类型、维数、和尺寸
int b[1:3][0:2];   // 正确：相同的类型、维数、和尺寸（不同的范围）
reg b[3:1][3:1];   // 正确：兼容类型的赋值
event b[3:1][3:1]; // 错误：不兼容的类型
int b[3:1];        // 错误：不兼容的维数
int b[3:1][4:1];   // 错误：不兼容的尺寸（3和4）

接收一个一维固定尺寸数组的子程序也可以传递一个具有兼容类型、相同尺寸的动态数组。

例如：

Copy Code
task bar(string arr[4:1]);

上面声明了一个接收一个变量的任务，变量是一个具有4个字符串的数组。这个任务可以接受下面的真实变量：

Copy Code
string b[4:1];       // 正确：相同的类型和尺寸
string b[5:2];       // 正确：相同的类型和尺寸（不同的范围）
string b[] = new[4]; // 正确：相同的类型和尺寸，要求运行时的检查

一个接收动态数组的例程可以被传递一个兼容类型的动态数组或者一个具有兼容类型的一维固定尺寸数组。

例如：

Copy Code
task foo(string arr[]);

上面声明了一个将一个字符串动态数组作为变量的任务。这个任务可以接受任何一维字符串数组或任何字符串动态数组。

一个可接受一维数组的导入DPI函数可以被传递一个兼容类型的动态数组，如果形式变量是无尺寸的，这个动态数组可以具有任何尺寸；如果形式变量是有尺寸的，那么这个动态数组需要具有相同的尺寸。然而，如果形式变量是一个无尺寸的输出，那么动态数组不能作为自变量传递。

Group

第四章 数组

链接
第四章 数组


4.9 联合数组

链接
第四章 数组, 主题
SystemVerilog 3.1a语言参考手册
4.9 联合数组
第四章 数组 | 主题

对于处理成员数目会动态改变的连续变量集合而言，动态数组非常有用。然而，当集合的尺寸是未知的或者数据空间紧缺的时候，联合数组则是更好的选择。联合数组在使用之前不会分配任何存储空间，并且索引表达式不再被限制成integral表达式，而是可以具有任何数据类型。

联合数组实现了一个所声明类型的元素的查找表。用作索引的数据类型作为查找表的查找键值，并强制了一种顺序。

联合数组的声明语法如下：

Copy Code
data_type array_id [index_type];

其中：

  • data_type是数组元素的数据类型。固定尺寸数组可以使用的任何类型都可以作为联合数组的数据类型。
  • array_id是联合数组的名字。
  • index_type是用作索引的数据类型， 或者是*。如果指定了*，那么数组可以使用任意尺寸的integral表达式来索引。采用数据类型作为索引的联合数组将索引表达式限制成一个特定的数据类型。

联合数组声明的例子如下：

Copy Code
integer i_array[*];         // 整数联合数组（未指定索引）
bit [20:0] array_b[string]; // 21位向量的联合数组，使用字符串类型作为索引
event ev_array[myClass];    // 事件类型的联合数组，使用类myClass索引

联合数组的元素被动态地分配；一个条目在它第一次写入的时候产生。联合数组维护已经被赋值的条目并根据索引数据类型维护相对顺序。联合数组元素是非压缩的，也就是说，除了拷贝或比较数组之外，当联合数组在大多数表达式中使用之前，你必须从数组中选择单独的元素。

Group

第四章 数组

主题
主题 | 描述
4.9.1 通配符索引类型 | 例子：
4.9.2 字符串索引 | 例子：
4.9.3 类索引 | 例子：
4.9.4 integer（或int）索引 | 例子：
4.9.5 有符号的压缩数组 | 例子：
4.9.6 无符号压缩数组或压缩结构体 | 例子：
4.9.7 其它用户定义类型 | 例子：
链接
第四章 数组, 主题


4.9.1 通配符索引类型

链接
4.9 联合数组
SystemVerilog 3.1a语言参考手册
4.9.1 通配符索引类型
4.9 联合数组

例子：

Copy Code
int array_name [*];

使用通配符索引类型的联合数组具有下列属性：

  • 数组可以使用任意integral数据类型进行索引。因为索引可以具有不同的尺寸，所以相同的数值可以具有多个表示，每一个索引都具有不同的尺寸。通过检测前导0的数目并为每一个值计算唯一的长度和表示，SystemVerilog能够解析这种模糊。
  • 非integral索引类型是非法的，并会导致一个类型检查错误。
  • 包含X或Z的四态索引是无效的。
  • 索引是无符号的。
  • 索引表达式是自解析的；有符号的索引不进行符号扩展。
  • 字符串文本索引被自动地强制转换成等价尺寸的位向量。
  • 按数值顺序排序（从最小到最大）。
Group

4.9 联合数组

链接
4.9 联合数组


4.9.2 字符串索引

链接
4.9 联合数组
SystemVerilog 3.1a语言参考手册
4.9.2 字符串索引
4.9 联合数组

例子：

Copy Code
int array_name [string];

使用字符串作为索引的联合数组具有下列属性：

  • 索引可以是任意长度的字符串或字符串文本。其它类型是非法的，并会导致一个类型检查错误。
  • 空字符串""索引是有效的。
  • 按字典编撰顺序排列（从较小到较大）。
Group

4.9 联合数组

链接
4.9 联合数组


4.9.3 类索引

链接
4.9 联合数组
SystemVerilog 3.1a语言参考手册
4.9.3 类索引
4.9 联合数组

例子：

Copy Code
int array_name [some_Class];

使用类索引的联合数组具有如下的属性：

  • 索引可以是特定类型或从这个类型派生出的对象。任何其它类型都是非法的，并且会导致一个类型检查错误。
  • 一个空索引是有效的。
  • 排序具有确定性，但却是任意的。
Group

4.9 联合数组

链接
4.9 联合数组


4.9.4 integer（或int）索引

链接
4.9 联合数组
SystemVerilog 3.1a语言参考手册
4.9.4 integer（或int）索引
4.9 联合数组

例子：

Copy Code
int array_name [integer];

使用整数索引的联合数组具有如下的属性：

  • 索引可以是任何integral表达式。
  • 索引可以是有符号的。
  • 包含X或Z的四态索引是无效的。
  • 位数小于整数位宽的索引被符号扩展到32位。
  • 位数大于整数位宽的索引被截断至32位。
  • 按有符号数排序。
Group

4.9 联合数组

链接
4.9 联合数组


4.9.5 有符号的压缩数组

链接
4.9 联合数组
SystemVerilog 3.1a语言参考手册
4.9.5 有符号的压缩数组
4.9 联合数组

例子：

Copy Code
typedef bit signed [4:1] Nibble;
int array_name [Nibble];

使用有符号压缩数组作为索引的联合数组具有如下属性：

  • 索引可以是任何integral表达式。
  • 索引是有符号的。
  • 小于索引类型尺寸的索引进行符号扩展。
  • 大于索引类型尺寸的索引截断至索引类型尺寸。
  • 按有符号数排序。
Group

4.9 联合数组

链接
4.9 联合数组


4.9.6 无符号压缩数组或压缩结构体

链接
4.9 联合数组
SystemVerilog 3.1a语言参考手册
4.9.6 无符号压缩数组或压缩结构体
4.9 联合数组

例子：

Copy Code
typedef bit [4:1] Nibble;
int array_name [Nibble];

使用无符号压缩数组作为索引的联合数组具有下列的属性：

  • 索引可以是任何integral表达式。
  • 索引是无符号的。
  • 包含X或Z的四态索引是无效的。
  • 小于索引类型尺寸的索引进行0扩展。
  • 大于索引类型尺寸的索引截断至索引类型尺寸。
  • 按数值顺序排序。

如果读操作过程中使用了一个无效索引（例如4态表达式中包含X）或者试图读取一个不存在的条目，那么会发布一个警告信息并返回数组类型的缺省值，如下表所述：

表4-1：从不存在的关联数组条目中读取值

数组类型 | 读取的值
4态integral类型 | 'X
2态integral类型 | '0
枚举类型 | 枚举中的第一个元素
字符串 | ""
类 | null
事件 | null

如果在写操作过程中使用了一个无效索引，那么写操作会被忽略并发布一个警告信息。

Group

4.9 联合数组

链接
4.9 联合数组


4.9.7 其它用户定义类型

链接
4.9 联合数组
SystemVerilog 3.1a语言参考手册
4.9.7 其它用户定义类型
4.9 联合数组

例子：

Copy Code
typedef struct {
    real R;
    int I[*];
} Unpkt;
int array_name [Unpkt];

通常，将任何类型作为索引的联合数组具有下列属性：

  • 作为索引的类型必须保证相等操作符是有效的。包括将所有动态尺寸类型作为有效的索引类型。
  • 索引表达式是X或Z，或者它的元素中包含X或Z是无效的。
  • 索引表达式是空值或null，或者它的元素中包含空值或null是无效的。
  • 如果索引类型定义了关系操作符，那么按照前面章节所定义的顺序排序。如果不是，那么这样的联合数组中的任何两个条目的相对顺序都是变化的，即使在相同工具的两次连续运行之间也是这样。然而，当没有加入或删除索引的情况下，在同一次仿真运行之内的相对关系必须是相同的。
Group

4.9 联合数组

链接
4.9 联合数组


4.10 联合数组方法

链接
第四章 数组, 主题
SystemVerilog 3.1a语言参考手册
4.10 联合数组方法
第四章 数组 | 主题

除了索引操作符之外，SystemVerilog提供了几个内建方法来允许用户分析和处理联合数组，同时提供了对联合数组的索引或键值的迭代处理。

Group

第四章 数组

主题
主题 | 描述
4.10.1 num() | num()方法的语法如下：
4.10.2 delete() | delete()方法的语法如下：
4.10.3 exists() | exists()方法的语法如下：
4.10.4 first() | first()方法的语法如下：
4.10.5 last() | last()方法的语法如下：
4.10.6 next() | next()方法的语法如下：
4.10.7 prev() | prev()方法的语法如下：
链接
第四章 数组, 主题


4.10.1 num()

链接
4.10 联合数组方法
SystemVerilog 3.1a语言参考手册
4.10.1 num()
4.10 联合数组方法

num()方法的语法如下：

Copy Code
function int num();

num()方法返回联合数组中条目的数目。如果数组是空数组，那么它返回0。

Copy Code
int imem[*];
imem[2'b3] = 1;
imem[16'hffff] = 2;
imem[4'b1000] = 3;
$display("%0d entries\n", imem.num); // 打印"3 entries"
Group

4.10 联合数组方法

链接
4.10 联合数组方法


4.10.2 delete()

链接
4.10 联合数组方法
SystemVerilog 3.1a语言参考手册
4.10.2 delete()
4.10 联合数组方法

delete()方法的语法如下：

Copy Code
function void delete([input index]);

其中index是一个可选的适当类型的索引。

如果指定了索引，那么delete()方法删除特定索引的条目。如果试图删除的条目不存在，该方法不会发布警告信息。

如果没有指定索引，delete()方法删除数组的所有元素。

Copy Code
int map[string];
map["hello"] = 1;
map["sad"] = 2;
map["world"] = 3;
map.delete("sad");   // 从"map"中删除索引为"sad"的条目
map.delete;          // 删除联合数组"map"中的所有条目
Group

4.10 联合数组方法

链接
4.10 联合数组方法


4.10.3 exists()

链接
4.10 联合数组方法
SystemVerilog 3.1a语言参考手册
4.10.3 exists()
4.10 联合数组方法

exists()方法的语法如下：

Copy Code
function int exists(input index);

其中index是一个适当类型的索引。

exists()函数检查对于指定数组中是否存在指定索引的元素。如果元素存在则返回1，否则返回0。

Copy Code
if (map.exists("hello"))
    map["hello"] += 1;
else
    map["hello"] = 0;
Group

4.10 联合数组方法

链接
4.10 联合数组方法


4.10.4 first()

链接
4.10 联合数组方法
SystemVerilog 3.1a语言参考手册
4.10.4 first()
4.10 联合数组方法

first()方法的语法如下：

Copy Code
function int first(ref index);

其中index是一个适当类型的索引。

first()方法将指定的索引变量赋值为联合数组中第一个（最小的）索引的值。如果数组是空的则返回0，否则返回1。

Copy Code
string s;
if (map.first(s))
    $display("First entry is : map[%s] = %0d\n", s, map[s]);
Group

4.10 联合数组方法

链接
4.10 联合数组方法


4.10.5 last()

链接
4.10 联合数组方法
SystemVerilog 3.1a语言参考手册
4.10.5 last()
4.10 联合数组方法

last()方法的语法如下：

Copy Code
function int last(ref index);

其中index是一个适当类型的索引。

last()方法将指定的索引变量赋值为联合数组中最后一个（最大的）索引的值。如果数组是空的则返回0，否则返回1。

Copy Code
string s;
if (map.last(s))
    $display("Last entry is : map[%s] = %0d\n", s, map[s]);
Group

4.10 联合数组方法

链接
4.10 联合数组方法


4.10.6 next()

链接
4.10 联合数组方法
SystemVerilog 3.1a语言参考手册
4.10.6 next()
4.10 联合数组方法

next()方法的语法如下：

Copy Code
function int next(ref index);

其中index是一个适当类型的索引。

next()方法寻找索引值大于指定索引的条目。如果存在下一个条目，索引变量被赋值为下一个条目的索引，并且函数返回1。否则，索引不会发生变化，函数返回0。

Copy Code
string s;
if (map.first(s))
    do
        $display("%s : %d\n", s, map[s]);
    while (map.next(s));
Group

4.10 联合数组方法

链接
4.10 联合数组方法


4.10.7 prev()

链接
4.10 联合数组方法
SystemVerilog 3.1a语言参考手册
4.10.7 prev()
4.10 联合数组方法

prev()方法的语法如下：

Copy Code
function int prev(ref index);

其中index是一个适当类型的索引。

prev()函数寻找索引小于指定索引的条目。如果存在前一个条目，索引变量被赋值为前一个条目的索引，并且函数返回1。否则，索引不会发生变化，并且函数返回0。

Copy Code
string s;
if (map.last(s))
    do
        $display("%s : %d\n", s, map[s]);
    while (map.prev(s));

如果传递给四个联合数组遍历方法（first、last、next、和prev）中任意一个方法的参数小于对应索引的尺寸，那么函数返回-1，并且会拷贝尽可能多的数据来适应这个参数。例如：

Copy Code
string aa[*];
byte ix;
int status;
aa[1000] = "a";
status = aa.first(ix); // status的结果为–1
                       // ix的值为232（值1000的最低有效8位）
Group

4.10 联合数组方法

链接
4.10 联合数组方法


4.11 联合数组赋值

链接
第四章 数组
SystemVerilog 3.1a语言参考手册
4.11 联合数组赋值
第四章 数组

联合数组只能被赋值为另外一个具有兼容类型并且具有相同索引类型的联合数组。其它的数组类型不能赋值给一个联合数组，而联合数组也不能赋值给其它类型的数组，无论是固定尺寸数组还是动态动态数组。

将联合数组赋值给另外一个联合数组会先将目的数组中所有现存条目清除，然后再将源数组中的每一个条目拷贝到目的数组。

Group

第四章 数组

链接
第四章 数组


4.12 联合数组自变量

链接
第四章 数组
SystemVerilog 3.1a语言参考手册
4.12 联合数组自变量
第四章 数组

作为自变量的联合数组只能传递给具有兼容类型并具有相同索引类型的联合数组。其它类型的数组，无论是固定尺寸数组还是动态数组，都不能传递给使用联合数组作为自变量的子程序。同样，联合数组也不能传递给使用其它类型的数组作为自变量的子程序。

通过值传递一个联合数组会产生联合数组的本地拷贝。

Group

第四章 数组

链接
第四章 数组


4.13 联合数组文本

链接
第四章 数组
SystemVerilog 3.1a语言参考手册
4.13 联合数组文本
第四章 数组

联合数组文本值使用{index:value}这样的语法并带有可选的缺省索引。与所有其它数组一样，联合数组可以一次只写一个条目，或者使用数组文本替代整个数组内容。

Copy Code
concatenation ::=   // 引用自附录A.8.1
    ...
  | {array_member_label:expression{, array_member_label:expression}}

array_member_label ::=
    default
  | type_identifier
  | constant_expression

语法 4-2—联合数组文本语法（摘录自附录A）

例如：

Copy Code
// 以两态整数作为索引的字符串联合数组，缺省值为"foo"。
string words [int] = {default: "foo"};

// 以字符串作为索引的四态整数联合数组，缺省值为-1。
integer table [string] = {"Peter":20, "Paul":22, "Mary":23, default:-1};

如果指定了缺省值，那么读取一个不存在的元素会返回这个指定的缺省值。否则，返回表4-1中描述的初始值。

Group

第四章 数组

链接
第四章 数组


4.14 队列

链接
第四章 数组, 主题
SystemVerilog 3.1a语言参考手册
4.14 队列
第四章 数组 | 主题

队列是一个相同元素的可变尺寸的有序集合。队列能够以常量时间访问它的所有元素，也能够以常量时间在队列的尾部和头部插入和删除元素。队列中的每一个元素都通过一个序号来标识，这个序号代表了元素在队列内的位置，0代表第一个元素，$代表最后一个元素。队列类似于一个一维的非压缩数组，它可以自动地增长和缩减。因此，与数组一样，队列可以使用索引、串联、分片、相等操作符进行处理。

队列使用与非压缩数组相同的语法声明，但可以使用$作为数组尺寸。队列的尺寸可以通过指定可选的右边界（最后一个索引）进行限制。

Copy Code
variable_dimension ::=  // 引用自附录A.2.5
     {sized_or_unsized_dimension}
    | associative_dimension
    | queue_dimension

queue_dimension ::= [$[:constant_expression]]

语法4-3—队列维数的声明（摘录自附录A）

constant_expression必须能够计算成一个正的整数值

例如：

Copy Code
byte q1[$];                // 一个字节队列
string names[$] = {"Bob"}; // 具有一个元素的字符串队列
integer Q[$] = {3, 2, 7};  // 一个被初始化成三个元素的整数队列
bit q2[$:255];             // 一个最大尺寸为256的位队列

空队列文本{}可以用来指示一个空队列。如果声明时没有提供初始值，那么队列变量被初始化成一个空队列。

Group

第四章 数组

主题
主题 | 描述
4.14.1 队列操作符 | 队列可以与非压缩数组执行相同的操作，除下述的操作符和操作规则外，它们使用相同的操作符和操作规则。
4.14.2 队列方法 | 除了数组操作符外，队列还提供了几个内建方法。
链接
第四章 数组, 主题


4.14.1 队列操作符

链接
4.14 队列
SystemVerilog 3.1a语言参考手册
4.14.1 队列操作符
4.14 队列

队列可以与非压缩数组执行相同的操作，除下述的操作符和操作规则外，它们使用相同的操作符和操作规则。

Copy Code
int q[$] = {2, 4, 8};
int p[$];
int e, pos;
e = q[0];     // 读取第一个（最左边）条目。
e = q[$];     // 读取最后一个（最右边）条目。
q[0] = e;     // 写第一个元素
p = q;        // 读和写整个队列（拷贝）
q = {q, 6};   // 在队列的尾部插入'6'
q = {e, q};   // 在队列的头部插入'e'
q = q[1:$];   // 删除第一个（最左边）元素
q = q[0:$-1]; // 删除最后一个（最右边）元素
q = q[1:$-1]; // 删除第一个和最后一个元素
q = {};       // 清除队列（删除所有的元素）
q = {q[0:pos-1], e, q[pos:$]}; // 在位置'pos'处插入'e'
q = {q[0:pos], e, q[pos+1:$]}; // 在位置'pos'之后插入'e'

与数组不同，空队列，{}，是一个有效的队列，并且可以作为某些队列操作的结果。下列规则适用于队列操作符：

  • Q[a:b] 产生具有b-a+1个元素的队列。
  • 如果a>b，那么Q[a:b]产生一个空队列{}。
  • Q[n:n]产生具有一个元素的队列，这个元素位于位置n。因此，Q[n:n]==={Q[n]}。
  • 如果 n位于Q(n < 0 或 n > $)的范围之外，那么Q[n:n]产生一个空队列{}。
  • 无论是a还是b是一个包含X或Z的四态表达式，都产生一个空队列{}。
  • Q[a:b]中如果a < 0，那么它与Q[0:b]相同。
  • Q[a:b]中如果b > $，那么它与Q[a:$]相同。
  • 使用无效索引值（例如包含X或Z的四态表示式，或者位于0...$之外的值）的读操作返回对列元素类型的初始值（如表4-1所述）。
  • 使用无效索引值（例如包含X或Z的四态表示式，或者位于0...$之外的值）的写操作会被忽略，并在运行时发布警告信息。注意：向Q[$+1]写入是合法的。
  • 使用[$:N]声明右边界的队列应被限制为从0到N索引（队列的最大尺寸为N+1）。位于这个限制之外的索引是无效的，因此，在队列尾部之外的写操作会被忽略，并发布一个警告信息。这些警告信息或者在编译时发布，或者在运行时发布，只要一发现索引位于队列尺寸限制之外就发布。

注意：队列和动态数组具有相同的赋值和自变量传递语义。

Group

4.14 队列

链接
4.14 队列


4.14.2 队列方法

链接
4.14 队列, 主题
SystemVerilog 3.1a语言参考手册
4.14.2 队列方法
4.14 队列 | 主题

除了数组操作符外，队列还提供了几个内建方法。

Group

4.14 队列

主题
主题 | 描述
4.14.2.1 size() | size()方法的原型如下：
4.14.2.2 insert() | insert()方法的原型如下：
4.14.2.3 delete() | delete()方法的原型如下：
4.14.2.4 pop_front() | pop_front()方法的原型如下：
4.14.2.5 pop_back() | pop_back()方法的原型为：
4.14.2.6 push_front() | push_front()方法的原型如下：
4.14.2.7 push_back() | push_back()方法的原型如下：
链接
4.14 队列, 主题


4.14.2.1 size()

链接
4.14.2 队列方法
SystemVerilog 3.1a语言参考手册
4.14.2.1 size()
4.14.2 队列方法

size()方法的原型如下：

Copy Code
function int size();

size()方法返回队列中元素的数目。如果队列是空的，它返回0。

Copy Code
for (int j=0; j<q.size; j++) $display(q[j]);
Group

4.14.2 队列方法

链接
4.14.2 队列方法


4.14.2.2 insert()

链接
4.14.2 队列方法
SystemVerilog 3.1a语言参考手册
4.14.2.2 insert()
4.14.2 队列方法

insert()方法的原型如下：

Copy Code
function void insert(int index, queue_type item);

insert()方法在指定的索引位置插入指定的元素。

  • Q.insert(i, e)等效于Q = {Q[0:i-1], e, Q[i,$]}
Group

4.14.2 队列方法

链接
4.14.2 队列方法


4.14.2.3 delete()

链接
4.14.2 队列方法
SystemVerilog 3.1a语言参考手册
4.14.2.3 delete()
4.14.2 队列方法

delete()方法的原型如下：

Copy Code
function void delete(int index);

delete()方法删除指定索引位置的元素。

  • Q.delete(i)等价于Q = {Q[0:i-1], Q[i+1,$]}
Group

4.14.2 队列方法

链接
4.14.2 队列方法


4.14.2.4 pop_front()

链接
4.14.2 队列方法
SystemVerilog 3.1a语言参考手册
4.14.2.4 pop_front()
4.14.2 队列方法

pop_front()方法的原型如下：

Copy Code
function queue_type pop_front();

pop_front()方法删除并返回队列的第一个元素。

  • e = Q.pop_front()等价于：e = Q[0]; Q = Q[1,$]
Group

4.14.2 队列方法

链接
4.14.2 队列方法


4.14.2.5 pop_back()

链接
4.14.2 队列方法
SystemVerilog 3.1a语言参考手册
4.14.2.5 pop_back()
4.14.2 队列方法

pop_back()方法的原型为：

Copy Code
function queue_type pop_back();

pop_back()方法删除并返回队列的最后一个元素。

  • e = Q.pop_back()等价于：e = Q[$]; Q = Q[0,$-1]
Group

4.14.2 队列方法

链接
4.14.2 队列方法


4.14.2.6 push_front()

链接
4.14.2 队列方法
SystemVerilog 3.1a语言参考手册
4.14.2.6 push_front()
4.14.2 队列方法

push_front()方法的原型如下：

Copy Code
function void push_front(queue_type item);

push_front()方法在队列的前端插入指定的元素。

  • Q.push_front(e)等价于：Q = {e, Q}
Group

4.14.2 队列方法

链接
4.14.2 队列方法


4.14.2.7 push_back()

链接
4.14.2 队列方法
SystemVerilog 3.1a语言参考手册
4.14.2.7 push_back()
4.14.2 队列方法

push_back()方法的原型如下：

Copy Code
function void push_back(queue_type item);

push_back()方法在队列的尾部插入指定的元素。

  • Q.push_back(e)等价于：Q = {Q, e}
Group

4.14.2 队列方法

链接
4.14.2 队列方法


4.15 数组处理方法

链接
第四章 数组, 主题
SystemVerilog 3.1a语言参考手册
4.15 数组处理方法
第四章 数组 | 主题

SystemVerilog提供了几个内建的方法来方便数组的搜索、排序和缩减。

调用这些数组方法的基本语法如下：

Copy Code
array_method_call ::= //没有包含在附录A中
    expression.array_method_name{attribute_instance}[(list_of_arguments)]
        [with(expression)]

语法 4-4—数组方法调用语法

可选的with子句接受一个包含在圆括号内的表达式。作为对比，随机化方法（参见12.6节）使用的with子句接受一组包含在花括号内的约束。

Group

第四章 数组

主题
主题 | 描述
4.15.1 数组定位符方法 | 数组定位符方法可以对任意非压缩数组（包括队列）进行操作，但它们的返回值是一个队列。这些定位符方法能够在数组中搜索满足一个指定表示式的元素（或它们的索引）。数组定位符方法以未指定的顺序遍历数组。表达式选项不应具有任何边带效应，否则，会出现不可预料的结果。 这些方法的原型如下：
4.15.2 数组排序方法 | 数组排序方法可以对一维数组或队列的元素重新排序。 数组排序方法的基本原型如下：
4.15.3 数组缩减方法 | 数组缩减方法适用于任何非压缩数组以便将数组缩减成一个单独的值。可选的with子句中的表达式被用来指定缩减操作中使用的元素。 这些方法的原型如下：
4.15.4 迭代器索引查询 | 在数组处理方法中使用的表达式有时在每一次迭代过程中都需要真实的数组索引，而不仅仅是数组元素。一个迭代器的索引方法返回指定维数的索引值。 索引方法的原型如下：
链接
第四章 数组, 主题


4.15.1 数组定位符方法

链接
4.15 数组处理方法
SystemVerilog 3.1a语言参考手册
4.15.1 数组定位符方法
4.15 数组处理方法

数组定位符方法可以对任意非压缩数组（包括队列）进行操作，但它们的返回值是一个队列。这些定位符方法能够在数组中搜索满足一个指定表示式的元素（或它们的索引）。数组定位符方法以未指定的顺序遍历数组。表达式选项不应具有任何边带效应，否则，会出现不可预料的结果。

这些方法的原型如下：

Copy Code
function array_type[$] locator_method(array_type iterator=item);
// 与数组相同的类型

或者

Copy Code
function int_or_index_type[$] index_locator_method(array_type iterator=item);
// 索引类型

索引定位符方法为除联合数组外的所有数组返回一个int队列，而对联合数组的操作返回一个与联合数组索引类型具有相同类型的队列。

如果没有元素满足指定的表达式或者数组是空数组（在队列或动态数组的情况下），那么返回一个空队列。否则，这些方法返回一个包含满足表达式的所有元素的队列。索引定位符方法返回一个满足表达式的所有元素的索引的队列。使用with子句指定的可选表达式必须能够计算成一个布尔值。

定位符方法在数组元素上迭代，接着它被用来计算with子句指定的表达式。迭代器自变量可选地指定变量的名字，with表达式使用这个变量在每一次迭代上指定数组的元素。如果没有指定，那么使用缺省的元素名字。迭代器名字的范围就是with表达式。

支持下列的定位符方法（with子句是强制的）：

  • find()返回满足指定表达式的所有元素。
  • find_index()返回满足指定表达式的所有元素的索引。
  • find_first()返回满足指定表达式的第一个元素。
  • find_first_index()返回满足指定表达式的第一个元素的索引。
  • find_last()返回满足指定表达式的最后一个元素。
  • find_last_index()返回满足指定表达式的最后一个元素的索引。

对于下列的定位符方法，如果为指定数组的元素类型定义了关系操作符，那么with子句（<，>，==）（以及它的表达式）可以被忽略。如果指定了一个with子句，表达式类型的关系操作符（<，>，==）必须被定义。

  • min()返回具有最小值或者它的表达式可以被计算成最小的元素。
  • max()返回具有最大值或者它的表达式可以被计算成最大的元素。
  • unique()返回具有唯一值或者它的表达式是唯一的所有元素。
  • unique_index()返回具有唯一值或者它的表达式是唯一的所有元素的索引。

例子：

Copy Code
string SA[10], qs[$];
int IA[*], qi[$];

// 找到大于5的所有元素
qi = IA.find(x) with (x>5);

// 找到等于3的所有元素的索引。
qi = IA.find_index with (item==3);

// 找到等于Bob的第一个元素
qs = SA.find_first with(item=="Bob");

// 找到等于Henry的最后一个元素
qs = SA.find_last(y) with (y=="Henry");

// 找到大于Z的最后一个元素的索引
qi = SA.find_last_index(s) with (s>"Z");

// 找到最小的元素
qi = IA.min;

// 找到具有最大数值的字符串
qs = SA.max with(item.atoi);

// 找到所有的唯一字符串元素
qs = SA.unique;

// 找到以小写字母表示的所有唯一字符串
qs = SA.unique(s) with (s.tolower);
Group

4.15 数组处理方法

链接
4.15 数组处理方法


4.15.2 数组排序方法

链接
4.15 数组处理方法
SystemVerilog 3.1a语言参考手册
4.15.2 数组排序方法
4.15 数组处理方法

数组排序方法可以对一维数组或队列的元素重新排序。

数组排序方法的基本原型如下：

Copy Code
function void ordering_method (array_type iterator = item)

SystemVerilog支持下列的排序方法：

  • reverse()反转数组（压缩的以及非压缩的）中的所有元素。指定一个with子句会引起一个编译器错误。
  • sort()以升序排列非压缩数组，可选地在with子句中使用表达式。当为数组元素类型定义了关系操作符的时候，with子句（以及它的表达式）是可选的。
  • rsort()以降序排列非压缩数组， 可选地在with子句中使用表达式。当为数组元素类型定义了关系操作符的时候，with子句（以及它的表达式）是可选的。
  • shuffle()将数组中元素的顺序随机化。指定一个with子句会引起一个编译器错误。

例子：

Copy Code
string s[] = {"hello", "sad", "world"};
s.reverse;   // s变为{"world", "sad", "hello"};

logic [4:1] b = 4'bXZ01;
b.reverse;   // b变为4'b10ZX

int q[$] = {4, 5, 3, 1};
q.sort;      // q变为{1, 3, 4, 5}

struct {byte red, green, blue} c [512];
c.sort with(item.red);      // 仅使用red域对c排序
c.sort(x) with (x.blue<<8+x.green); // 以blue接着green的顺序排序
Group

4.15 数组处理方法

链接
4.15 数组处理方法


4.15.3 数组缩减方法

链接
4.15 数组处理方法
SystemVerilog 3.1a语言参考手册
4.15.3 数组缩减方法
4.15 数组处理方法

数组缩减方法适用于任何非压缩数组以便将数组缩减成一个单独的值。可选的with子句中的表达式被用来指定缩减操作中使用的元素。

这些方法的原型如下：

Copy Code
function expression_or_array_type reduction_method (array_type iterator = item)

方法返回一个与数组元素相同类型的单一的值，或者，如果指定的话，它返回一个与with子句中表达式相同类型的单一的值。如果数组元素类型定义了相应的算术或布尔缩减操作的话，那么with子句可以被忽略。如果指定了with子句，那么表达式类型对应的算术或布尔缩减操作必须被定义。

SystemVerilog支持下列的缩减方法：

  • sum()返回所有数组元素的和，或者，如果指定了with子句，它返回通过为每一个数组元素计算所产生的值的和。
  • product()返回所有数组元素的积，或者，如果指定了with子句，它返回通过为每一个数组元素计算所产生的值的积。
  • and()返回所有数组元素的位与（&），或者，如果指定了with子句，它返回通过为每一个数组元素计算所产生的值的位与。
  • or()返回所有数组元素的位或（|），或者，如果指定了with子句，它返回通过为每一个数组元素计算所产生的值的位或。
  • xor()返回所有数组元素的位异或（^），或者，如果指定了with子句，它返回通过为每一个数组元素计算所产生的值的位异或。

例子：

Copy Code
byte b[] = { 1, 2, 3, 4 };
int y;
y = b.sum ; // y变为10 => 1 + 2 + 3 + 4
y = b.product ; // y变为24 => 1 * 2 * 3 * 4
y = b.xor with ( item + 4 ); // y变为12 => 5 ^ 6 ^ 7 ^ 8
Group

4.15 数组处理方法

链接
4.15 数组处理方法


4.15.4 迭代器索引查询

链接
4.15 数组处理方法
SystemVerilog 3.1a语言参考手册
4.15.4 迭代器索引查询
4.15 数组处理方法

在数组处理方法中使用的表达式有时在每一次迭代过程中都需要真实的数组索引，而不仅仅是数组元素。一个迭代器的索引方法返回指定维数的索引值。

索引方法的原型如下：

Copy Code
function int_or_index_type index (int dimension = 1)

数组维数使用23.7节中描述的方式编号：变化最慢的是维数1。变化更快的维数具有更高的维数编号。如果没有指定维数，缺省使用第一维。

除联合数组外，索引方法对所有其它数组迭代器元素返回的类型是int。联合数组返回与联合索引类型相同类型的索引。

例如：

Copy Code
int arr[]
int mem[9:0][9:0], mem2[9:0][9:0];
int q[$];
...
// 找到等于它们位置（索引）的所有元素
q = arr.find with ( item == item.index );

// 在mem中找到大于mem2中对应元素的所有元素。
q = mem.find(x) with (x>mem2[x.index(1)][x.index(2)]);
Group

4.15 数组处理方法

链接
4.15 数组处理方法


第五章 数据声明

链接
主题
SystemVerilog 3.1a语言参考手册
第五章 数据声明
主题
主题
主题 | 描述
5.1 简介（一般信息） | 在SystemVerilog中存在几种形式的数据：文本值（参见第二章）、参数（参见第二十一章）、常量、变量、线网、以及属性（参见第六章）。 在Verilog-2001中，常量可以是文本值、genvar参数、localparam和specparam。Verilog-2001还具有变量和线网。变量必须使用过程语句写入，线网必须通过连续赋值或端口写入。 SystemVerilog扩展了变量的功能，变量既可以使用过程语句写入，也可以像wire那样使用单一的连续赋值进行驱动。由于关键字reg在许多情况下不再描述用户意图，所以加入了关键字logic作为等价于reg的更为精确的描述。Verilog-2001已经不赞成使用术语“寄存器”，取而代之的是术语“变量”。 除了隐式线网之外，SystemVerilog遵从Verilog中关于数据必须在其使用之前声明的规定。隐式线网的规则与Verilog-2001中的规定相同。 变量可以是静态的（在实例化的时候分配存储空间并且永远不会释放），也可以自动的（在进入变量作用范围（例如任务、函数或块）时分配并在退出时释放）。C语言具有static和auto关键字。SystemVerilog遵从Verilog中关于静态缺省存储类，以及自动的任务和函数的规则，但允许在这些任务和函数中使用静态存储覆盖一个特定变量的动态存储。
5.2 数据声明语法 |
5.3 常量 | 常量是永远也不会改变的命名数据变量。SystemVerilog中有三种类型的常量，它们分别使用关键字localparam、specparam和const声明。所有这三种类型的常量都使用一个文本值来初始化。
5.4 变量 | 变量声明包含一个数据类型紧跟着一个或多个变量实例。
5.5 作用范围与生命周期 | 在模块、接口、任务或函数外声明的任何数据都具有全局的作用范围（可以在其声明后的任何地方使用），并且具有一个静态的生命周期（在整个确立和仿真时间内存在）。 在模块或接口内但在任务、进程或函数之外声明的SystemVerilog数据具有本地的作用范围，并具有静态的生命周期（在模块或接口的生命周期内存在）。这大致等价于C语言中在函数外声明的静态数据，它对于文件来说是本地的。 在自动任务、函数或块内声明的数据具有调用期或激活期内的生命周期，并且具有本地的作用范围。这大致等价于C的自动变量。 在一个静态任务、函数或块内声明的数据缺省情况下具有静态的生命周期并具有本地的作用范围。 注意：在SystemVerilog中，数据既可以在未命名的块中声明也可以在命名的块中声明。这些数据对未命名的块及其底层的嵌套块都是可见的。但不能使用层次化引用来通过名字访问数据。 Verilog-2001允许将任务和函数声明成automatic的，这使得任务或函数内的所有存储空间都是自动的。SystemVerilog允许一个静态任务或函数内的特定数据被显式地声明成automatic的。声明成自动的数据具有调用或块内的生命周期，并且在每次进入调用或块内的时候进行初始化。fork...jion、fork...jion_any或fork...join_one块的生命周期应该包含块内所有进程的执行。一个包含任何fork...jion块范围的生命周期包括fork...jion块的生命周期。 SystemVerilog也允许数据被显式地声明成静态的。在一个自动任务、函数或块内声明的静态数据具有静态的生命周期并且对于块来说具有本地的作用范围。这类似于C语言中在一个函数内声明的静态数据。
5.6 线网、reg、与logic | Verilog-2001指出，线网可以使用一个或多个连续赋值语句、原语输出或模块端口写入。多驱动的结果值由线网类型的解析函数确定。线网不能使用过程赋值语句。如果端口一侧的线网被端口另一侧的变量所驱动，那么隐含是连续赋值。force语句可以覆盖线网的值。当其被释放以后，线网返回到解析的值。 Verilog-2001还指出，一个或多个过程语句可以对变量执行写操作，包括过程连续赋值。最后一次执行的写入操作确定变量的值。变量不能被连续赋值。force语句覆盖过程赋值语句，它轮流覆盖正常的赋值。变量不能通过端口写入，它必须通过一个隐含的由连续赋值驱动的线网写入。 在SystemVerilog中，所有变量现在都可以通过连续赋值写入，或者通过一个或多个过程语句写入，包括过程连续赋值。在一个被写入的逻辑变量的最长静态前缀扩展中（关于一个最长静态前缀扩展的定义，参见9.2.1节），对其中任何项使用连续赋值或过程赋值与连续赋值的混合来执行写入操作都是错误的。所有数据类型都可以通过一个端口写入。 SystemVerilog变量可以是其它数据类型的压缩或非压缩集合。对变量中独立元素的多个赋值被单独地检查。左侧包含了一个分片的赋值被看作是对整个分片的单一赋值。使用过程赋值与连续赋值的混合形式写入一个压缩结构体或压缩数组类型是错误的。因此，一个非压缩结构体或非压缩数组中的一个元素可以过程化赋值，而另一个元素可以进行连续赋值。并且，一个压缩结构体或压缩数组的每一个元素都可以使用单一的连续赋值。例如，对于下面的结构体声明：
5.7 信号别名 | Verilog assign语句是单向赋值并可以结合一个延时和强度变化。为了建模一个双向短路连接，很有必要使用alias语句。一个别名列表的成员是那些共享相同物理网络的信号。下面的例子实现了总线A和总线B之间的字节顺序交换。
5.8 类型兼容性 | 为了使操作数是合法的，某些SystemVerilog结构和操作要求某种程度的类型兼容。SystemVerilog具有四种层次的类型兼容，形式上进行如下的定义：等价、赋值兼容、强制转换兼容、以及不等价。 注意：这里没有定义相同类型这一类别，因为SystemVerilog语言中没有哪种结构需要这种类别。例如，就像下面定义的那样，int可以与bit signed [0:31]互换，只要在语法上这样做是合法的。用户可以使用$typename系统函数（参见23.3节，typname函数）或通过使用PLI来定义自己的类型标识层次。
链接
主题


5.1 简介（一般信息）

链接
第五章 数据声明
SystemVerilog 3.1a语言参考手册
5.1 简介（一般信息）
第五章 数据声明

在SystemVerilog中存在几种形式的数据：文本值（参见第二章）、参数（参见第二十一章）、常量、变量、线网、以及属性（参见第六章）。

在Verilog-2001中，常量可以是文本值、genvar参数、localparam和specparam。Verilog-2001还具有变量和线网。变量必须使用过程语句写入，线网必须通过连续赋值或端口写入。

SystemVerilog扩展了变量的功能，变量既可以使用过程语句写入，也可以像wire那样使用单一的连续赋值进行驱动。由于关键字reg在许多情况下不再描述用户意图，所以加入了关键字logic作为等价于reg的更为精确的描述。Verilog-2001已经不赞成使用术语“寄存器”，取而代之的是术语“变量”。

除了隐式线网之外，SystemVerilog遵从Verilog中关于数据必须在其使用之前声明的规定。隐式线网的规则与Verilog-2001中的规定相同。

变量可以是静态的（在实例化的时候分配存储空间并且永远不会释放），也可以自动的（在进入变量作用范围（例如任务、函数或块）时分配并在退出时释放）。C语言具有static和auto关键字。SystemVerilog遵从Verilog中关于静态缺省存储类，以及自动的任务和函数的规则，但允许在这些任务和函数中使用静态存储覆盖一个特定变量的动态存储。

Group

第五章 数据声明

链接
第五章 数据声明


5.2 数据声明语法

链接
第五章 数据声明
SystemVerilog 3.1a语言参考手册
5.2 数据声明语法
第五章 数据声明
Copy Code
data_declaration15 ::=   // 引用自附录A.2.1.3
    [const][lifetime] variable_declaration
  | type_declaration
  | package_import_declaration
  | virtual_interface_declaration

variable_declaration ::=
    data_type list_of_variable_decl_assignments;

lifetime ::= static|automatic

15)：对于不在过程关联文中的数据声明，使用automatic关键字是非法的。

语法 5-1 — 数据声明语法（摘录自附录A）

Group

第五章 数据声明

链接
第五章 数据声明


5.3 常量

链接
第五章 数据声明
SystemVerilog 3.1a语言参考手册
5.3 常量
第五章 数据声明

常量是永远也不会改变的命名数据变量。SystemVerilog中有三种类型的常量，它们分别使用关键字localparam、specparam和const声明。所有这三种类型的常量都使用一个文本值来初始化。

Copy Code
localparam byte colon1 = ":";
specparam int delay = 10; // specparams用来指定块
const logic flag = 1;

参数或本地参数只能被设置成一个文本值的表达式、参数或本地参数、genvar、枚举名字、或者是这些类型的数据的常量函数。其中不允许使用层次化的名字。

specparam还可以被设置为包含一个或多个specparam的表达式。

使用const关键字声明的静态常量只能被设置为一个文本值的表达式、参数、本地参数、genvar、枚举名字、这些类型的常量函数、或者其它常量。参数、本地参数或常量函数可以具有层次化的名字，因为使用const关键字声明的常量是在确立之后计算。使用const关键字声明的自动常量可以被设置为任意表达式，只要这个表达式在没有const关键字时也是合法的。

Copy Code
const logic option = a.b.c;

一个常量表达式包含文本值以及其它的命名常量。

一个类的实例（一个对象句柄）也可以使用const关键字声明。

Copy Code
const class_name object = new(5,3);

这就意味着对象的行为就象一个不能被写入的变量。new方法的自变量必须是一个常量表达式。对象的成员可以被写入（除了使用const关键字声明的成员之外）。

SystemVerilog对parameter和localparam常量声明的增强将在第二十一章详细描述。SystemVerilog没有改变specparam常量声明。const常量与localparam常量的区别在于localparam必须在确立过程中设置，而const常量则在仿真过程中设置，例如在一个自动任务中。

Group

第五章 数据声明

链接
第五章 数据声明


5.4 变量

链接
第五章 数据声明
SystemVerilog 3.1a语言参考手册
5.4 变量
第五章 数据声明

变量声明包含一个数据类型紧跟着一个或多个变量实例。

Copy Code
shortint s1, s2[0:9];

一个变量在声明的时候可以使用一个初始器，例如：

Copy Code
int i = 0;

在Verilog-2001中，在声明中指定初始值就像仿真启动以后在initial块中的赋值一样。因此，初始化可以在仿真时间0的时候引起变量上的一个事件。

在SystemVerilog中，设置一个静态变量的初始值是作为变量声明的一部分（包括静态类成员），它发生在initial或always块启动之前，并且不会产生一个事件。如果确实需要一个事件，那么可以用intial块设置初始值。

SystemVerilog中的初始值并没有被限制成简单常量；他们可以包括运行时的表达式，包括动态存储器分配。例如，一个静态类句柄或一个mailbox可以通过调用它的new方法（参见13.3.1节中的介绍）来产生，或者通过调用$urandom系统任务将静态变量初始化成随机值。这在运行时就要求一个特殊的初始化前的传递。

表 5-1: 缺省值

类型 | 缺省的初始值
四态integral | 'X
两态integral | '0
real、shortreal | 0.0
枚举 | 枚举中的第一个值
字符串 | ""（空字符串）
事件 | new事件
类 | null
chandle（不透明句柄） | null
Group

第五章 数据声明

链接
第五章 数据声明


5.5 作用范围与生命周期

链接
第五章 数据声明
SystemVerilog 3.1a语言参考手册
5.5 作用范围与生命周期
第五章 数据声明

在模块、接口、任务或函数外声明的任何数据都具有全局的作用范围（可以在其声明后的任何地方使用），并且具有一个静态的生命周期（在整个确立和仿真时间内存在）。

在模块或接口内但在任务、进程或函数之外声明的SystemVerilog数据具有本地的作用范围，并具有静态的生命周期（在模块或接口的生命周期内存在）。这大致等价于C语言中在函数外声明的静态数据，它对于文件来说是本地的。

在自动任务、函数或块内声明的数据具有调用期或激活期内的生命周期，并且具有本地的作用范围。这大致等价于C的自动变量。

在一个静态任务、函数或块内声明的数据缺省情况下具有静态的生命周期并具有本地的作用范围。

注意：在SystemVerilog中，数据既可以在未命名的块中声明也可以在命名的块中声明。这些数据对未命名的块及其底层的嵌套块都是可见的。但不能使用层次化引用来通过名字访问数据。

Verilog-2001允许将任务和函数声明成automatic的，这使得任务或函数内的所有存储空间都是自动的。SystemVerilog允许一个静态任务或函数内的特定数据被显式地声明成automatic的。声明成自动的数据具有调用或块内的生命周期，并且在每次进入调用或块内的时候进行初始化。fork...jion、fork...jion_any或fork...join_one块的生命周期应该包含块内所有进程的执行。一个包含任何fork...jion块范围的生命周期包括fork...jion块的生命周期。

SystemVerilog也允许数据被显式地声明成静态的。在一个自动任务、函数或块内声明的静态数据具有静态的生命周期并且对于块来说具有本地的作用范围。这类似于C语言中在一个函数内声明的静态数据。

Copy Code
module msl;

int st0;                  // 静态的

initial begin
    int st1;              // 静态的
    static int st2;       // 静态的
    automatic int auto1;  // 自动的
end

task automatic t1();
    int auto2;            // 自动的
    static int st3;       // 静态的
    automatic int auto3;  // 自动的
endtask

endmodule

对于在模块、接口或程序（参见第十六章）中定义的任务、函数或块，SystemVerilog加入了一个可选的限定符来指定其中声明的所有变量的缺省生命周期。生命周期限定符可以是automatic或static。缺省的生命周期是static。

Copy Code
program automatic test;
    int i;           // 没有在一个过程块内 - 静态的

    task foo(int a); // 在foo内的自变量和变量是自动的
        ...
    endtask
endmodule

类方法以及声明的for循环变量缺省是自动的，无论它们所在的范围的生命周期属性是什么。类将在第十一章中讨论。

注意：自动或动态变量不能够使用非阻塞赋值或连续赋值来写入。自动变量以及动态结构（对象句柄、动态数组、联合数组、字符串以及事件变量）应被限制到过程关联文中。

参见第十章中有关任务和函数的说明。

Group

第五章 数据声明

链接
第五章 数据声明


5.6 线网、reg、与logic

链接
第五章 数据声明
SystemVerilog 3.1a语言参考手册
5.6 线网、reg、与logic
第五章 数据声明

Verilog-2001指出，线网可以使用一个或多个连续赋值语句、原语输出或模块端口写入。多驱动的结果值由线网类型的解析函数确定。线网不能使用过程赋值语句。如果端口一侧的线网被端口另一侧的变量所驱动，那么隐含是连续赋值。force语句可以覆盖线网的值。当其被释放以后，线网返回到解析的值。

Verilog-2001还指出，一个或多个过程语句可以对变量执行写操作，包括过程连续赋值。最后一次执行的写入操作确定变量的值。变量不能被连续赋值。force语句覆盖过程赋值语句，它轮流覆盖正常的赋值。变量不能通过端口写入，它必须通过一个隐含的由连续赋值驱动的线网写入。

在SystemVerilog中，所有变量现在都可以通过连续赋值写入，或者通过一个或多个过程语句写入，包括过程连续赋值。在一个被写入的逻辑变量的最长静态前缀扩展中（关于一个最长静态前缀扩展的定义，参见9.2.1节），对其中任何项使用连续赋值或过程赋值与连续赋值的混合来执行写入操作都是错误的。所有数据类型都可以通过一个端口写入。

SystemVerilog变量可以是其它数据类型的压缩或非压缩集合。对变量中独立元素的多个赋值被单独地检查。左侧包含了一个分片的赋值被看作是对整个分片的单一赋值。使用过程赋值与连续赋值的混合形式写入一个压缩结构体或压缩数组类型是错误的。因此，一个非压缩结构体或非压缩数组中的一个元素可以过程化赋值，而另一个元素可以进行连续赋值。并且，一个压缩结构体或压缩数组的每一个元素都可以使用单一的连续赋值。例如，对于下面的结构体声明：

Copy Code
struct {
    bit [7:0] A;
    bit [7:0] B;
    byte C;
} abc;

下列的语句对于结构体abc来说都是合法的赋值：

Copy Code
assign abc.C = sel ? 8'hBE : 8'hEF;

not (abc.A[0],abc.B[0]),
    (abc.A[1],abc.B[1]),
    (abc.A[2],abc.B[2]),
    (abc.A[3],abc.B[3]);

always @(posedge clk)
    abc.B <= abc.B + 1;

下列的语句对于结构体abc来说都是非法的赋值：

Copy Code
// 对abc.C的多个连续赋值
assign abc.C = sel ? 8'hhDE : 8'hED; // ？？？

// 对abc.A的连续和过程赋值的混合
always @(posedge clk)
    abc.A[7:4] <= !abc.B[7:4];

为了遵从上述规则，在声明时进行的变量初始化或者一个过程连续赋值被认为是一个过程赋值。一条force语句既不是一个连续赋值也不是一个过程赋值。一条release语句在没有另外一个过程赋值之前不应改变变量的值，或者，release语句应对驱动它的连续赋值语句进行重新运算。一条单一的force或release语句不应应用到通过连续和过程混合赋值的变量的整体或部分。

当一个变量被连接到一个输入端口声明时，隐含着一个连续赋值。这就使得对一个声明成输入端口的变量的赋值是非法的。当一个变量被连接到一个实例的输出端口的时候，隐含着一个连续赋值。这就使得对一个连接到实例输出端口的变量的过程赋值或连续赋值是非法的。

SystemVerilog变量不能被连接到inout端口的任意一侧。SystemVerilog通过ref端口类型引入了穿越端口的共享变量的概念。参阅18.12节以便获得有关端口和端口连接规则的更详细的信息。

在一个连续赋值能够将一个变量驱动成除St0、St1、StX、或Hiz之外的强度的时候，编译器可以发布一条警告信息。在任何情况下，SystemVerilog都对赋值施加自动的类型转换，并且会将强度信息丢失。

注意：SystemVerilog不能将隐式的连续赋值作为它的声明的一部分，与此相反的是，线网可以这样做。作为逻辑声明一部分的赋值是变量的初始化，而不是一个连续赋值。例如：

Copy Code
wire w = vara & varb;        // 连续赋值

logic v = consta & constb;   // 初始化过程赋值

logic vw;                    // 没有初始化赋值
assign vw = vara & varb;     // 对一个logic类型变量的连续赋值

real circ;
assign circ = 2.0 * PI * R; // 对一个real类型变量的连续赋值
Group

第五章 数据声明

链接
第五章 数据声明


5.7 信号别名

链接
第五章 数据声明
SystemVerilog 3.1a语言参考手册
5.7 信号别名
第五章 数据声明

Verilog assign语句是单向赋值并可以结合一个延时和强度变化。为了建模一个双向短路连接，很有必要使用alias语句。一个别名列表的成员是那些共享相同物理网络的信号。下面的例子实现了总线A和总线B之间的字节顺序交换。

Copy Code
module byte_swap (inout wire [31:0] A, inout wire [31:0] B);
    alias {A[7:0],AA[15:8],AA[23:16],AA[31:24]} = B;
endmodule

下面的例子从一个四字节总线中剥离最低和最高有效字节：

Copy Code
module byte_rip (inout wire [31:0] W, inout wire [7:0] LSB, MSB);
    alias W[7:0] = LSB;
    alias W[31:24] = MSB;
endmodule

位覆盖规则与具有相同成员类型的压缩联合体的位覆盖规则相同：每一个成员应具有相同的尺寸，并且连通性独立于仿真主机。使用别名语句连接的线网必须是类型兼容的。换句话说，它们必须是相同的线网类型。例如，使用alias语句将一个wand线网连接到wor线网是非法的。这比应用到在端口上结合的线网具有更严格的规则，因为别名的作用范围是受限的并且这样的连接很可能是一个设计错误。变量和层次化引用不能使用在别名语句中。如果违背这些规则，那么会认为是一个严重错误。

相同的线网可以出现在多条别名语句中。效果是累积的。下面两个例子是等价的。在这两种情况下，low12[11:4]和high12[7:0]共享相同的线网。

Copy Code
module overlap(inout wire [15:0] bus16, inout wire [11:0] low12, high12);
    alias bus16[11:0] = low12;
    alias bus16[15:4] = high12;
endmodule

module overlap(inout wire [15:0] bus16, inout wire [11:0] low12, high12);
    alias bus16 = {high12, low12[3:0]};
    alias high12[7:0] = low12[11:4];
endmodule

为了在规范中避免错误，SystemVerilog不允许从一个单独的变量中为它本身指定别名，也不允许多次指定一个特定的别名。上面代码的下面版本是非法的，因为高四位与低四位在两条语句中是相同的：

Copy Code
alias bus16 = {high12[11:8], low12};
alias bus16 = {high12, low12[3:0]};

下面的语句也是非法的，因为bus16的各位是它本身的别名：

Copy Code
alias bus16 = {high12, bus16[3:0]} = {bus16[15:12], low12};

在模块实例语句可以出现的任何地方都可以出现别名语句。如果在别名语句中出现了没有声明数据类型的标识符，那么就隐含成线网，并与模块实例的隐式线网遵从相同的规则。对于来自不同库的单元，下面的例子使用alias并伴随着自动的名字绑定来连接单元管脚，这样就产生一个标准宏：

Copy Code
module lib1_dff(Reset, Clk, Data, Q, Q_Bar);
    ...
endmodule

module lib2_dff(reset, clock, data, a, qbar);
    ...
endmodule

module lib3_dff(RST, CLK, D, Q, Q_);
    ...
endmodule

macromodule my_dff(rst, clk, d, q, q_bar); // 包装单元
    input rst, clk, d;
    output q, q_bar;
    alias rst = Reset = reset = RST;
    alias clk = Clk = clock = CLK;
    alias d = data = D;
    alias q = Q;
    alias Q_ = q_bar = Q_Bar = qbar;

    ‘LIB_DFF my_dff (.*); // LIB_DFF可以是lib1_dff、lib2_dff或lib3_dff中的任意一个

endmodule

在一条别名语句中使用线网不会修改线网在其它语句中的语法行为。别名在确立的时候执行并且不能取消。

Group

第五章 数据声明

链接
第五章 数据声明


5.8 类型兼容性

链接
第五章 数据声明, 主题
SystemVerilog 3.1a语言参考手册
5.8 类型兼容性
第五章 数据声明 | 主题

为了使操作数是合法的，某些SystemVerilog结构和操作要求某种程度的类型兼容。SystemVerilog具有四种层次的类型兼容，形式上进行如下的定义：等价、赋值兼容、强制转换兼容、以及不等价。

注意：这里没有定义相同类型这一类别，因为SystemVerilog语言中没有哪种结构需要这种类别。例如，就像下面定义的那样，int可以与bit signed [0:31]互换，只要在语法上这样做是合法的。用户可以使用$typename系统函数（参见23.3节，typname函数）或通过使用PLI来定义自己的类型标识层次。

Group

第五章 数据声明

主题
主题
描述
5.8.1 等价类型
如果两个数据类型符合下列的归纳定义，那么它们是等价的。如果两个数据类型不符合下列的归纳定义，那么它们就是不等价的。

  1. 在每一个范围内，任何内建类型都等价于它本身的每一个其它的具体值。
  2. 一个简单的typedef或者重命名了一个内建的或用户定义类型的类型参数覆盖在类型标识符作用范围内等价于那个内建的或用户定义的数据类型。

5.8.2 赋值兼容
所有的等价类型以及所有定义了隐式强制类型转换的非等价类型都是赋值兼容的类型。例如，所有integral类型都是赋值兼容的。赋值兼容类型间的转换会由于缩减或四舍五入导致数据丢失。

兼容性可能仅存在于一个方向上。例如，一个枚举类型不需要一个强制类型转换就可以转换成integral类型，但反方向则不行。显式强制类型转换在“第三章 数据类型”以及“第七章 操作符与表达式”中定义。
5.8.3 强制转换兼容
所有的赋值兼容类型，加上定义了显式强制类型转换规则的非等价类型都是强制转换兼容的。例如，一个integral类型要求一个强制类型转换来赋值到一个枚举类型。显式强制类型转换在“第三章 数据类型”中定义。
5.8.4 类型非兼容性
所有余下的没有定义隐式或显式强制类型转换规则的非等价类型都是类型不兼容的。类句柄和chandle与所有其它类型都是类型不兼容的。
链接
第五章 数据声明, 主题


5.8.1 等价类型

链接
5.8 类型兼容性
SystemVerilog 3.1a语言参考手册
5.8.1 等价类型
5.8 类型兼容性

如果两个数据类型符合下列的归纳定义，那么它们是等价的。如果两个数据类型不符合下列的归纳定义，那么它们就是不等价的。

  1. 在每一个范围内，任何内建类型都等价于它本身的每一个其它的具体值。
  2. 一个简单的typedef或者重命名了一个内建的或用户定义类型的类型参数覆盖在类型标识符作用范围内等价于那个内建的或用户定义的数据类型。
Copy Code
typedef bit node;    // 'bit'与'node'是等价类型
typedef type1 type2; // 'type1'与'type2'是等价类型
  3. 一个匿名的枚举、结构体、或联合体类型在相同的声明语句中声明的变量间是等价的。
Copy Code
struct {int A; int B;} AB1, AB2; // AB1, AB2具有等价的类型
struct {int A; int B;} AB3;      // AB3与AB1在类型上不等价
  4. 针对于枚举、非压缩结构体、非压缩联合体或类的typedef等价于其本身以及在类型标识符作用范围内使用这个类型声明的变量。
Copy Code
typedef struct {int A; int B;} AB_t;
AB_t AB1;
AB_t AB2;      // AB1与AB2具有等价的类型

typedef struct {int A; int B;} otherAB_t;
otherAB_t AB3; // AB3与AB1或AB2在类型上不等价
  5. 如果压缩数组、压缩结构体、以及内建的integral类型的总位数相同，只要成员都是两态或四态，或者都是有符号或无符号的，那么它们是等价的。注意：如果压缩结构体或联合体的任意一位是四态的，那么整个结构体或联合体就被认为是四态的。
Copy Code
typedef bit signed [7:0] BYTE; // 等价于byte类型
typedef struct packed signed {bit[3:0] a, b;} uint8;
                              // 等价于byte类型
  6. 如果非压缩数组类型具有等价的元素类型并且具有相同的形状，那么它们是等价的。形状指的是数组的维数以及每一维中元素的数目，并不是真实的维数范围。
Copy Code
bit [9:0] A[0:5];
bit [1:10] B[6];
typedef bit [10:1] uint10;
uint10 C[6:1];          // A, B以及C具有等价的类型
typedef int anint[0:0]; // anint在类型上与int不等价
  7. 显式地为一个类型加入signed或unsigned修饰符不会改变类型的缺省符号，也不会产生一个不等价的类型。然而，为了能够等价，符号必须匹配。
Copy Code
typedef bit unsigned ubit; // 等价于bit的类型
  8. 应用于在一个包中声明的枚举、非压缩结构体、非压缩联合体或一个类类型的typedef总是等价于其本身，而不管类型导入的范围如何。

一个类型标识符的作用范围包括层次化的实例范围。这也就意味着内部声明了用户定义类型的每一个实例都产生了一个唯一的类型。为了在相同模块、接口、或程序的多个实例间具有类型等价性，一个类型必须在比模块、接口、或程序声明更高层次的编译单元范围内声明，或者从一个包中导入。

虽然包声明不需要在相同的编译单元内，然而下面的例子假设它们都处于一个编译单元。

Copy Code
package p1;
    typedef struct {
        int A;
    } t_1;
endpackage

typedef struct {
    int A;
} t_2;

module sub();
    import p1:t_1;
    parameter type t_3 = int;
    parameter type t_4 = int;
    typedef struct {int A;} t_5;
    t_1 v1; t_2 v2; t_3 v3; t_4 v4; t_5 v5;
endmodule

module top();
    typedef struct {int A;} t_6;
    sub #(.t_3(t_6)) s1();
    sub #(.t_3(t_6)) s2();

    initial begin
        s1.v1 = s2.v1; // 合法的 - 两个类型均来自于包p1（规则8）
        s1.v2 = s2.v2; // 合法的 - 两个类型均来自于$unit（规则4）
        s1.v3 = s2.v3; // 合法的 - 两个类型均来自于top（规则2）
        s1.v4 = s2.v4; // 合法的 - 两个类型均为int（规则1）
        s1.v5 = s2.v5; // 非法的 - 类型来自于s1和s2（规则4）
    end
endmodule
Group

5.8 类型兼容性

链接
5.8 类型兼容性


5.8.2 赋值兼容

链接
5.8 类型兼容性
SystemVerilog 3.1a语言参考手册
5.8.2 赋值兼容
5.8 类型兼容性

所有的等价类型以及所有定义了隐式强制类型转换的非等价类型都是赋值兼容的类型。例如，所有integral类型都是赋值兼容的。赋值兼容类型间的转换会由于缩减或四舍五入导致数据丢失。

兼容性可能仅存在于一个方向上。例如，一个枚举类型不需要一个强制类型转换就可以转换成integral类型，但反方向则不行。显式强制类型转换在“第三章 数据类型”以及“第七章 操作符与表达式”中定义。

Group

5.8 类型兼容性

链接
5.8 类型兼容性


5.8.3 强制转换兼容

链接
5.8 类型兼容性
SystemVerilog 3.1a语言参考手册
5.8.3 强制转换兼容
5.8 类型兼容性

所有的赋值兼容类型，加上定义了显式强制类型转换规则的非等价类型都是强制转换兼容的。例如，一个integral类型要求一个强制类型转换来赋值到一个枚举类型。显式强制类型转换在“第三章 数据类型”中定义。

Group

5.8 类型兼容性

链接
5.8 类型兼容性


5.8.4 类型非兼容性

链接
5.8 类型兼容性
SystemVerilog 3.1a语言参考手册
5.8.4 类型非兼容性
5.8 类型兼容性

所有余下的没有定义隐式或显式强制类型转换规则的非等价类型都是类型不兼容的。类句柄和chandle与所有其它类型都是类型不兼容的。

Group

5.8 类型兼容性

链接
5.8 类型兼容性


第六章 属性

链接
主题
SystemVerilog 3.1a语言参考手册
第六章 属性
主题
主题
主题 | 描述
6.1 简介（一般信息） | 在Verilog-2001中，用户可以为Verilog对象（例如模块、实例、wire等）加入命名的属性。属性还可以在扩展的SystemVerilog结构中指定，并作为BNF的一部分（参见附录A）。SystemVerilog还为属性定义了一个缺省的数据类型。
6.2 缺省属性类型 | 一个没有值的属性的缺省类型是bit，它的值为1。另外，属性接受表达式的类型。
链接
主题


6.1 简介（一般信息）

链接
第六章 属性
SystemVerilog 3.1a语言参考手册
6.1 简介（一般信息）
第六章 属性

在Verilog-2001中，用户可以为Verilog对象（例如模块、实例、wire等）加入命名的属性。属性还可以在扩展的SystemVerilog结构中指定，并作为BNF的一部分（参见附录A）。SystemVerilog还为属性定义了一个缺省的数据类型。

Group

第六章 属性

链接
第六章 属性


6.2 缺省属性类型

链接
第六章 属性
SystemVerilog 3.1a语言参考手册
6.2 缺省属性类型
第六章 属性

一个没有值的属性的缺省类型是bit，它的值为1。另外，属性接受表达式的类型。

Group

第六章 属性

链接
第六章 属性


第七章 操作符与表达式

链接
主题
SystemVerilog 3.1a语言参考手册
第七章 操作符与表达式
主题
主题
主题
描述
7.1 简介（一般信息）
SystemVerilog操作符是Verilog和C语言操作符的组合。在这两种语言中，操作数的类型和尺寸是固定的，因此操作符具有固定的类型和尺寸。SystemVerilog保持了操作符的固定类型和尺寸。这能够产生有效的编码。

Verilog不包含赋值操作符或递增及递减操作符。SystemVerilog包含了C语言的赋值操作符，例如+=，以及C语言的递增和递减操作符（++和--）。

Verilog-2001加入了有符号线网和reg变量，以及有符号文本值。对于有符号整数和无符号整数的结合规则，Verilog和C语言存在差异。SystemVerilog使用Verilog-2001的规则。
7.2 操作符语法
7.3 赋值操作符
除了简单赋值操作符（=）之外，SystemVerilog包含了C语言赋值操作符以及特殊的位级赋值操作符：+=、 -=、 *=、 /=、 %=、 &=、 |=、 ^=、 <<=、 >>=、 <<<=、 以及 >>>=。除了左侧索引表达式仅仅计算一次之外，赋值操作符在语义上等价于一个阻塞赋值。例如：
7.4 对logic和bit类型的操作
当一个二元操作符包含一个bit类型的操作数和一个logic类型的操作数的时候，结果的数据类型是logic。如果一个操作数的类型是int而另一个操作数的类型是integer的时候，那么结果的数据类型是integer。

对于!=和==操作符，如果任何一个操作数包含X或Z，那么就像Verilog-2001一样，返回一个X。如果结果被转换成bit类型（例如在一个if语句中），那么结果被转换成0。

一元缩减操作符（& ~& | ~| ^ ~^）可以应用于任何整数类型（包括压缩数组）。如果压缩类型是一个四态类型，那么操作符应该返回类型为logic的值；如果压缩类型是一个两态类型，那么返回值的类型是bit。
7.5 通配等式与通配不等式
SystemVerilog 3.1引入了如下所述的通配比较操作符。

表 7-1：通配等式与通配不等式操作符

7.6 实操作符
shortreal类型的操作数与Verilog real类型的操作数具有相同的操作限制。一元操作符++和--可以应用于类型为real和shortreal的操作数（按1.0递增或递减）。赋值操作符+=、-=、*=、/=也可以具有real和shortreal类型的操作数。

除了三元操作符中?之前的操作数外，如果任一操作数是real类型的，那么结果就是real类型的。另外，除了三元操作符中?之前的操作数外，如果任一操作数是shortreal类型的，那么结果就是shortreal类型的。

实操作数还可以用在下面的表达式中：
7.7 尺寸
一个表达式的位宽由操作数和上下文决定，它与Verilog遵从相同的规则。在SystemVerilog中，可以使用强制类型转换来设置中间值的尺寸。

在Verilog中，当一条赋值语句的左侧和右侧具有不同尺寸的时候，工具可以发布一条警告信息。使用SystemVerilog的尺寸强制转换，可以阻止掉这些警告信息。
7.8 符号
确定SystemVerilog表达式符号的规则应该与Verilog相同。通过类型转换将shortreal转换成integer应该是有符号的。
7.9 操作符优先级与关联性
操作符的优先级与关联性在表7-2中列出。最先列出的操作符具有最高优先级。

表 7-2：操作符优先级与关联性

7.10 内建方法
SystemVerilog引入了类和方法调用语法，其中一个任务或函数通过使用圆点符号（.）调用。
7.11 静态前缀
对于一个选择片来讲，选择片的“最长静态前缀”被非正式地定义为一个分析工具能够在确立完成后确定其值的最长的那一部分。当描述隐式敏感列表（参见9.2节）以及为逻辑端口的驱动描述错误条件（参见5.6 线网、reg、与logic ）的时候，我们使用这个概念。本节余下的部分定义由什么组成了一个选择片的最长静态前缀。

域选择被定义成一个层次化的名字，其中最后一个层次分割符（“.”）的右侧标识了类型为结构体或联合体的变量的一个域。域选择前缀被定义成域选择中最后一个层次分割符左侧的部分。

一个索引选择是一个单纯的索引操作。索引选择前缀或者是一个标识符或者是另外一个索引选择（在多维选择的情况下）。数组选择、位选择、部分选择、以及索引部分选择都是索引选择的例子。

静态前缀的定义是递归的并且具有如下的定义：

  1. 一个标识符是一个静态前缀
  2. 如果一个域选择前缀是一个静态前缀，那么这个域选择是一个静态前缀
  3. 如果一个索引选择前缀是一个静态前缀并且选择表达式是一个常量表达式，那么这个索引选择是一个静态前缀。

最长静态前缀的定义如下：

  1. 如果一个标识符不是一个静态前缀表达式的域选择前缀或索引选择前缀，那么它是一个最长静态前缀
  2. 如果一个域选择不是一个静态前缀表达式的域选择前缀或索引选择前缀，那么它是一个最长静态前缀
  3. 如果一个索引选择不是一个静态前缀表达式的域选择前缀或索引选择前缀，那么它是一个最长静态前缀

例子：

7.12 串联
与Verilog一样，花括号（{ }）被用来表示串联。串联被当作一个压缩的位向量来看待。它可以使用在一条赋值语句或一个表达式的左侧。
7.13 非压缩数组表达式
表达式中也可以使用花括号来为非压缩数组赋值。与C语言不同的是，表达式必须在元素与元素之间达到匹配，并且花括号必须匹配数组维数。在数组中对应元素类型的赋值关联文中，每一个表达式的元素都会被计算。这也就意味着，与上面的相似赋值不同，下面的例子不会发布尺寸警告信息：
7.14 结构体表达式
结构体表达式（压缩的和非压缩的）可以使用花括号和逗号由成员表达式构建，其中成员表达式以成员声明的顺序排列。复制操作符可以用来设置准确的成员数目。每一个成员表达式应该在对结构体中对应成员类型赋值的关联文中计算。结构体表达式也可以使用成员的名字来构建。
7.15 标签联合体表达式与成员访问
7.16 集合表达式
非压缩结构体和数组变量、文本值、以及表达式都可以作为集合表达式使用。一个非压缩数组的多维分片也可以用作集合表达式。

集合表达式可以在通过赋值语句、通过一个端口、或作为任务或函数的自变量进行拷贝。集合表达式也可以使用相等或不等操作符进行比较。为了进行拷贝或比较，集合表达式的类型必须是赋值兼容的。参见5.8.2 赋值兼容 。
7.17 操作符过载
有多种算术算法可能非常有用：饱和算法，任意尺寸的浮点数运算，进位保留算法等。使用普通的算术操作符而不是依赖于函数调用有利于代码的可读性。
7.18 流操作符（压缩/非压缩）
在3.16节描述了位流强制类型转换，当转换操作可以仅仅使用一个强制类型转换方便地表达，并且位流的特定顺序并不重要的时候，这种方法最为有用。然而，有时位流需要匹配于一个特定的组织形式。流操作符将位流类型（参见3.16节）以用户指定的顺序压缩到一个位序列当中。当流操作符使用在表达式左侧的时候，它执行相反的操作：将位流解压缩成一个或多个变量。如果正在被压缩的数据包含任何四态类型，那么压缩操作的结果是四态类型，否则，结果为两态类型。将四态类型的位流解压缩成两态类型变量是通过一个向两态变量的强制类型转换实现的，反之亦然。

位流串联的语法如下：
7.19 条件操作符
7.20 集合成员资格
SystemVerilog支持单一值集合以及集合成员资格操作符。

集合成员资格操作符的语法如下：
链接
主题


7.1 简介（一般信息）

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.1 简介（一般信息）
第七章 操作符与表达式

SystemVerilog操作符是Verilog和C语言操作符的组合。在这两种语言中，操作数的类型和尺寸是固定的，因此操作符具有固定的类型和尺寸。SystemVerilog保持了操作符的固定类型和尺寸。这能够产生有效的编码。

Verilog不包含赋值操作符或递增及递减操作符。SystemVerilog包含了C语言的赋值操作符，例如+=，以及C语言的递增和递减操作符（++和--）。

Verilog-2001加入了有符号线网和reg变量，以及有符号文本值。对于有符号整数和无符号整数的结合规则，Verilog和C语言存在差异。SystemVerilog使用Verilog-2001的规则。

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.2 操作符语法

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.2 操作符语法
第七章 操作符与表达式
Copy Code
assignment_operator ::=         // 引用自附录A.6.2
    = | += | -= | *= | /= | %= | &= | |= | ^= | <<= | >>= | <<<= | >>>=

conditional_expression ::=      // 引用自附录A.8.3
    cond_predicate ? {attribute_instance} expression : expression

unary_operator ::=              // 引用自附录A.8.6
    + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~

binary_operator ::=
    + | - | * | / | % | == | != | === | !== | =?= | !?= | && | || | **
    | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<

inc_or_dec_operator ::= ++ | --

unary_module_path_operator ::=
    ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~

binary_module_path_operator ::=
    == | != | && | || | & | | | ^ | ^~ | ~^

语法7-1 — 操作符语法（摘录自附录A）

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.3 赋值操作符

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.3 赋值操作符
第七章 操作符与表达式

除了简单赋值操作符（=）之外，SystemVerilog包含了C语言赋值操作符以及特殊的位级赋值操作符：+=、 -=、 *=、 /=、 %=、 &=、 |=、 ^=、 <<=、 >>=、 <<<=、 以及 >>>=。除了左侧索引表达式仅仅计算一次之外，赋值操作符在语义上等价于一个阻塞赋值。例如：

Copy Code
a[i] += 2; // 与a[i] = a[i] + 2;相同

在SystemVerilog中，假如一个表达式不包含一个时间控制，那么它可以包含一个阻塞赋值。注意：这样的赋值必须使用圆括号包围起来以便避免一些基本错误，例如将a==b写为a=b，或者将a!=b写为a|=b。

Copy Code
if ((a=b))
    b = (a+=1);
a = (b = (c = 5));

这样的一个赋值表达式的语义与一个计算右侧值，将右侧值强制转换成左侧数据类型，然后更新左侧值并返回这个值的函数相同。返回值的数据类型与左侧数据类型相同。如果左侧是一个串联，那么返回的类型应该是一个无符号integral值，它的位长度等于其操作数位长度之和。

在一个事件表达式、过程连续赋值中的表达式、或者不在一个过程语句内的表达式中包含赋值操作符是非法的。

SystemVerilog包含C语言的递增和递减赋值操作符：++i，--i，i++，以及i--。当它们使用在表达式中的时候，这些操作符不需要使用圆括号包围。这些递增和递减赋值操作符的操作与阻塞赋值一样。

赋值操作相对于表达式中任何其它操作的顺序是未定义的。只要同时写一个变量、在一个integral表达式中读或写一个变量、或者在实现时不能保证计算顺序的关联文中的时候，在实现时就可以发布一个警告。在下面的例子中：

Copy Code
i = 10;
j = i++ + (i=i-1);

根据递增和赋值语句的相对顺序，在执行之后，j的值可能是18、19、或20。

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.4 对logic和bit类型的操作

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.4 对logic和bit类型的操作
第七章 操作符与表达式

当一个二元操作符包含一个bit类型的操作数和一个logic类型的操作数的时候，结果的数据类型是logic。如果一个操作数的类型是int而另一个操作数的类型是integer的时候，那么结果的数据类型是integer。

对于!=和==操作符，如果任何一个操作数包含X或Z，那么就像Verilog-2001一样，返回一个X。如果结果被转换成bit类型（例如在一个if语句中），那么结果被转换成0。

一元缩减操作符（& ~& | ~| ^ ~^）可以应用于任何整数类型（包括压缩数组）。如果压缩类型是一个四态类型，那么操作符应该返回类型为logic的值；如果压缩类型是一个两态类型，那么返回值的类型是bit。

Copy Code
int i;
bit b = &i;
integer j;
logic c = &j;
Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.5 通配等式与通配不等式

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.5 通配等式与通配不等式
第七章 操作符与表达式

SystemVerilog 3.1引入了如下所述的通配比较操作符。

表 7-1：通配等式与通配不等式操作符

操作符 | 用法 | 描述
=?= | a =?= b | a等于b，X和Z的作用像通配符一样
!?= | a !?= b | a不等于b，X和Z的作用像通配符一样

通配相等操作符（=?=）和通配不等操作符（!?=）将一个指定位置处的X和Z值当作是一个通配符。在进行比较的表达式中，通配符匹配于任意位值（0，1，Z，或X）。

这些操作符一位一位地比较操作数，并返回一个1位的自决结果。如果通配相等/不等操作符的操作数具有不同的位宽，那么操作数就像条件相等/不等操作符中使用的规则一样地扩展操作数。如果关系操作的结果为“真”，那么操作符产生一个1。如果关系操作的结果是“否”，那么它产生一个0。

对于SystemVerilog中三种类型的等式（和不等式），当它们的操作数中包含未知值（X或Z）的时候，它们的行为是不同的。如果操作数中包含X或Z，那么==和!=操作的结果是X。而===和!==明确地检查四态值，因此，X和Z应该或者匹配或者不匹配，结果永远也不会是X。=?=和!?=操作符将X或Z当作是可以匹配任意值得通配符，因此，它们也永远不产生X。

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.6 实操作符

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.6 实操作符
第七章 操作符与表达式

shortreal类型的操作数与Verilog real类型的操作数具有相同的操作限制。一元操作符++和--可以应用于类型为real和shortreal的操作数（按1.0递增或递减）。赋值操作符+=、-=、*=、/=也可以具有real和shortreal类型的操作数。

除了三元操作符中?之前的操作数外，如果任一操作数是real类型的，那么结果就是real类型的。另外，除了三元操作符中?之前的操作数外，如果任一操作数是shortreal类型的，那么结果就是shortreal类型的。

实操作数还可以用在下面的表达式中：

Copy Code
str.realval       // 结构体或联合体成员
realarray[intval] // 数组元素
Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.7 尺寸

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.7 尺寸
第七章 操作符与表达式

一个表达式的位宽由操作数和上下文决定，它与Verilog遵从相同的规则。在SystemVerilog中，可以使用强制类型转换来设置中间值的尺寸。

在Verilog中，当一条赋值语句的左侧和右侧具有不同尺寸的时候，工具可以发布一条警告信息。使用SystemVerilog的尺寸强制转换，可以阻止掉这些警告信息。

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.8 符号

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.8 符号
第七章 操作符与表达式

确定SystemVerilog表达式符号的规则应该与Verilog相同。通过类型转换将shortreal转换成integer应该是有符号的。

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.9 操作符优先级与关联性

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.9 操作符优先级与关联性
第七章 操作符与表达式

操作符的优先级与关联性在表7-2中列出。最先列出的操作符具有最高优先级。

表 7-2：操作符优先级与关联性

() [] :: . | 左
+ - ! ~ & ~& | ~| ^ ~^ ^~ ++ -- (一元) | 右
** | 左
* / % | 左
+ - (二元) | 左
<< >> <<< >>> | 左
< <= > >= inside dist | 左
== != === !== =?= !?= | 左
& (二元) | 左
^ ~^ ^~ (二元) | 左
| (二元) | 左
&& | 左
|| | 左
?: (条件操作符) | 右
–> | 右
= += -= *= /= %= &= ^= |= <<= >>= <<<= >>>= := :/ <= | 无
{} {{}} | 串联
Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.10 内建方法

链接
第七章 操作符与表达式, 主题
SystemVerilog 3.1a语言参考手册
7.10 内建方法
第七章 操作符与表达式 | 主题

SystemVerilog引入了类和方法调用语法，其中一个任务或函数通过使用圆点符号（.）调用。

Copy Code
object.task_or_function()

object唯一地识别了任务或函数操作的数据。因此，为了加入传统上只能通过系统任务或函数才能实现的功能，方法的概念被自然地扩展到内建类型。与系统任务不同，内建方法不使用$作为前缀，因为它们不需要特殊前缀来避免与用户定义标识符的冲突。这样，方法语法对语言进行了扩展而无需加入新的关键字，也不会将全局命名空间与系统任务相混淆。

与系统任务不同，内建方法不会被用户通过PLI任务重新定义。因此，对内建方法调用来说，只有不会被用户重新定义的函数是一个很好的候选。

通常，当一个特定的功能适用于所有数据类型，或者适用于一个特定数据类型的时候，相对于系统任务来说，内建方法是首选的。例如：

Copy Code
dynamic_array.size, associative_array.num, and string.len

这些内建方法具有相似的概念，然而，它们却代表不同的东西。一个动态数组具有一个尺寸、一个联合数组包含指定书目的元素，一个字符串具有一个指定的长度。如果对它们使用相同的系统任务，例如$length，则会缺乏清晰性和直观性。

内建方法只能与一个特定数据类型关联。因此，如果某些功能具有一个简单的边带效应（例如$stop或$reset）或者它不针对特定的数据操作（例如，$random），那么必须使用一个系统任务。

当一个函数或任务内建方法调用没有指定参数的时候，在任务/函数名字之后的空括号，()，是可选的。对于要求参数的任务或函数，如果所有的参数都指定为缺省值，那么这个规则也是适用的。对于一个方法而言，这条规则使得简单调用就好像是对象或内建类型的属性一样。在10.4.5节中为函数和任务定义了相似的规则。

Group

第七章 操作符与表达式

主题
主题 | 描述
7.10.1 内建包 | SystemVerilog提供了一个内建的包，它包含了系统类型（例如类）、变量、任务和函数。用户不能在内建包中插入其它的声明。 内建包被隐含地导入到每一个编译单元的作用范围内（参见18.3节）。因此，内建包中的声明在所有范围内直接有效（就像系统任务和函数一样），除非他们被用户代码重新定义。
链接
第七章 操作符与表达式, 主题


7.10.1 内建包

链接
7.10 内建方法
SystemVerilog 3.1a语言参考手册
7.10.1 内建包
7.10 内建方法

SystemVerilog提供了一个内建的包，它包含了系统类型（例如类）、变量、任务和函数。用户不能在内建包中插入其它的声明。 内建包被隐含地导入到每一个编译单元的作用范围内（参见18.3节）。因此，内建包中的声明在所有范围内直接有效（就像系统任务和函数一样），除非他们被用户代码重新定义。

Copy Code
built_in_data_type ::= [std::] data_type_identifier  // 未包含在附录A中
built_in_function_call ::= [std::] built_in_identifier // 未包含在附录A中

包名字std后面紧跟着范围解析操作符::可以用来明确地访问内建包中的名字。例如：

Copy Code
std::sys_task(); // 明确调用系统提供的sys_task

与系统任务和函数不同，内建包中的任务和函数不需要使用$前缀来避免与用户定义标识符的冲突。这种机制能够对语言以后向兼容的方式进行功能扩展，而无需加入额外的关键字或干扰本地命名空间。

Group

7.10 内建方法

链接
7.10 内建方法


7.11 静态前缀

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.11 静态前缀
第七章 操作符与表达式

对于一个选择片来讲，选择片的“最长静态前缀”被非正式地定义为一个分析工具能够在确立完成后确定其值的最长的那一部分。当描述隐式敏感列表（参见9.2节）以及为逻辑端口的驱动描述错误条件（参见5.6 线网、reg、与logic ）的时候，我们使用这个概念。本节余下的部分定义由什么组成了一个选择片的最长静态前缀。

域选择被定义成一个层次化的名字，其中最后一个层次分割符（“.”）的右侧标识了类型为结构体或联合体的变量的一个域。域选择前缀被定义成域选择中最后一个层次分割符左侧的部分。

一个索引选择是一个单纯的索引操作。索引选择前缀或者是一个标识符或者是另外一个索引选择（在多维选择的情况下）。数组选择、位选择、部分选择、以及索引部分选择都是索引选择的例子。

静态前缀的定义是递归的并且具有如下的定义：

  1. 一个标识符是一个静态前缀
  2. 如果一个域选择前缀是一个静态前缀，那么这个域选择是一个静态前缀
  3. 如果一个索引选择前缀是一个静态前缀并且选择表达式是一个常量表达式，那么这个索引选择是一个静态前缀。

最长静态前缀的定义如下：

  1. 如果一个标识符不是一个静态前缀表达式的域选择前缀或索引选择前缀，那么它是一个最长静态前缀
  2. 如果一个域选择不是一个静态前缀表达式的域选择前缀或索引选择前缀，那么它是一个最长静态前缀
  3. 如果一个索引选择不是一个静态前缀表达式的域选择前缀或索引选择前缀，那么它是一个最长静态前缀

例子：

Copy Code
localparam p = 7;
reg [7:0] m[5:1][5:1];
integer i;
m[1][i] // 最长的静态前缀是m[1]
m[p][1] // 最长的静态前缀是m[p][1]
m[i][1] // 最长的静态前缀是m
Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.12 串联

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.12 串联
第七章 操作符与表达式

与Verilog一样，花括号（{ }）被用来表示串联。串联被当作一个压缩的位向量来看待。它可以使用在一条赋值语句或一个表达式的左侧。

Copy Code
logic log1, log2, log3;
{log1, log2, log3} = 3'b111;
{log1, log2, log3} = {1'b1, 1'b1, 1'b1}; // 与3'b111具有相同的效果

如果一条赋值语句一侧的串联宽度与另外一侧的表达式的宽度不同，那么软件工具可以产生一个警告信息。对于下面的例子，软件工具可以给出尺寸不匹配的警告信息。

Copy Code
bit [1:0] packedbits = {32'b1,32'b1}; // 右侧是64位
int i = {1'b1, 1'b1};                 // 右侧是2位

参见2.7 数组文本和2.8 结构体文本节中有关数组和结构体初始化的信息。

SystemVerilog增强了串联操作，它允许字符串类型变量的串联。一般情况下，如果一个串联操作的任何一个操作数是字符串类型，那么串联就被当作是字符串，并且所有其它自变量都被隐式转换成字符串类型（参见3.7 string数据类型中的描述）。字符串串联只能作为表达式使用，不能使用在赋值语句的左侧。

Copy Code
string hello = "hello";
string s;
s = {hello, " ", "world"};
$display( "%s\n", s );     // 显示成'hello world'

s = {s, " and goodbye"};
$display("%s\n", s);       // 显示成'hello world and goodbye'

复制操作符（也被称为乘串联）中的花括号还可以与字符串类型的变量一起使用。在字符串复制的情况下，可以使用非常量的乘数。

Copy Code
int n = 3;
string s = {n{"boo "}};
$display("%s\n", s);       // 显示成'boo boo boo '

注意：与位串联不同，字符串串联或复制的结果不会被缩减。相反，目的变量（具有字符串类型）会调整尺寸以便容纳结果字符串。

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.13 非压缩数组表达式

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.13 非压缩数组表达式
第七章 操作符与表达式

表达式中也可以使用花括号来为非压缩数组赋值。与C语言不同的是，表达式必须在元素与元素之间达到匹配，并且花括号必须匹配数组维数。在数组中对应元素类型的赋值关联文中，每一个表达式的元素都会被计算。这也就意味着，与上面的相似赋值不同，下面的例子不会发布尺寸警告信息：

Copy Code
bit unpackedbits[1:0] = {1,1}; // 不会发布警告信息，因为bit可以被设置成1
int unpackedints[1:0] = {1'b1, 1'b1}; // 不会发布警告信息，因为int可以被
                                      // 设置成1'b1

乘串联的语法也可以使用在非压缩数组表达式中。每一个复制均代表数组中的一维。

Copy Code
unpackedbits = {2{y}};         // 与{y, y}相同
int n[1:2][1:3] = {2{{3{y}}}}; // 与{{y,y,y},{y,y,y}}相同

当花括号使用在一条赋值语句的关联文中的时侯，由SystemVerilog确定花括号的关联文。如果花括号使用在一条对非压缩数组赋值的关联文中，那么花括号代表一个非压缩数组文本或表达式。在赋值语句右侧关联文之外，花括号必须与一个显式的强制类型转换一起使用以便将它与串联区分开来。

注意：一个集合表达式不能用作赋值的目标。下面的例子被认为是非法的：

Copy Code
logic [2:0] a[1:0];
logic [2:0] b, c;
always {b,c} = a; // 非法赋值，花括号不能被解析成一个非压缩数组表达式

有时我们希望将数组元素设置成某一个值而无需知道数组到底有多少个成员。这种方式可以使用default关键字来实现：

Copy Code
initial unpackedints = {default:2}; // 将数组元素设置为2

对于更多的结构体数组，指定一个或多个匹配类型键值非常有用，正如下面的结构体表达式所演示的那样。

Copy Code
struct {
    int a;
    time b;
} abkey[1:0];

abkey = {{a:1, b:2ns}, {int:5, time:$time}};

当花括号包含了一个类型键值或缺省键值的时候，无论对于压缩数组类型还是非压缩数组类型，花括号都不应被解释成串联。

非压缩数组的匹配规则如下：

  • index:value显式地为键入的数组索引指定一个值。这个值在为被索引的元素赋值的关联文中计算，并应该被强制转换成元素的类型。在单个数组表达式中多次为相同索引的元素指定值是错误的。
  • 对于type:value，如果非压缩数组的元素或子数组的类型等价于type指定的类型，那么每一个元素或子数组都应被设置成value指定的值。这个值必须能够被强制转换成数组元素或子数组类型。如果非压缩数组是多维的，那么需要使用本节描述的规则以及类型和缺省键值递归地深入到每一个子数组。另外，如果非压缩数组是一个结构体数组，那么需要使用结构体表达式规则以及类型和缺省键值递归地深入到数组的每一个元素。如果多个类型匹配于相同的元素，那么使用最后一个值。
  • 对于没有被本节前面几条规则所涵盖的非压缩数组元素，由default:value指定它们的值。这个值在对由default所涵盖的每一个元素的赋值关联文中计算，并且必须能够被强制转换成数组元素类型。

每一个元素都应该被其中的一条规则所涵盖。

如果类型键值、缺省键值、或复制操作符被用于一个具有边带效应的表达式，那么表达式的计算次数是未定义的。

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.14 结构体表达式

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.14 结构体表达式
第七章 操作符与表达式

结构体表达式（压缩的和非压缩的）可以使用花括号和逗号由成员表达式构建，其中成员表达式以成员声明的顺序排列。复制操作符可以用来设置准确的成员数目。每一个成员表达式应该在对结构体中对应成员类型赋值的关联文中计算。结构体表达式也可以使用成员的名字来构建。

Copy Code
module mod1;

typedef struct {
    int x;
    int y;
} st;

st s1;

int k = 1;

initial begin
    #1 s1 = {1, 2+k};     // 通过位置构建结构体表达式
    #1 $display(s1.x, s1.y);
    #1 s1 = {x:2, y:3+k}; // 通过名字构建结构体表达式
    #1 $display(s1);
    #1 $finish;
end

endmodule

有时我们希望将结构体成员设置成某一个值而无需知道结构体到底有多少个成员或者成员的具体名字是什么。这种方式可以使用default关键字来实现：

Copy Code
initial s1 = {default:2}; // 将x和y设置成2

我们也可以使用{member:value}或{data_type: default_value}这样的语法：

Copy Code
ab abkey[1:0] = {{a:1, b:1.0}, {int:2, shortreal:2.0}};

注意：default关键字可以应用于嵌套结构体中的成员或结构体中非压缩数组的元素。事实上，它可以沿着嵌套深入到其中的内建类型或压缩数组。

Copy Code
struct {
    int A;
    struct {
        int B, C;
    } BC1, BC2;
}

ABC = {A:1, BC1:{B:2, C:3}, BC2:{B:4,C:5}};
DEF = {default:10};

为了处理成员具有不同类型的问题，我们可以使用一个类型作为键值。它会过载该类型成员的缺省值：

Copy Code
typedef struct {
    logic [7:0] a;
    bit b;
    bit signed [31:0] c;
    string s;
} sa;

sa s2;

initial begin
    s2 = {int:1, default:0, string:""}; // 除了将位数组设置成1以及将字符串设置成
                                        // ""之外，所有其它成员均设置成0。
end

类似的，我们可以设置单个成员以便过载由default和类型缺省设置的值：

Copy Code
initial #10 s1 = {default:'1, s:""}; // 除了s设置为""之外，所有其它成员均设置成1

当花括号使用在一条赋值语句的关联文中的时侯，由SystemVerilog确定花括号的关联文。如果花括号使用在一条对非压缩结构体赋值的关联文中，那么花括号代表一个非压缩数组文本或表达式。在对一个集合类型赋值的关联文之外，花括号必须与一个显式的强制类型转换一起使用以便将它与串联区分开来。当花括号包含了一个标签、类型或default键值的时候，无论对于压缩结构体类型还是非压缩结构体类型，花括号都不应被解释成串联。

匹配规则如下：

  • member:value：为结构体的一个命名成员显式地指定一个确定的值。这个命名成员必须位于结构体的顶层，也就是说位于某个子结构体中具有相同名字的成员不会被设置。这个指定的值必须能够被强制转换到成员类型，并在为命名成员赋值的关联文中计算，否则会产生一个错误。
  • type:value：如果结构体中的一个域没有使用上述的域名键值设置，那么可以使用type:value为结构体中等价于指定类型的域指定一个确切的值。如果指定了多个相同的类型键值，那么使用最后一个类型键值。这个值在为匹配类型成员赋值的关联文中计算。
  • default:value：应用于没有通过成员名或类型键值匹配，并且不是结构体或非压缩数组的成员。值在对通过default匹配的成员的每一个赋值中计算，并且必须能够被强制转换到成员的类型，否则会产生一个错误。对于未匹配的结构体成员，类型和default说明符根据本节中的规则递归地应用到每一个子结构体的成员。对于未匹配的非压缩数组成员，类型和default说明符根据非压缩数组规则应用到这个数组。

每一个成员都必须被其中的一个规则所涵盖。

如果一个类型键值、default键值、或者复制操作符被使用在一个具有副作用的表达式中，那么表达式的计算次数是为定义的。

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.15 标签联合体表达式与成员访问

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.15 标签联合体表达式与成员访问
第七章 操作符与表达式
Copy Code
expression ::=     // 引用自附录A.8.3
    ...
  | tagged_union_expression

tagged_union_expression ::=
    tagged member_identifier [expression]

语法 7-2 — 标签联合体语法（摘录自附录A）

一个标签联合体表达式（压缩的或非压缩的）可以使用关键字tagged紧跟着一个标签联合体标识符，然后再跟着一个代表对应成员值的表达式来表示。对于void类型的成员，成员值表达式被忽略。

例子：

Copy Code
typedef union tagged {
    void Invalid;
    int Valid;
} VInt;

VInt vi1, vi2;

vi1 = tagged Valid (23+34); // 产生Valid int
vi2 = tagged Invalid;       // 产生一个Invalid值

在下面的标签联合体表达式中，花括号内的表达式是结构体表达式（参见7.14 结构体表达式 ）。

Copy Code
typedef union tagged {
    struct {
        bit [4:0] reg1, reg2, regd;
    } Add;
    union tagged {
        bit [9:0] JmpU;
        struct {
            bit [1:0] cc;
            bit [9:0] addr;
        } JmpC;
    } Jmp;
} Instr;

Instr i1, i2;

// 产生具有3个寄存器域的Add指令
i1 = (e
    ? tagged Add {e1, 4, ed}; // 通过位置设置结构体成员
    ? tagged Add {reg2:e2, regd:3, reg1:19}); // 通过名字（顺序无关的）

// 产生一个具有“无条件”子操作码的Jump指令
i1 = tagged Jmp (tagged JmpU 239);

// 产生一个具有“有条件”子操作码的Jump指令
i2 = tagged Jmp (tagged JmpC {2, 83}); // 通过位置设置内层结构体
i2 = tagged Jmp (tagged JmpC {cc:2, addr:83}); // 通过名字设置内层结构体

标签联合体表达式的类型必须能够从它的上下文中获知（例如，使用在为类型已知变量赋值的语句的右侧、具有一个强制类型转换、或者是使用在一个已知类型的另外一个表达式中）。表达式计算成该类型的标签联合体的值。标签联合体表达式可以执行完全静态的类型检查：tagged关键字之后的成员名字必须具有表达式的类型，并且成员表达式必须具有对应的成员类型。

一个未初始化的标签联合体类型的变量应该是未定义的（包括标签位）。标签联合体变量可以使用标签联合体表达式初始化，只要成员值的表达式具有合法的成员类型。

标签联合体的成员可以使用通常的点号来读取或赋值。这样的访问需要完全的类型检查，也就是说，读取或赋值的值必须与当前的标签一致。通常，这要求运行时的检查。试图读取或赋值一个类型与标签不一致的值会导致一个运行时错误。

只要指令变量instr当前具有Add标签，那么下面的例子就是合法的：

Copy Code
x = i1.Add.reg1;
i1.Add = {19, 4, 3};
i1.Add.reg2 = 4;
Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.16 集合表达式

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.16 集合表达式
第七章 操作符与表达式

非压缩结构体和数组变量、文本值、以及表达式都可以作为集合表达式使用。一个非压缩数组的多维分片也可以用作集合表达式。

集合表达式可以在通过赋值语句、通过一个端口、或作为任务或函数的自变量进行拷贝。集合表达式也可以使用相等或不等操作符进行比较。为了进行拷贝或比较，集合表达式的类型必须是赋值兼容的。参见5.8.2 赋值兼容 。

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.17 操作符过载

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.17 操作符过载
第七章 操作符与表达式

有多种算术算法可能非常有用：饱和算法，任意尺寸的浮点数运算，进位保留算法等。使用普通的算术操作符而不是依赖于函数调用有利于代码的可读性。

Copy Code
overload_declaration ::=  // 引用自附录A.2.8
    bind overload_operator function data_type function_identifier (overload_proto_formals);

overload_operator ::= + | ++ | – | –– | * | ** | / | % | == | != | < | <= | > | >= | =

overload_proto_formals ::= data_type {, data_type}

语法 7-3 — 操作符重载语法（摘录自附录A）

过载声明使得算术操作符能够应用于一般情况下它们不能使用的数据类型，例如非压缩结构体。它不会改变操作符原本的含义，也就是说，当使用操作符过载的时候，原来的代码不会改变其运算行为。

过载声明将一个操作符链接到一个函数原型。在使用时，首先检查函数自变量是否匹配，然后再检查结果类型是否匹配。多个函数可以具有相同的自变量及不同的返回值。如果操作符使用在一个自决关联文中，而且不存在一个期望的返回类型，那么必须使用强制类型转换来选择正确的函数。类似地，如果由于嵌套操作符而导致可能具有多个期望的类型，并且可以与多于一个函数相匹配，那么也必须使用强制类型转换来选择正确的函数。

一个期望的结果类型存在于下列任意一个关联文中：

  • 一条赋值语句或赋值表达式的右侧
  • 一个任务或函数调用的真实输入参数
  • 一个模块、接口或程序的输入端口连接
  • 一个模块、接口、程序或类的真实参数
  • 具有明确比较的关系操作符
  • 在一个强制类型转换中

例如，假定float是一个结构体类型：

Copy Code
typedef struct {
    bit sign;
    bit [3:0] exponent;
    bit [10:0] mantissa;
} float;

通过调用下述过载声明中所指示的函数，+操作符能够应用于这个结构体。

Copy Code
bind + function float faddif(int, float);
bind + function float faddfi(float, int);
bind + function float faddrf(real, float);
bind + function float faddrf(shortreal, float);
bind + function float faddfr(float, real);
bind + function float faddfr(float, shortreal);
bind + function float faddff(float, float);
bind + function float fcopyf(float);     // 一元操作符 +
bind + function float fcopyi(int);       // 一元操作符 +
bind + function float fcopyr(real);      // 一元操作符 +
bind + function float fcopyr(shortreal); // 一元操作符 +

float A, B, C, D;
assign A = B + C;   // 等价于A = faddff(B, C);
assign D = A + 1.0; // 等价于A = faddfr(A, 1.0);

根据过载表达式中等价的自变量类型，过载声明将+操作符链接到每一个函数原型。通常，这种过载需要自变量具有精确的类型匹配。然而，一个例外是：如果真实参数具有integral类型，并且只有一个函数原型具有对应的integral类型的自变量，那么真实参数会被隐式地强制转换到原型中的类型。

注意：函数原型不需要精确地匹配于真实的函数声明。如果没有，那么在调用函数的时候应用普通的隐式强制类型转换。例如，fcopyi 函数可以被定义成具有一个int类型的自变量：

Copy Code
function float fcopyi (int i);
    float o;

    o.sign = i[31];
    o.exponent = 0;
    o.mantissa = 0;
    …
    return o;
endfunction

对赋值操作符的过载也会过载隐式赋值或强制类型转换。Here these are using the same functions as the unary +.

Copy Code
bind = function float fcopyi(int);       // 将int强制转换成float
bind = function float fcopyr(real);      // 将real强制转换成float
bind = function float fcopyr(shortreal); // 将shortreal强制转换成float

可以被过载的操作符有算术操作符、关系操作符、以及赋值操作符。注意，在这里从float到float的赋值操作符不能被过载，因为这种赋值本来就是合法的。类似的，在float之间的相等和不等操作符也不能被过载。

对于0或1来说，我们不能假定它的格式，所以用户不能依靠减法来得出是否相等的结论，也不能使用加法来获得递增的操作结果。类似地，对于正数或负数也不能假定它的格式，因此，比较操作必须被显式地编码。

诸如+=之类的赋值操作符从连续的+和=操作符自动构建，其中，=操作符具有标准含义。例如：

Copy Code
float A, B;

bind + function float faddff(float, float);

always @(posedge clock) A += B;  // 等价于A = A + B

过载声明的作用范围和可视性与数据声明遵从相同的搜索规则。在过载声明的可视范围内，过载声明必须在其使用之前声明。The function bound by the overload declaration uses the same scope search rules as a function enable from the scope where the operator is invoked.

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.18 流操作符（压缩/非压缩）

链接
第七章 操作符与表达式, 主题
SystemVerilog 3.1a语言参考手册
7.18 流操作符（压缩/非压缩）
第七章 操作符与表达式 | 主题

在3.16节描述了位流强制类型转换，当转换操作可以仅仅使用一个强制类型转换方便地表达，并且位流的特定顺序并不重要的时候，这种方法最为有用。然而，有时位流需要匹配于一个特定的组织形式。流操作符将位流类型（参见3.16节）以用户指定的顺序压缩到一个位序列当中。当流操作符使用在表达式左侧的时候，它执行相反的操作：将位流解压缩成一个或多个变量。如果正在被压缩的数据包含任何四态类型，那么压缩操作的结果是四态类型，否则，结果为两态类型。将四态类型的位流解压缩成两态类型变量是通过一个向两态变量的强制类型转换实现的，反之亦然。

位流串联的语法如下：

Copy Code
streaming_expression ::= {stream_operator [slice_size] stream_concatenation}
                                                          // 引用自附录A.8.1

stream_operator ::= >> | <<

slice_size ::= ps_type_identifier | constant_expression

stream_concatenation ::= {stream_expression{, stream_expression}}

stream_expression ::= expression [with [array_range_expression]]

array_range_expression ::=
    expression
  | expression : expression
  | expression +: expression
  | expression -: expression

primary ::=
    ...
  | streaming_expression

语法 7-4—位流串联语法（摘录自附录A）

流操作符决定了数据位流化的顺序：>>使得数据以从左到右的顺序位流化，而<<使得数据以从右到左的顺序位流化。如果指定了slice-size（分片尺寸），那么数据首先被分割成具有特定位数目的分片，然后这些分片以特定的顺序位流化。如果没有指定slice-size，那么缺省尺寸为1（或bit）。如果分片的时候最后一个分片小于设定的分片宽度，那么不会添加填充位。

例如：

Copy Code
int j = {"A", "B", "C", "D"};

{>> {j}}               // 产生流 "A" "B" "C" "D"
{<< byte{j}}           // 产生流 "D" "C" "B" "A" (小字节顺序)
{<< 16{j}}             // 产生流 "C" "D" "A" "B"
{<< {8'b0011_0101}}    // 产生流 'b1010_1100 (位反转)
{<< 4{6'b11_0101}}     // 产生流 'b0101_11
{>> 4{6'b11_0101}}     // 产生流 'b1101_01 (相同)
{<< 2{{<< {4'b1101}}}} // 产生流 'b1110

流操作符直接操作于integral类型和流。当应用于非压缩集合类型（例如非压缩数组、非压缩结构体、或类）的时候，它们会以深度最先的顺序递归地遍历数据直到得到单个integral类型。一个多维压缩数组会被当作单个integral类型，然而压缩条目的非压缩数组会使得每一个压缩条目被单独位流化。流操作符只能处理位流类型，处理任何其它类型都会产生一个错误。

压缩操作的结果可以直接赋值到任何位流类型的变量。如果赋值左侧代表一个固定尺寸的变量并且流尺寸大于变量的尺寸，那么会产生一个错误。如果变量的尺寸大于流尺寸，那么流会向左调整并在右侧填充0。如果左侧代表一个动态尺寸的变量（例如队列或动态数组），那么变量会重新调整尺寸以便容纳整个流。如果调整后的变量尺寸大于流的尺寸，那么流会向左调整并在右侧填充0。流不是一个integral类型的值；为了在表达式中使用，需要一个强制类型转换。

解压缩操作在右侧可以接受任何位流类型，包括一个流。右侧的数据可以具有比解压缩操作所能容纳的位数更多的位数。然而，如果需要的位数比右侧表达式所能提供的位数更多的话，则会产生一个错误。

例如：

Copy Code
int a, b, c;
logic [10:0] up[3:0];
logic [11:1] p1, p2, p3, p4;

bit [96:1] y = {>>{a, b, c}};  // 正确：压缩a, b, c
int j = {>>{a, b, c}};         // 错误：j具有32位 < 96位
bit [99:0] d = {>>{a, b, c}};  // 正确：d被填充4位
{>>{a, b, c}} = 23'b1;         // 错误：流中的位数太少
{>>{a, b, c}} = 96'b1;         // 正确：解压缩后a = 0, b = 0, c = 1
{>>{a, b, c}} = 100'b1;        // 正确：结果与上一个例子相同（有四位未读）
{>>{p1, p2, p3, p4}} = up;     // 正确：解压缩后 p1 = up[3], p2 = up[2],
                               //                p3 = up[1], p4 = up[0]
Group

第七章 操作符与表达式

主题
主题 | 描述
7.18.1 将动态尺寸的数据位流化 | 如果解压缩操作包含了庞大的动态尺寸类型，那么解压缩过程是很复杂的（就像强制类型转换中一样）：第一个动态尺寸条目被重新调整尺寸以便容纳流中所有的有效数据（排除了后续的固定尺寸条目）。对于仅仅包含了一个动态尺寸数据条目的流来说，采用这种机制来实现解压缩操作是足够的。然而，当流中包含了多个可变尺寸的数据包，或者每一个数据包包含了多个可变尺寸的数据条目、或者解压缩的数据的尺寸存储与一个流的中间部分，那么这种机制是很麻烦的并且容易引入错误。为了解决这些问题，解压缩操作允许使用一个with表达式来显式地指明解压缩操作中可变尺寸域的范围。 with表达式的语法如下：
链接
第七章 操作符与表达式, 主题


7.18.1 将动态尺寸的数据位流化

链接
7.18 流操作符（压缩/非压缩）
SystemVerilog 3.1a语言参考手册
7.18.1 将动态尺寸的数据位流化
7.18 流操作符（压缩/非压缩）

如果解压缩操作包含了庞大的动态尺寸类型，那么解压缩过程是很复杂的（就像强制类型转换中一样）：第一个动态尺寸条目被重新调整尺寸以便容纳流中所有的有效数据（排除了后续的固定尺寸条目）。对于仅仅包含了一个动态尺寸数据条目的流来说，采用这种机制来实现解压缩操作是足够的。然而，当流中包含了多个可变尺寸的数据包，或者每一个数据包包含了多个可变尺寸的数据条目、或者解压缩的数据的尺寸存储与一个流的中间部分，那么这种机制是很麻烦的并且容易引入错误。为了解决这些问题，解压缩操作允许使用一个with表达式来显式地指明解压缩操作中可变尺寸域的范围。

with表达式的语法如下：

Copy Code
stream_expression ::= expression [with[array_range_expression]]
                                                       // 引用自附录A.8.1
array_range_expression ::=
    expression
  | expression : expression
  | expression +: expression
  | expression -: expression

语法7-5 — with表达式语法（摘录自附录A）

with结构内的数组范围表达式必须具有integral类型，并且能够计算成位于固定尺寸数组边界内的值，或者，对于动态数组或队列，计算成正的值。with之前的表达式可以是任何一维的非压缩数组（包括队列）。with结构之内的表达式在它对应的数组被流化（也就是压缩或解压缩）之前被立即计算。因此，这个表达式可以指向被相同的操作符解压缩但位于数组之前的数据。如果这个表达式指向在对应数组之后（数组的右侧）被解压缩的变量，那么表达式使用变量的前一个值进行计算。

如果使用在一个解压缩操作的关联文中，并且数组是一个可变尺寸的数组，那么应该调整尺寸以便容纳这个范围表达式。如果数组是一个固定尺寸的数组并且范围表达式被计算成一个位于数组边界之外的范围，那么只有位于数组范围之内的数据被解压缩，并会产生一个错误。如果范围表达式被计算成一个小于数组（固定尺寸或可变尺寸）边界的范围，那么仅仅那些指定的条目被解压缩到指定的数组位置；数组中余下的部分不会被修改。

当使用在一个压缩操作关联文（位于语句的右侧）中的时候，它与数组分片的行为相同：指定数目的数组条目被压缩到流中。如果范围表达式的值小于数组的边界，那么只有指定的数组条目被流化。如果范围表达式大于数组边界，那么整个数组被流化，剩余的条目由指定数组的缺省值（在表5-1中描述）产生。

例如，下面的代码使用流操作符来建模一个在字节流上传输的包，它使用小字节编码顺序：

Copy Code
byte stream[$]; // 字节流

class Packet
    rand int header;
    rand int len;
    rand byte payload[];
    int crc;
    constraint G {len > 1; payload.size == len;}
    function void post_randomize;
        crc = payload.sum;
    endfunction
endclass

...

send: begin // 产生随机包并发送
    byte q[$];
    Packet p = new;
    void'(p.randomize());
    q = {<< byte{p.header, p.len, p.payload, p.crc}}; // 压缩
    stream = {stream, q};  // 添加到to stream
end

...

receive: begin // 接收包，解压缩，并删除
    byte q[$];
    Packet p = new;
    {<< byte{p.header, p.len, p.payload with[0+:p.len], p.crc}} = stream;
    stream = stream[$bits(p)/8:$]; // 删除包
end

在上面的例子中，压缩操作也可以写成：

Copy Code
q = {<< byte{p.header, p.len, p.payload with[0+:p.len], p.crc}};

或者写成：

Copy Code
q = {<< byte{p.header, p.len, p.payload with[0:p.len-1], p.crc}};

或者写成：

Copy Code
q = {<< byte{p}};

这几种情况的操作结果是相同的，因为p.len通过约束被指定成p.payload的尺寸。

Group

7.18 流操作符（压缩/非压缩）

链接
7.18 流操作符（压缩/非压缩）


7.19 条件操作符

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.19 条件操作符
第七章 操作符与表达式
Copy Code
conditional_expression ::=        // 引用自附录A.8.3
    cond_predicate ? {attribute_instance} expression : expression

cond_predicate ::=                // 引用自附录A.6.6
    expression_or_cond_pattern {&& expression_or_cond_pattern}

expression_or_cond_pattern ::=
    expression | cond_pattern

cond_pattern ::= expression matches pattern

语法 7-6 — 条件操作符语法（摘录自附录A）

本节描述了传统的条件操作符，其中cond_predicate仅仅是单个表达式。SystemVerilog还允许cond_predicate执行模式匹配，这种方式将在8.4节中描述。

正像Verilog所定义的那样，如果cond_predicate为真，那么操作符返回第一个表达式；如果结果为假，那么返回第二个表达式。如果cond_predicate被计算成一个不明确的值（x或z），那么无论是第一个表达式还是第二个表达式都应该被计算，并且它们的计算结果应该一位一位地组合起来。

SystemVerilog通过下列规则将条件操作符扩展到非integral类型以及结合表达式：

  • 如果第一个表达式和第二个表达式都是integral类型，那么操作按上述方式进行。
  • 如果第一个表达式或第二个表达式是intergral类型，并且另外一个可以被隐式地强制转换到integral类型，那么会进行强制类型转换并按上述的方式进行操作。
  • 对于所有其它情况，第一个表达式和第二个表达式的类型必须是等价的。

cond_predicate被计算成一个不明确的值，那么无论是第一个表达式还是第二个表达式都应该被计算，并且它们的结果应该一个元素一个元素地组合起来。如果元素是匹配的，那么返回元素。如果不匹配，那么应该返回元素类型的缺省的未初始化的值。

Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


7.20 集合成员资格

链接
第七章 操作符与表达式
SystemVerilog 3.1a语言参考手册
7.20 集合成员资格
第七章 操作符与表达式

SystemVerilog支持单一值集合以及集合成员资格操作符。

集合成员资格操作符的语法如下：

Copy Code
inside_expression ::= expression inside {open_range_list} // 引用自附录A.8.3

语法7-7 — inside表达式语法（摘录自附录A）

inside操作符左侧的表达式是任意单一表达式。inside操作符右侧的集合成员资格open_range_list是逗号分割的表达式或范围列表。如果列表中的表达式是一个集合数组，那么它的元素会被遍历，沿着数组深入直到到达一个单一值。集合的成员会被扫描直到找到一个匹配并返回1'b1。值可以是重复的，所以值与值的范围可以重叠。表达式和范围的计算顺序是不确定的。

Copy Code
int a, b, c;

if (a inside {b, c}) ...

int array[$] = {3,4,5};
if (ex inside {1, 2, array}) ... // 与{1, 2, 3, 4, 5}相同

对于非integral类型的表达式，inside操作符使用相等操作符（==）来执行比较。如果没有找到匹配的值，inside操作符返回1'b0。integral表达式也使用相等操作符，除了集合中各个值中的z会被当作是不予考虑的位，并且不会考虑这个位的位置。注意：与casez语句所执行的比较不同，位于左侧的表达式中的z值会被考虑在内；不予考虑是单向的。

Copy Code
logic [2:0] val;
while (val inside {3'b1?1}) ... // 匹配于3'b101, 3'b111, 3'b1x1, 3'b1z1

如果没有找到匹配，但某些比较结果是x，那么inside操作符应该返回1'bx。返回值实际是集合中所有与左侧表达式比较结果的或缩减。

Copy Code
wire r;
assign r = 3'bz11 inside {3'b1?1, 3'b011}; // r = 1'bx

SystemVerilog可以使用方括号（[]）来指定一个范围，方括号中包含了一个低边界和高边界，这两个边界值之间用冒号（:）隔开，例如[low_bound:high_bound]这样的形式。使用$指定的范围应代表左侧表达式类型的最高或最低值。如果左侧的表达式包含在范围之内，那么会找到一个匹配。当指定了一个范围的时候，表达式必须是定义了关系操作符（<=，>=）的单一值。如果冒号左侧的边界大于冒号右侧的边界，那么这个范围是空的并且不包含任何值。

例如：

Copy Code
bit ba = a inside {[16:23], [32:47]};

string I;
if (I inside {["a rock":"hard place"]}) ...
    // I在"a rock"和"hard place"之间
Group

第七章 操作符与表达式

链接
第七章 操作符与表达式


第八章 过程语句和控制流

链接
主题
SystemVerilog 3.1a语言参考手册
第八章 过程语句和控制流
主题
主题
主题 | 描述
8.1 简介（一般信息） | 过程语句通过下列语句引入：
8.2 语句 |
8.3 阻塞赋值与无阻塞赋值 |
8.4 选择语句 |
8.5 循环语句 |
8.6 跳转语句 |
8.7 final块 | final块类似于intial块，它们都定义了一个过程化的语句块，不同的是，final块仅仅在仿真时间的尾部无延时地执行。典型情况下，final块用来显示有关仿真的统计信息。
8.8 命名块与语句标签 |
8.9 disable | SystemVerilog具有break和continue来中断或继续循环的执行。Verilog-2001的disable也可以用来中断或继续一个循环，但不如break或continue好用。disable也可以用来关闭一个命名的未包含disable语句的块。如果那个块当前正在执行，会立即跳转到块之后的语句。如果块是一个循环体，那么它与continue起相同的作用。如果块当前没有执行，那么disable没有任何效果。 SystemVerilog可以在任务中使用return，但也支持disable。如果disable被应用到一个命名的任务，那么这个任务中所有当前正在运行的部分都会被关闭。
8.10 事件控制 |
8.11 电平敏感的序列控制 | 我们可以延迟过程代码的执行直到一个序列终结状态为“真”。为了达到这个目的，我们可以使用电平敏感的wait语句并结合内建方法triggered来实现，这个内建方法能够返回一个命名序列当前的结束状态。 如果指定的序列已经在特定的时间点（在当前的时间步值内）上到达了它的结束点，那么triggered方法返回“真”，否则返回“假”。一个序列的触发状态在Observe区域内设置，并且在时间步值的余下部分保持（也就是说直到仿真时间进入到下一步）。 例如：
8.12 过程赋值与解赋值的移除 | SystemVerilog当前支持过程赋值与解赋值语句。然而，这些语句在语言的未来版本中可能会被移除。参见26.3节。
链接
主题


8.1 简介（一般信息）

链接
第八章 过程语句和控制流
SystemVerilog 3.1a语言参考手册
8.1 简介（一般信息）
第八章 过程语句和控制流

过程语句通过下列语句引入：

Copy Code
initial   // 在仿真开始的时候使能这个语句，并且仅执行一次
final     // 在仿真结束的时候执行这个语句
always, always_comb, always_latch, always_ff
          // 永远循环执行（参见第九章有关进程的内容）
task      // 在任务被调用的时候执行这些语句
function  // 在函数被调用并返回一个值的时候执行这些语句

在一个进程内部，SystemVerilog具有下述类型的控制流：

  • 选择、循环及跳转
  • 任务与函数调用
  • 顺序和并行块
  • 时序控制

Verilog过程语句包含在initial或always块、任务或函数中。SystemVerilog加入了在仿真结束时执行的final块。

除了do...while、break、continue和goto语句外，Verilog包含了C语言的大多数语句类型。Verilog具有C语言所没有的repeat语句以及disable语句。使用Verilog dsiable语句来执行break和continue的功能要求用户说明块名字并引入了出错的机会。

SystemVerilog加入了类似于C语言的break、continue和return功能，它们并不要求使用块名字。

在外部检查的循环有时对于节省循环体的复制非常有用。为了具有这种能力，SystemVerilog加入了类似于C语言的do...while循环。

Verilog提供了两种重叠的方法来过程化地加入和移除变量的驱动：force/releas语句和assign/deassign语句。除了变量之外，force/releas语句还可以用来加入和移除线网的驱动。一条作用于当前是一个assign语句目标的变量的force语句应该过载那条赋值语句；然而，一旦force被释放，那么assign的效果又会重新可见。

基于某些相似而又完全不同的目的，assign关键字被普遍用来为线网定义永久的驱动值。

SystemVerilog的final块以一个任意但又确定的顺序执行。这是因为：final块被限制成允许在函数中使用的合法语句集。SystemVerilog没有指定语句的执行顺序，但实现工具应该定义一种规则来保持不同运行间的执行次序。由于final块主要用于显示统计信息，因此这种方法可以保证一个稳定的输出日志文件。

Group

第八章 过程语句和控制流

链接
第八章 过程语句和控制流


8.2 语句

链接
第八章 过程语句和控制流
SystemVerilog 3.1a语言参考手册
8.2 语句
第八章 过程语句和控制流
Copy Code
statement_or_null ::=            // 引用自附录A.6.4
    statement
  | {attribute_instance};

statement ::= [block_identifier:]{attribute_instance} statement_item

statement_item ::=
    blocking_assignment;
  | nonblocking_assignment;
  | procedural_continuous_assignment;
  | case_statement
  | conditional_statement
  | inc_or_dec_expression;
  | subroutine_call_statement
  | disable_statement
  | event_trigger
  | loop_statement
  | jump_statement
  | par_block
  | procedural_timing_control_statement
  | seq_block
  | wait_statement
  | procedural_assertion_statement
  | clocking_drive;
  | randsequence_statement
  | randcase_statement
  | expect_property_statement

语法8-1—过程语句语法（摘录自附录A）

Group

第八章 过程语句和控制流

链接
第八章 过程语句和控制流


8.3 阻塞赋值与无阻塞赋值

链接
第八章 过程语句和控制流
SystemVerilog 3.1a语言参考手册
8.3 阻塞赋值与无阻塞赋值
第八章 过程语句和控制流
Copy Code
blocking_assignment ::=    // 引用自附录A.6.2
    variable_lvalue = delay_or_event_control expression
  | hierarchical_dynamic_array_variable_identifier = dynamic_array_new
  | [implicit_class_handle.|class_scope|package_scope]hierarchical_variable_identifier
        select = class_new
  | operator_assignment

operator_assignment ::= variable_lvalue assignment_operator expression

assignment_operator ::=
    = | += | -= | *= | /= | %= | &= | |= | ^= | <<= | >>= | <<<= | >>>=

nonblocking_assignment ::= variable_lvalue <= [delay_or_event_control] expression

语法 8-2—阻塞与无阻塞赋值语法（摘录自附录A）

下列的赋值语句在Verilog-2001和SystemVerilog中都是合法的：

Copy Code
#1 r = a;
r = #1 a;
r <= #1 a;
r <= a;
@c r = a;
r = @c a;
r <= @c a;

在赋值语句中，SystemVerilog还允许指定一个时间单位，例如：

Copy Code
#1ns r = a;
r = #1ns a;
r <= #1ns a;

为自动变量进行无阻塞赋值是非法的。

赋值语句左侧的尺寸形成了右侧表达式的关联文。如果左侧尺寸小于右侧表达式尺寸，信息可能会丢失，并且可以给出警告信息。

Group

第八章 过程语句和控制流

链接
第八章 过程语句和控制流


8.4 选择语句

链接
第八章 过程语句和控制流, 主题
SystemVerilog 3.1a语言参考手册
8.4 选择语句
第八章 过程语句和控制流 | 主题
Copy Code
conditional_statement ::=                                       // 引用自附录A.6.6
    if (cond_predicate) statement_or_null [else statement_or_null]
  | unique_priority_if_statement

unique_priority_if_statement ::=
    [unique_priority] if (cond_predicate) statement_or_null
        {else if (cond_predicate) statement_or_null}
        [else statement_or_null]

unique_priority ::= unique | priority

cond_predicate ::=
    expression_or_cond_pattern {&& expression_or_cond_pattern}

expression_or_cond_pattern ::=
    expression | cond_pattern

cond_pattern ::= expression matches pattern

case_statement ::=                                           // 引用自附录 A.6.7
    [unique_priority]case_keyword(expression) case_item {case_item} endcase
  | [unique_priority]case_keyword(expression) matches case_pattern_item {case_pattern_item}
        endcase

case_keyword ::= case | casez | casex

case_item ::=
    expression {,expression} : statement_or_null
  | default [:] statement_or_null

case_pattern_item ::=
    pattern [&&expression ] : statement_or_null
  | default [:] statement_or_null

语法 8-3—选择语句语法（摘录自附录A）

在Verilog中，if (expression) 被计算成一个布尔值，因此，如果表达式的值是0或X，那么条件检查被认为是“假”的。

SystemVerilog加入了关键字unique和priority，它们可以在if之前使用。除非有一个显式的else语句，在没有条件匹配的情况下，只要使用了这两个关键字，就会引起运行时错误。例如：

Copy Code
unique if ((a==0) || (a==1)) $display("0 or 1");
else if (a == 2) $display("2");
else if (a == 4) $display("4"); // 值3,5,6,7会引起一个错误

priority if (a[2:1]==0) $display("0 or 1");
else if (a[2]==0) $display("2 or 3");
else $display("4 or 7"); // 覆盖了所有可能的其他值，因此没有错误。

unique if指示在一系列 if...else...if条件中不应该有任何交迭，也就是说，这些条件是互斥的，这就使得表达式能够并行计算。如果软件工具发现有多于一个条件为“真”，那么它应该发布一条错误信息。另外，如果软件工具发现没有条件为“真”，或者可能没有条件为“真”，并且最后的if没有对应的else语句，软件工具也应该发布一条错误信息。

priority if指示一系列if...else...if条件应该按列出的顺序计算。在前面的例子中，如果变量a的值为0，那么它可以满足第一个条件和第二个条件，这就要求一个优先级逻辑。如果软件工具发现没有条件为“真”，或者可能没有条件为“真”，并且最后的if没有对应的else语句，软件工具也应该发布一条错误信息。

unique和priority关键字适用于整个if...else...if条件。在前面的例子中，在任何一个else的后面插入这两个关键字都是非法的。为了在这一系列中的条件中嵌套另外一个if语句，应该使用begin...end块。

在Verilog中，具有三种类型的case语句，分别为case、casez和casex。在SystemVerilog中，这三个中的任何一个都可以使用priority或unique限定。priority case仅仅作用于第一个匹配。unique case应该检查case条目的交迭，允许case条目能够并行计算。如果多于一个case条目匹配于case表达式，那么unique case应该发布一条警告信息。如果case被限定为priority或unique，那么，如果没有case条目匹配的话，仿真器应该发布一条警告信息。这些警告信息可以在编译时发布也可以在运行时发布，只要仿真器能够确定这些无效条件。

注意：通过指定unique或priority，我们没有必要编码一个default条件来包含不期望的条件值。例如：

Copy Code
bit [2:0] a;

unique case(a)   // 值3,5,6,7会引起一个运行时警告
    0,1: $display("0 or 1");
    2: $display("2");
    4: $display("4");
endcase

priority case(a) // 值4,5,6,7会引起一个运行时警告
    3'b00?: $display("0 or 1");
    3'b0??: $display("2 or 3");
endcase
Group

第八章 过程语句和控制流

主题
主题 | 描述
8.4.1 模式匹配 | 对于将一个值与结构体、标签联合体和常量进行比较以及对它们的成员的访问来讲，模式匹配提供了一个形象而又简洁的符号。SystemVerilog为case语句、if语句以及条件表达式加入了模式匹配的能力。在描述那些关联文中的模式匹配之前，我们首先描述一下基本概念。 模式是在叶子上带有标识符、常量表达式、以及通配符模式“.*”的标签联合体和结构体表达式的嵌套。对于标签联合体模式，紧跟tagged关键字之后的标识符是一个联合体成员名。对于void成员， 嵌套的成员模式被忽略。
链接
第八章 过程语句和控制流, 主题


8.4.1 模式匹配

链接
8.4 选择语句, 主题
SystemVerilog 3.1a语言参考手册
8.4.1 模式匹配
8.4 选择语句 | 主题

对于将一个值与结构体、标签联合体和常量进行比较以及对它们的成员的访问来讲，模式匹配提供了一个形象而又简洁的符号。SystemVerilog为case语句、if语句以及条件表达式加入了模式匹配的能力。在描述那些关联文中的模式匹配之前，我们首先描述一下基本概念。

模式是在叶子上带有标识符、常量表达式、以及通配符模式“.*”的标签联合体和结构体表达式的嵌套。对于标签联合体模式，紧跟tagged关键字之后的标识符是一个联合体成员名。对于void成员， 嵌套的成员模式被忽略。

Copy Code
pattern ::=                                              // 引用自附录A.6.7.1
    variable_identifier
  | .*
  | .constant_expression
  | tagged member_identifier [pattern]
  | {pattern{,pattern}}
  | {member_identifier : pattern {, member_identifier : pattern}}

语法 8-4 — 模式语法（摘录自附录A）

由于模式是与已知类型的表达式进行匹配，所以模式总是出现在已知类型的关联文中。递归起来，它的嵌套模式也是已知类型的。常量表达式模式必须具有integral类型。因此，模式总是可以进行静态的类型检查。

每一个模式都引入了一个新的范围；下面的几节会对case语句、if语句和条件表达式的范围扩展作单独的描述。每一个模式标识符在模式的范围内被隐式地声明成一个新的具有唯一类型的变量，它必须基于它在模式中的位置来确定这个类型。模式标识符在模式内必须是唯一的，也就是说，在单个模式内相同的标识符不能在多个位置使用。

在模式匹配中，一个表达式的值V总是匹配于一个模式。注意：静态类型检查能够确保V与模式具有相同的类型。一个模式匹配的结果是：

  • 一个确定的1位值：0（假或失败）或1（真或成功）。即使值和模式包含了x或z，结果也不会是x或z。
  • 如果匹配成功，那么模式标识符使用普通的过程赋值绑定到V中的对应成员。

每一个模式通过使用下述简单的递归规则进行匹配：

  • 一个标识符模式总是成功的（匹配于任意值），并且标识符被绑定到这个值（使用普通的过程赋值）。
  • 通配符模式“.*”总是成功的。
  • 一个常量表达式模式在V等于表达式的值的时候是成功的。
  • 对于一个标签联合体模式，如果值具有相同的标签，并且如果这个嵌套的模式匹配于标签联合体的成员值，那么匹配是成功的。
  • 对于结构体模式，如果每一个嵌套成员模式匹配于V中的对应成员，那么匹配是成功的。在具有命名成员的结构体模式中，成员的文本顺序是无关紧要的，并且成员可以被省略。省略的成员会被忽略。

从概念上讲，如果值V被看作是一个展平的位向量，那么模式指定了哪些位进行匹配，它们应该匹配于什么值，并且，如果匹配成功，它指定需要提取哪些位并绑定于模式标识符。匹配可以不敏感于x和z，就像下面的单独结构中所描述的那样。

Group

8.4 选择语句

主题
主题 | 描述
8.4.1.1 case语句中的模式匹配 | 在一个模式匹配case语句中，圆括号内的表达式紧跟着关键字matches，并且语句包含了一系列“case_pattern_items”。在一个case条目的左侧，“:”之前的部分，包含了一个模式以及一个可选的&&操作符，在&&操作符之后紧跟一个“filter”布尔表达式。case条目的右侧是一条语句。每一个模式都引入了一个新的作用范围，在这个范围中会隐式地声明它的模式标识符；这个作用范围扩展到可选的过滤器表达式以及同一个case条目右侧的语句。因此，不同的case条目可以复用模式标识符。 所有的模式均执行完全静态的类型检查。在模式匹配case语句中进行测试的表达式必须具有已知的类型，它与每个case条目中模式的类型相同。 模式匹配case语句中圆括号内的表达式应该仅计算一次。它的值V应该以指定的顺序一次一个条目地与case条目的左侧进行匹配，如果有default case条目的话，会将其忽略。在这个线性搜索过程中，如果一个case条目被选择，那么它对应的语句会被执行，然后中止这个线性搜索。如果没有case条目被选择，那么会执行default case条目中的语句。如果既没有case条目被选择也没有指定default case条目的话，那么不执行任何语句。 对于一个被选择的case条目，值V必须与模式匹配（模式标识符被赋值为V中对应的成员），并且，布尔过滤器表达式的计算结果必须为“真”（非零的确定值）。 例子：
8.4.1.2 if语句中的模式匹配 | if语句中的判定条件可以是一系列使用&&操作符分割的子句。每一个字句或者是一个表达式（用作布尔过滤器），或者具有形状表达式匹配模式。这些子句代表了一个从左到右的顺序的联合，也就是说，如果任何子句失败，剩余的子句都不会被计算，为了使判定条件为真，所有的子句都必须成功。布尔表达式以正常的方式计算。每一个模式都产生一个新的作用范围，其中模式标识符被隐式声明；这个作用范围扩展到判定条件中剩余的子句并扩展到if语句中对应为“真”的分支。 在每一个e匹配于p的子句中，e和p必须相同的静态已知的类型。e的值以上面描述的方式与p进行匹配。 即使模式匹配子句总是返回1位的结果，整个判定条件的结果也可能会因为其中的布尔过滤器表达式变得不明确。if语句保持标准语义，也就是说，第一条语句只有当结果是确定的非零值时才执行。 例子：
8.4.1.3 条件表达式中的模式匹配 | 条件表达式（e1 ? e2 : e3）也可以使用模式匹配，也就是说，判定条件e1可以是一个表达式序列，并且表达式匹配模式子句使用&&操作符分割，就像if语句中的判定条件一样。这些子句代表了一个从左到右的顺序的联合，也就是说，如果任何子句失败，剩余的子句都不会被计算，为了使判定条件为真，所有的子句都必须成功。布尔表达式以正常的方式计算。每一个模式都产生一个新的作用范围，其中模式标识符被隐式声明；这个作用范围扩展到判定条件中剩余的子句并扩展到作为结果的表达式e2。 正像前面章节所描述的那样，e1可以被计算成“真”、“假”或者一个不明确的值。对于e1，整个条件表达式的语义基于这三个可能的结果在7.18节中描述。
链接
8.4 选择语句, 主题


8.4.1.1 case语句中的模式匹配

链接
8.4.1 模式匹配
SystemVerilog 3.1a语言参考手册
8.4.1.1 case语句中的模式匹配
8.4.1 模式匹配

在一个模式匹配case语句中，圆括号内的表达式紧跟着关键字matches，并且语句包含了一系列“case_pattern_items”。在一个case条目的左侧，“:”之前的部分，包含了一个模式以及一个可选的&&操作符，在&&操作符之后紧跟一个“filter”布尔表达式。case条目的右侧是一条语句。每一个模式都引入了一个新的作用范围，在这个范围中会隐式地声明它的模式标识符；这个作用范围扩展到可选的过滤器表达式以及同一个case条目右侧的语句。因此，不同的case条目可以复用模式标识符。

所有的模式均执行完全静态的类型检查。在模式匹配case语句中进行测试的表达式必须具有已知的类型，它与每个case条目中模式的类型相同。

模式匹配case语句中圆括号内的表达式应该仅计算一次。它的值V应该以指定的顺序一次一个条目地与case条目的左侧进行匹配，如果有default case条目的话，会将其忽略。在这个线性搜索过程中，如果一个case条目被选择，那么它对应的语句会被执行，然后中止这个线性搜索。如果没有case条目被选择，那么会执行default case条目中的语句。如果既没有case条目被选择也没有指定default case条目的话，那么不执行任何语句。

对于一个被选择的case条目，值V必须与模式匹配（模式标识符被赋值为V中对应的成员），并且，布尔过滤器表达式的计算结果必须为“真”（非零的确定值）。

例子：

Copy Code
typedef union tagged {
    void Invalid;
    int Valid;
} VInt;

...
VInt v;
...

case (v) matches
    tagged Invalid : $display ("v is Invalid");
    tagged Valid n : $display ("v is Valid with value %d", n);
endcase

在上述的case语句中，如果v当前具有Invalid标签，那么第一个模式形成匹配。否则，它必须具有Valid标签，并且第二个模式形成匹配。标识符n被绑定到Valid成员的值，并且这个值被显示。当标签为Invalid的时候，我们不可能访问整数成员值n。

例子：

Copy Code
typedef union tagged {
    struct {
        bit [4:0] reg1, reg2, regd;
    } Add;
    union tagged {
        bit [9:0] JmpU;
        struct {
            bit [1:0] cc;
            bit [9:0] addr;
        } JmpC;
    } Jmp;
} Instr;
...
Instr instr;
...
case (instr) matches
    tagged Add {r1,r2,rd} && (rd != 0): rf[rd] = rf[r1] + rf[r2];
    tagged Jmp j : case (j) matches
                       tagged JmpU a : pc = pc + a;
                       tagged JmpC {c,a}: if (rf[c]) pc = a;
                   endcase
endcase

如果instr保存了一个Add指令，那么第一个模式形成匹配，标识符r1、r2和rd被绑定到嵌套结构体值得三个寄存器域。右侧的语句对寄存器文件rf执行这个指令。如果标签为Jmp，我们不可能访问这些寄存器域。如果instr保存了一个Jmp指令，那么第二个模式形成匹配，并且标识符j被绑定到嵌套的标签联合体值。内层的case语句轮流地将这个值与JmpU和JmpC模式进行匹配，依次类推。

下面的例子与前一个例子相同，但使用通佩符和常量模式来排除rd=0的情况（在某些处理器中，寄存器0是一个特殊的“丢弃”寄存器）：

Copy Code
case (instr) matches
    tagged Add {.*,.*, .0} : ;   // 无操作
    tagged Add {r1,r2,rd} : rf[rd] = rf[r1] + rf[r2];
    tagged Jmp j : case (j) matches
                       tagged JmpU a : pc = pc + a;
                       tagged JmpC {c,a}: if (rf[c]) pc = a;
                   endcase
endcase

下面的例子与前一个例子相同，但第一个内层case语句仅包含结构体和常量，但不包括标签联合体：

Copy Code
case (instr) matches
    tagged Add s: case (s) matches
                      {.*,.*, .0} : ;   // 无操作
                      {r1,r2,rd} : rf[rd] = rf[r1] + rf[r2];
                  endcase
    tagged Jmp j : case (j) matches
                       tagged JmpU a : pc = pc + a;
                       tagged JmpC {c,a}: if (rf[c]) pc = a;
                   endcase
endcase

下面的例子与前一个相同，但使用嵌套的标签联合体模式：

Copy Code
case (instr) matches
    tagged Add {r1,r2,rd} && (rd != 0): rf[rd] = rf[r1] + rf[r2];
    tagged Jmp (tagged JmpU a) : pc = pc + a;
    tagged Jmp (tagged JmpC {c,a}) : if (rf[c]) pc = a;
endcase

下面的例子与前一个相同，但使用命名的结构体组件：

Copy Code
case (instr) matches
    tagged Add {reg2:r2,regd:rd,reg1:r1} && (rd != 0): rf[rd] = rf[r1] + rf[r2];
    tagged Jmp (tagged JmpU a) : pc = pc + a;
    tagged Jmp (tagged JmpC {addr:a,cc:c}) : if (rf[c]) pc = a;
endcase

casez和casex关键字同样可以用来替代case关键字，并具有相同的语义。换句话说，在模式匹配过程中，无论两个位在哪里比较（无论它们是标签位还是成员位），casez都会忽略z位，casex会忽略z和x位。

priority和unique限定符扮演它们原本的角色。priority意味着某个case条目必须被选择。unique也同样意味着仅仅可以选择一个case条目，所以他们可以并行计算。

Group

8.4.1 模式匹配

链接
8.4.1 模式匹配


8.4.1.2 if语句中的模式匹配

链接
8.4.1 模式匹配
SystemVerilog 3.1a语言参考手册
8.4.1.2 if语句中的模式匹配
8.4.1 模式匹配

if语句中的判定条件可以是一系列使用&&操作符分割的子句。每一个字句或者是一个表达式（用作布尔过滤器），或者具有形状表达式匹配模式。这些子句代表了一个从左到右的顺序的联合，也就是说，如果任何子句失败，剩余的子句都不会被计算，为了使判定条件为真，所有的子句都必须成功。布尔表达式以正常的方式计算。每一个模式都产生一个新的作用范围，其中模式标识符被隐式声明；这个作用范围扩展到判定条件中剩余的子句并扩展到if语句中对应为“真”的分支。

在每一个e匹配于p的子句中，e和p必须相同的静态已知的类型。e的值以上面描述的方式与p进行匹配。

即使模式匹配子句总是返回1位的结果，整个判定条件的结果也可能会因为其中的布尔过滤器表达式变得不明确。if语句保持标准语义，也就是说，第一条语句只有当结果是确定的非零值时才执行。

例子：

Copy Code
if (e matches (tagged Jmp (tagged JmpC {cc:c,addr:a})))
    ...    // c和a可以在这里使用
else
    ...

下面的例子与前一个相同，它演示了一个带有标识符的两个模式匹配的序列，标识符在第一个模式中绑定，并在第二个模式中使用。

Copy Code
if (e matches (tagged Jmp j),
    j matches (tagged JmpC {cc:c,addr:a}))
    ...    // c和a可以在这里使用
else
    ...

下面的例子与第一个例子相同，但为子句序列加入了一个布尔表达式。它的含义为：“如果e是一个有条件的跳转指令并且条件寄存器不等于0，...”。

Copy Code
if (e matches (tagged Jmp (tagged JmpC {cc:c,addr:a})) && (rf[c] != 0))
    ...    // c和a可以在这里使用
else
    ...

对于if语句来说，即使它们使用了模式匹配，priority和unique限定符也仍然扮演它们原本的角色。

Group

8.4.1 模式匹配

链接
8.4.1 模式匹配


8.4.1.3 条件表达式中的模式匹配

链接
8.4.1 模式匹配
SystemVerilog 3.1a语言参考手册
8.4.1.3 条件表达式中的模式匹配
8.4.1 模式匹配

条件表达式（e1 ? e2 : e3）也可以使用模式匹配，也就是说，判定条件e1可以是一个表达式序列，并且表达式匹配模式子句使用&&操作符分割，就像if语句中的判定条件一样。这些子句代表了一个从左到右的顺序的联合，也就是说，如果任何子句失败，剩余的子句都不会被计算，为了使判定条件为真，所有的子句都必须成功。布尔表达式以正常的方式计算。每一个模式都产生一个新的作用范围，其中模式标识符被隐式声明；这个作用范围扩展到判定条件中剩余的子句并扩展到作为结果的表达式e2。

正像前面章节所描述的那样，e1可以被计算成“真”、“假”或者一个不明确的值。对于e1，整个条件表达式的语义基于这三个可能的结果在7.18节中描述。

Group

8.4.1 模式匹配

链接
8.4.1 模式匹配


8.5 循环语句

链接
第八章 过程语句和控制流, 主题
SystemVerilog 3.1a语言参考手册
8.5 循环语句
第八章 过程语句和控制流 | 主题
Copy Code
loop_statement ::=                // 引用自附录A.6.8
    forever statement_or_null
  | repeat (expression) statement_or_null
  | while (expression) statement_or_null
  | for (for_initialization; expression; for_step)
        statement_or_null
  | do statement_or_null while (expression);
  | foreach (array_identifier[loop_variables]) statement

for_initialization ::=
    list_of_variable_assignments
  | data_type list_of_variable_assignments {,data_type list_of_variable_assignments}

for_step ::= for_step_assignment {,for_step_assignment}

for_step_assignment ::=
    operator_assignment
  | inc_or_dec_expression

loop_variables ::= [index_variable_identifier]{,[index_variable_identifier]}

语法 8-5—循环语句语法（摘录自附录A）

Verilog提供了for、while、repeat以及forever循环。SystemVerilog增强了Verilog的for循环，并加入了一个do...while循环和一个foreach循环。

Group

第八章 过程语句和控制流

主题
主题 | 描述
8.5.1 do...while循环 |
8.5.2 循环的增强 | 在Verilog中，用来控制for循环的变量必须在循环之前声明。如果两个或多个并行程序中的循环使用相同的循环控制变量，那么就有可能出现一个循环修改其它循环还在使用的循环控制变量的情况。 SystemVerilog加入了在for循环中声明for循环控制变量的能力。这种方式会在循环内产生一个本地变量。其它并行循环不可能偶然地影响这个循环控制变量。例如：
8.5.3 foreach循环 | foreach结构指定在数组元素上的迭代。它的自变量是一个指明任意类型数组（固定尺寸的、动态的、及联合数组）的标识符，然后紧跟着一个包围在方括号内的循环变量的列表。每一个循环变量对应于数组的某一维。foreach结构类似于一个使用数组范围替代一个表达式来指定重复次数的repeat循环。 例子：
链接
第八章 过程语句和控制流, 主题


8.5.1 do...while循环

链接
8.5 循环语句
SystemVerilog 3.1a语言参考手册
8.5.1 do...while循环
8.5 循环语句
Copy Code
do statement while(condition) // 与C语言相同

condition可以是作为布尔值看待的任何表达式。它在statement之后计算。

Group

8.5 循环语句

链接
8.5 循环语句


8.5.2 循环的增强

链接
8.5 循环语句
SystemVerilog 3.1a语言参考手册
8.5.2 循环的增强
8.5 循环语句

在Verilog中，用来控制for循环的变量必须在循环之前声明。如果两个或多个并行程序中的循环使用相同的循环控制变量，那么就有可能出现一个循环修改其它循环还在使用的循环控制变量的情况。

SystemVerilog加入了在for循环中声明for循环控制变量的能力。这种方式会在循环内产生一个本地变量。其它并行循环不可能偶然地影响这个循环控制变量。例如：

Copy Code
module foo;
    initial begin
        for (int i = 0; i <= 255; i++)
            ...
    end

    initial begin
        loop2: for (int i = 15; i >= 0; i--)
        ...
    end
endmodule

在for循环内部声明的本地变量相等于在一个未命名的块中声明了一个自动变量。

Verilog仅允许单个初始化语句以及在for循环中的单个步值赋值语句。SystemVerilog允许初始声明或赋值语句可以是一条或多条用逗号分割的语句。步值赋值也可以是一条或多条用逗号分割的语句。

Copy Code
for (int count = 0; count < 3; count++)
    value = value +((a[count]) * (count+1));

for (int count = 0, done = 0, int j = 0; j * count < 125; j++)
    $display("Value j = %d\n", j);
Group

8.5 循环语句

链接
8.5 循环语句


8.5.3 foreach循环

链接
8.5 循环语句
SystemVerilog 3.1a语言参考手册
8.5.3 foreach循环
8.5 循环语句

foreach结构指定在数组元素上的迭代。它的自变量是一个指明任意类型数组（固定尺寸的、动态的、及联合数组）的标识符，然后紧跟着一个包围在方括号内的循环变量的列表。每一个循环变量对应于数组的某一维。foreach结构类似于一个使用数组范围替代一个表达式来指定重复次数的repeat循环。

例子：

Copy Code
string words[2] = {"hello", "world"};
int prod[1:8][1:3];

foreach (words[j])
    $display(j, words[j]); // 打印每一个索引和值

foreach (prod[k,m])
    prod[k][m] = k * m;    // 初始化

循环变量的数目必须匹配数组变量的维数。空循环变量可以用来指示在对应的数组维数上没有迭代，并且趋向于尾部的连续空循环变量可以被忽略。循环变量是自动的、只读的，并且它们的作用范围对于循环来讲是本地的。每一个循环变量的类型被隐含地声明成与数组索引的类型一致。数组中任何具有相同标识符的循环变量都是错误的。

循环变量到数组索引的映射由维基数确定，如23.7节所描述的那样。对于foreach循环，更高基数的索引变化也更快。

Copy Code
//     1  2  3         3    4       1   2 -> 维数
int A [2][3][4]; bit [3:0][2:1] B [5:1][4];

foreach(A[i, j, k]) ...
foreach(B[q, r, , s]) ...

对于第一条foreach子句，i从0到1迭代，j从0到2迭代，k从0到3迭代。对第二条foreach子句，q从5到1迭代，r从0到3迭代、s从2到1迭代（第三个索引的迭代被忽略）。

多个循环变量对应于在指定索引上迭代的嵌套循环。循环的嵌套由维基数确定；外层循环对应于较低的基数索引。在上面的第一个例子中，最外层的循环在i上迭代，最内层的循环在k上迭代。

当循环变量用在表达式当中而不是作为指定数组的索引的时候，它们被自动地强制转换到与索引类型一致的类型。对于固定尺寸或动态数组，强制转换类型时int。对于以特定索引类型索引的联合数组，强制转换类型与索引类型一致。对于使用通配符索引（*）进行索引的联合数组，强制转换类型是无符号的longint类型。为了使用不同的类型，可以使用一个显式的强制类型转换。

Group

8.5 循环语句

链接
8.5 循环语句


8.6 跳转语句

链接
第八章 过程语句和控制流
SystemVerilog 3.1a语言参考手册
8.6 跳转语句
第八章 过程语句和控制流
Copy Code
jump_statement ::=               // 引用自附录A.6.5
    return [expression];
  | break;
  | continue;

语法 8-6—跳转语句语法（摘录自附录A）

SystemVerilog加入了C语言跳转语句：break、continue和return。

Copy Code
break             // 像C语言一样跳出循环
continue          // 像C语言一样跳转到循环的尾部
return expression // 退出一个函数
return            // 退出一个任务或void函数

continue和break只能使用在循环当中。continue语句跳转到循环的尾部，并且，如果尾部存在循环控制语句，就执行这个循环控制语句。continue和break语句不能在fork...join语句中用来控制位于fork...join块之外的循环。

return语句只能使用在一个任务或函数当中。在返回一个值的函数中，return必须具有一个正确类型的表达式。

注意：SystemVerilog没有包含C语言的goto语句。

Group

第八章 过程语句和控制流

链接
第八章 过程语句和控制流


8.7 final块

链接
第八章 过程语句和控制流
SystemVerilog 3.1a语言参考手册
8.7 final块
第八章 过程语句和控制流

final块类似于intial块，它们都定义了一个过程化的语句块，不同的是，final块仅仅在仿真时间的尾部无延时地执行。典型情况下，final块用来显示有关仿真的统计信息。

Copy Code
final_construct ::= final function_statement // 引用自附录A.6.2

语法8-7 — final块语法（摘录自附录A）

在final块中可以使用的语句就是那些允许在一个函数声明中使用的语句。这就可以保证它们在一个仿真周期内执行。与intial块不同，final块不会作为一个单独的进程执行；相反，它的执行时间为0，与函数调用相同。

当一个显式或隐式的$finish调用引起仿真结束的时候会执行final块。

Copy Code
final
    begin
        $display("Number of cycles executed %d",$time/period);
        $display("Final PC = %h",PC);
    end

从一个final块中执行$finish、tf_dofinish()、或vpi_control(vpiFinish,...)会引起仿真立即中止。final块只能在一次仿真中触发一次。

final块应该在任何指示仿真结束的PLI回调之前执行。

Group

第八章 过程语句和控制流

链接
第八章 过程语句和控制流


8.8 命名块与语句标签

链接
第八章 过程语句和控制流
SystemVerilog 3.1a语言参考手册
8.8 命名块与语句标签
第八章 过程语句和控制流
Copy Code
seq_block ::=           // 引用自附录A.6.3
    begin [:block_identifier] {block_item_declaration} {statement_or_null}
    end [:block_identifier]

par_block ::=
    fork [:block_identifier] {block_item_declaration} {statement_or_null}
    join_keyword [:block_identifier]

join_keyword ::= join | join_any | join_none

语法8-8 — 块和标签语法（摘录自附录A）

Verilog允许命名一个begin...end、fork...join、fork...join_any或fork...join_none语句。一个命名的块可以用来标识整个语句块。一个命名的块产生了一个新的层次范围。块的名字在begin或fork关键字之后，并在前面加上一个冒号来说明。例如：

Copy Code
begin : blockA // Verilog-2001命名的块
    ...
end

SystemVerilog允许在块的end、join、join_any或join_none关键字之后说明一个匹配的块名字，并在名字的前面加上一个冒号。当块是一个嵌套的块的时候，这种方式可以帮助理解哪一个end、join、join_any或join_none与哪一个begin或fork相关联。块尾部的名字不是必须的，但如果它与块起始处的名字不一致的话，会引起一个错误。

Copy Code
begin: blockB // begin或fork后的块名字
    ...
end: blockB

与C语言一样，SystemVerilog允许在任何语句之前指定一个标签。一个语句标签被用来识别单条语句。标签名字在语句之前说明并跟着一个冒号。

Copy Code
labelA: statement

一个begin...end、fork...join、fork...join_any或fork...join_none块被当作一条语句，并且可以在块的前面具有一个语句标签。

Copy Code
labelB: fork  // begin或fork之前的标签
    ...
join : labelB

在begin或fork之前具有标签而在这两个关键字的后面具有块名字是非法的。标签不能出现在end、join、join_any或join_none之前，因为这些关键字不会组成一条语句。

带有标签的语句可以使用disable语句关闭。关闭一条语句与关闭一个命名块具有相同的行为。

参看9.6节中有关fork...join、fork...join_any或fork...join_none的其它讨论。

Group

第八章 过程语句和控制流

链接
第八章 过程语句和控制流


8.9 disable

链接
第八章 过程语句和控制流
SystemVerilog 3.1a语言参考手册
8.9 disable
第八章 过程语句和控制流

SystemVerilog具有break和continue来中断或继续循环的执行。Verilog-2001的disable也可以用来中断或继续一个循环，但不如break或continue好用。disable也可以用来关闭一个命名的未包含disable语句的块。如果那个块当前正在执行，会立即跳转到块之后的语句。如果块是一个循环体，那么它与continue起相同的作用。如果块当前没有执行，那么disable没有任何效果。

SystemVerilog可以在任务中使用return，但也支持disable。如果disable被应用到一个命名的任务，那么这个任务中所有当前正在运行的部分都会被关闭。

Copy Code
module ...
    always always1: begin
        ...
        t1: task1();
        ...
    end
    ...
endmodule

always begin
    ...
    disable u1.always1.t1; // 突出在always1（静态）中调用的任务
end
Group

第八章 过程语句和控制流

链接
第八章 过程语句和控制流


8.10 事件控制

链接
第八章 过程语句和控制流, 主题
SystemVerilog 3.1a语言参考手册
8.10 事件控制
第八章 过程语句和控制流 | 主题
Copy Code
delay_or_event_control ::=             // 引用自附录A.6.5
    delay_control
  | event_control
  | repeat (expression) event_control

delay_control ::=
    #delay_value
  | #(mintypmax_expression)

event_control ::=
    @hierarchical_event_identifier
  | @(event_expression)
  | @*
  | @(*)
  | @sequence_instance

event_expression ::=
    [edge_identifier] expression [iff expression]
  | sequence_instance [iff expression]
  | event_expression or event_expression
  | event_expression , event_expression

edge_identifier ::= posedge | negedge  // 引用自附录A.7.4

语法 8-9—时延与事件控制语法（摘录自附录A）

像Verilog一样，一个变量或线网的任何变化都可以使用@事件控制检测到。如果表达式的计算结果多于一位，那么结果中的任何一位发生变化（包括X到Z的变化）均会触发事件控制。

SystemVerilog为@事件控制加入了一个iff限定符。

Copy Code
module latch (output logic [31:0] y, input [31:0] a, input enable);
    always @(a iff enable == 1)
        y <= a; // latch处于透明模式
endmodule

事件表达式仅仅在iff之后的表达式为“真”时才会触发，在上面的例子中就是enable等于1的情况。注意：这个表达式只有在a发生变化时计算，而不是enable发生变化的时候。还需要注意：iff比or具有更高的优先级。我们可以使用圆括号使这层含义更加清晰。

如果变量不是一个四态类型，那么posedge和negedge分别指的是从0和到0的跃变。

如果这个表达式表示一个时钟控制块的输入或双向端口（参见第十五章），那么事件控制操作符使用同步的值，也就是时钟控制事件采样的值。表达式也可以表示一个由时钟控制事件触发的时钟控制块的名字（没有沿限定符）。

与事件控制一起使用的变量可以是任意integral数据类型（参见3.3.1节）或者是字符串。这个变量可以是一个简单的变量也可以是ref自变量（通过引用传递的变量）；它可以是上述类型的数组、联合数组、或对象（类实例）的成员。

事件表达式必须返回单一值。如果表达式能够缩减到一个单一值，集合类型也可以使用在表达式中。对象成员或集合元素可以是任意类型，只要表达式的结果是一个单一值。

如果事件表达式一个简单对象句柄的引用或者是chandel变量，那么当对变量的写不等于它的前一个值的时候会产生一个事件。

一个对象的非虚拟方法以及一个集合类型的内建方法或系统函数允许使用在事件控制表达式中，只要返回值是单一值并且方法被定义成一个函数而不是一个任务。

改变由一个方法或函数引用的对象数据成员、集合元素的值，或者动态尺寸数组的尺寸会引起事件表达式被重新计算。当改变值或尺寸的时候，一个具体的实现可以引起事件表达式被重新计算，即使这些成员没有被方法或函数引用。

Copy Code
real AOR[];     // real类型的动态数组
byte stream[$]; // byte类型的队列
initial wait(AOR.size() > 0) ....;   // 等待数组被分配
initial wait($bits(stream) > 60)...; // 等待stram中总的位数大于60

Packet p = new; // Packet 1
Packet q = new; // Packet 2

initial fork
    @(p.status); // 等待Packet 1中的status发生变化
    @q;          // 等待q的变化
    #10 q = p;   // triggers @q.
    // @(p.status) now waits for status in Packet 2 to change,
    // if not already different from Packet 1
join
Group

第八章 过程语句和控制流

主题
主题 | 描述
8.10.1 序列事件 | 事件表达式中可以使用一个序列实例，它基于序列的成功匹配来控制过程语句的执行。这就允许命名序列的终点能够触发其它进程中的多个动作。语法17-2和语法17-4描述了声明命名序列和序列实例的语法。正像语法8-9所显示的那样，一个序列实例可以直接使用在事件表达式中。 当一个事件表达式中指定了一个序列实例的时候，执行事件控制的进程应该阻塞直到指定的序列到达终点。只要整个序列形成匹配，一个序列就到达终点。进程继续执行之后的检测到终点的Observe区域。 使用一个序列作为事件控制的例子如下：
链接
第八章 过程语句和控制流, 主题


8.10.1 序列事件

链接
8.10 事件控制
SystemVerilog 3.1a语言参考手册
8.10.1 序列事件
8.10 事件控制

事件表达式中可以使用一个序列实例，它基于序列的成功匹配来控制过程语句的执行。这就允许命名序列的终点能够触发其它进程中的多个动作。语法17-2和语法17-4描述了声明命名序列和序列实例的语法。正像语法8-9所显示的那样，一个序列实例可以直接使用在事件表达式中。

当一个事件表达式中指定了一个序列实例的时候，执行事件控制的进程应该阻塞直到指定的序列到达终点。只要整个序列形成匹配，一个序列就到达终点。进程继续执行之后的检测到终点的Observe区域。

使用一个序列作为事件控制的例子如下：

Copy Code
sequence abc;
    @(posedge clk) a ##1 b ##1 c;
endsequence

program test;
    initial begin
        @abc $display("Saw a-b-c");
        L1 : ...
    end
endprogram

在上面的例子中，当命名序列abc到达终点时，program块test中的initial块被解除阻塞，然后它显示字符串"Saw a-b-c"，并执行标记为L1的语句。在这个例子中，序列终点的作用是解除事件阻塞的触发器。

使用在事件控制中的序列被实例化（就好像被一个断言特性语句实例化一样）；事件控制被用来同步序列的终点，而不管它的起始时间如何。序列的自变量应该是静态的；将自动变量作为序列的自变量会导致一个错误。

Group

8.10 事件控制

链接
8.10 事件控制


8.11 电平敏感的序列控制

链接
第八章 过程语句和控制流
SystemVerilog 3.1a语言参考手册
8.11 电平敏感的序列控制
第八章 过程语句和控制流

我们可以延迟过程代码的执行直到一个序列终结状态为“真”。为了达到这个目的，我们可以使用电平敏感的wait语句并结合内建方法triggered来实现，这个内建方法能够返回一个命名序列当前的结束状态。

如果指定的序列已经在特定的时间点（在当前的时间步值内）上到达了它的结束点，那么triggered方法返回“真”，否则返回“假”。一个序列的触发状态在Observe区域内设置，并且在时间步值的余下部分保持（也就是说直到仿真时间进入到下一步）。

例如：

Copy Code
sequence abc;
    @(posedge clk) a ##1 b ##1 c;
endsequence

sequence de;
    @(negedge clk) d ##[2:5] e;
endsequence

program check;
    initial begin
        wait(abc.triggered || de.triggered);

        if(abc.triggered)
            $display("abc succeeded");

        if(de.triggered)
            $display("de succeeded");

        L2 : ...
    end
endprogram

在上面的例子中，程序check中的initial块或者等待序列abc的结束点（成功）或者等待序列de的结束点。当其中一个条件满足的时候，wait语句解除进程的阻塞，它显示引起进程解除阻塞的序列，然后继续执行标记为L2的语句。

Group

第八章 过程语句和控制流

链接
第八章 过程语句和控制流


8.12 过程赋值与解赋值的移除

链接
第八章 过程语句和控制流
SystemVerilog 3.1a语言参考手册
8.12 过程赋值与解赋值的移除
第八章 过程语句和控制流

SystemVerilog当前支持过程赋值与解赋值语句。然而，这些语句在语言的未来版本中可能会被移除。参见26.3节。

Group

第八章 过程语句和控制流

链接
第八章 过程语句和控制流


第九章 进程

链接
主题
SystemVerilog 3.1a语言参考手册
第九章 进程
主题
主题
主题
描述
9.1 简介（一般信息）
Verilog-2001具有定义了静态进程的always和initial块。

在一个用来建模组合逻辑的always块中，如果忘记了else语句会产生一个不期望的锁存器。为了避免这个错误，SystemVerilog加入了专门的always_comb和always_latch块，它向仿真、综合和形式验证工具指明设计意图。SystemVerilog还加入了一个always_ff块来指示时序逻辑。

在系统建模过程中，Verilog的一个主要限制是缺乏动态创建进程的能力，这种能力在操作系统中经常出现。虽然Verilog具有fork...jion结构，但它仍然被限制成静态的。

SystemVerilog既具有由always、initial或fork引入的静态进程，也具有由fork...join_any和fork...join_none引入的动态进程。

SystemVerilog为每一个initial或always块、fork...join块中的每一条并行语句以及为每一个动态进程均创建了一个执行线程。每一条连续赋值语句也被认为是它自己的线程。

SystemVerilog 3.1通过增强fork...join结构加入了动态进程的能力，这种方式对于Verilog用户来说是非常自然的。SystemVerilog 3.1还引入了动态进程控制结构，它能够使用动态、父子关系来中止或等待进程。它们是wait fork和disable fork。
9.2 组合逻辑
SystemVerilog提供了一个特殊的always_comb过程来建模组合逻辑行为。例如：
9.3 锁存逻辑
SystemVerilog还包含了一个特殊的always_latch过程来建模锁存逻辑行为。例如：
9.4 时序逻辑
SystemVerilog的always_ff过程可以用来建模可综合的时序逻辑行为。例如：
9.5 连续赋值
在Verilog中，连续赋值只能驱动线网，而不能驱动变量。

SystemVerilog去除了这个限制，允许连续赋值驱动任何类型的变量。线网可以被多个连续赋值驱动，或者被原语和连续赋值混合驱动。而变量仅仅能够被一个连续赋值或一个原语驱动。对于被一个连续赋值或原语输出驱动的变量来说，在其声明或任何过程赋值中包含初始化是错误的。参见5.6节。
9.6 fork...join
fork...join能够从它的每一个并行语句中产生并发进程。

fork...join块的声明语法如下：
9.7 进程执行线程
SystemVerilog为下列进程产生一个执行线程：

  • 每一个initial块
  • 每一个always块
  • fork...join（或join_any，或jion_none）语句组中的每一个并行语句
  • 每一个动态进程

每一个连续赋值也可以认为是它自己的线程

9.8 进程控制
SystemVerilog提供了一些结构，它们允许一个进程能够中止其它进程，或者等待其它进程的结束。wait fork等待进程的结束。disable fork结构停止进程的执行。
9.9 精细的进程控制
进程是一个内建的类，一旦一个进程被启动，就允许这个进程访问和控制另外一个进程。用户可以声明进程类型的变量，并且能够通过任务对它们进行安全的传递，或者将它们结合到其它对象中。进程类的原型如下：
链接
主题


9.1 简介（一般信息）

链接
第九章 进程
SystemVerilog 3.1a语言参考手册
9.1 简介（一般信息）
第九章 进程

Verilog-2001具有定义了静态进程的always和initial块。

在一个用来建模组合逻辑的always块中，如果忘记了else语句会产生一个不期望的锁存器。为了避免这个错误，SystemVerilog加入了专门的always_comb和always_latch块，它向仿真、综合和形式验证工具指明设计意图。SystemVerilog还加入了一个always_ff块来指示时序逻辑。

在系统建模过程中，Verilog的一个主要限制是缺乏动态创建进程的能力，这种能力在操作系统中经常出现。虽然Verilog具有fork...jion结构，但它仍然被限制成静态的。

SystemVerilog既具有由always、initial或fork引入的静态进程，也具有由fork...join_any和fork...join_none引入的动态进程。

SystemVerilog为每一个initial或always块、fork...join块中的每一条并行语句以及为每一个动态进程均创建了一个执行线程。每一条连续赋值语句也被认为是它自己的线程。

SystemVerilog 3.1通过增强fork...join结构加入了动态进程的能力，这种方式对于Verilog用户来说是非常自然的。SystemVerilog 3.1还引入了动态进程控制结构，它能够使用动态、父子关系来中止或等待进程。它们是wait fork和disable fork。

Group

第九章 进程

链接
第九章 进程


9.2 组合逻辑

链接
第九章 进程, 主题
SystemVerilog 3.1a语言参考手册
9.2 组合逻辑
第九章 进程 | 主题

SystemVerilog提供了一个特殊的always_comb过程来建模组合逻辑行为。例如：

Copy Code
always_comb
    a = b & c;

always_comb
    d <= #1ns b & c;

always_comb过程提供了不同于正常always过程的功能：

  • 具有一个推断的敏感列表，它包括了9.2.1节中所定义的表达式。
  • 赋值语句左侧的变量不应该被任何其它进程写入。
  • 在所有的initial和always块被启动以后，过程在时间0处被自动地触发一次，因此过程的输出与输入一致。

SystemVerilog的always_comb过程在下述几个方面上不同于Verilog-2001的always @*：

  • always_comb在时间0处自动执行，而always @*直到推断的敏感列表中的一个信号发生变化的时候才会执行。
  • always_comb敏感于一个函数内容内部的改变，而always @*仅敏感于一个函数自变量的改变。
  • 在always_comb内部赋值左侧的变量（包括来自被调用函数内容中的变量）不应该被其它进程写入，而always @*则允许多个进程写入相同的变量。
  • always_comb中的语句不应该包含阻塞语句、具有阻塞定时或事件控制的语句，或者fork...join语句。

如果always_comb过程内的行为没有代表组合逻辑，例如推断出了锁存器，软件工具执行额外的检查来发布警告信息。

Group

第九章 进程

主题
主题
描述
9.2.1 隐含的always_comb敏感性
最长静态前缀“P”的扩展具有如下的定义：

  1. 如果P不是一个存储器或索引选择，或者P是一个合法的字或位选择，那么扩展就是P本身。
  2. 如果P是一个存储器或索引选择，那么扩展是每一个可能的有效的存储器字，只要它带有与P匹配的静态前缀。

一个always_comb块的隐式敏感列表包括每一个变量或选择表达式的最长静态前缀扩展，只要它们块内读取或在块内的任何函数调用中读取，但具有下列例外：

  1. 在块内或块内调用的任何函数内声明的变量的扩展。
  2. 也在块内或块内调用的任何函数内写入的任何表达式。

链接
第九章 进程, 主题


9.2.1 隐含的always_comb敏感性

链接
9.2 组合逻辑
SystemVerilog 3.1a语言参考手册
9.2.1 隐含的always_comb敏感性
9.2 组合逻辑

最长静态前缀“P”的扩展具有如下的定义：

  1. 如果P不是一个存储器或索引选择，或者P是一个合法的字或位选择，那么扩展就是P本身。
  2. 如果P是一个存储器或索引选择，那么扩展是每一个可能的有效的存储器字，只要它带有与P匹配的静态前缀。

一个always_comb块的隐式敏感列表包括每一个变量或选择表达式的最长静态前缀扩展，只要它们块内读取或在块内的任何函数调用中读取，但具有下列例外：

  1. 在块内或块内调用的任何函数内声明的变量的扩展。
  2. 也在块内或块内调用的任何函数内写入的任何表达式。
Group

9.2 组合逻辑

链接
9.2 组合逻辑


9.3 锁存逻辑

链接
第九章 进程
SystemVerilog 3.1a语言参考手册
9.3 锁存逻辑
第九章 进程

SystemVerilog还包含了一个特殊的always_latch过程来建模锁存逻辑行为。例如：

Copy Code
always_latch
    if(ck) q <= d;

always_latch确定它自己的敏感性并且具有与always_comb相同的运行方式。如果always_latch内的逻辑行为不代表锁存逻辑，那么软件工具可以执行额外的检查以便给出告警信息。

Group

第九章 进程

链接
第九章 进程


9.4 时序逻辑

链接
第九章 进程
SystemVerilog 3.1a语言参考手册
9.4 时序逻辑
第九章 进程

SystemVerilog的always_ff过程可以用来建模可综合的时序逻辑行为。例如：

Copy Code
always_ff @(posedge clock iff reset == 0 or posedge reset) begin
    r1 <= reset ? 0 : r2 + 1;
    ...
end

always_ff块具有一个限制：它仅能包含一个事件控制过程并且没有阻塞定时控制。always_ff块内赋值语句左侧的变量，包括来自于一个被调用的函数内容中的变量，不应该被其它进程写入。如果always_ff过程内的逻辑行为不代表时序逻辑，软件工具可以执行额外的检查以便给出警告信息。

Group

第九章 进程

链接
第九章 进程


9.5 连续赋值

链接
第九章 进程
SystemVerilog 3.1a语言参考手册
9.5 连续赋值
第九章 进程

在Verilog中，连续赋值只能驱动线网，而不能驱动变量。

SystemVerilog去除了这个限制，允许连续赋值驱动任何类型的变量。线网可以被多个连续赋值驱动，或者被原语和连续赋值混合驱动。而变量仅仅能够被一个连续赋值或一个原语驱动。对于被一个连续赋值或原语输出驱动的变量来说，在其声明或任何过程赋值中包含初始化是错误的。参见5.6节。

Group

第九章 进程

链接
第九章 进程


9.6 fork...join

链接
第九章 进程
SystemVerilog 3.1a语言参考手册
9.6 fork...join
第九章 进程

fork...join能够从它的每一个并行语句中产生并发进程。

fork...join块的声明语法如下：

Copy Code
par_block ::=          // 引用自附录A.6.3
    fork [: block_identifier] {block_item_declaration} {statement_or_null}
    join_keyword [: block_identifier]

join_keyword ::= join | join_any | join_none

语法 9-1—Fork...join块语法（摘录自附录A）

fork...join块可以指定一条或多条语句，每一条语句都应该作为并发进程执行。Verilog fork...join块总是引起执行fork语句的进程阻塞直到所有分支进程中止。通过加入join_any和join_none关键字，SystemVerilog提供了三种选择来指定父进程何时恢复执行。

表 9-1: fork...join控制选项

选项 | 描述
join | 父进程会阻塞直到这个分支产生的所有进程结束。
join_any | 父进程会阻塞直到这个分支产生的任意一个进程结束。
join_none | 父进程会继续与这个分支产生的所有进程并发执行。在父线程执行一条阻塞语句之前，产生的进程不会启动执行。

在定义一个fork...join块的时候，将整个分叉封装在一个begin...end块中会引起整个块作为单个进程执行，其中每条语句顺序地执行。

Copy Code
fork
    begin
        statement1; // 一个带有2条语句的进程
        statement2;
    end
join

在下面的例子中，包含两个进程分支，第一个等待20ns，第二个等待命名事件eventA被触发。因为指定了join关键字，父进程应该阻塞直到这两个进程结束；也就是说，直到过了20ns并且eventA被触发。

Copy Code
fork
    begin
        $display("First Block\n");
        #20ns;
    end
    begin
        $display("Second Block\n");
        @eventA;
    end
join

在一个fork...join语句的关联文中使用return语句是非法的，并且会导致一个编译错误。例如：

Copy Code
task wait_20;
    fork
        #20;
        return; // 非法的：不能返回；任务位于另外一个进程中
    join_none
endtask

只要fork...join块作用范围内声明的自动变量进入它们的作用范围，在产生任何进程之前，这些自动变量应该被初始化成它们的初始值。这些变量对于循环结构产生的进程存储唯一的、每次都交互的数据非常有用。例如：

Copy Code
initial
    for(int j = 1; j <= 3; ++j)
        fork
            automatic int k = j;     // 对每一个j值的本地拷贝
            #k $write("%0d", k);
            begin
                automatic int m = j; // m的值是不确定的
                ...
            end
        join_none

上面的例子的输出为：123。

Group

第九章 进程

链接
第九章 进程


9.7 进程执行线程

链接
第九章 进程
SystemVerilog 3.1a语言参考手册
9.7 进程执行线程
第九章 进程

SystemVerilog为下列进程产生一个执行线程：

  • 每一个initial块
  • 每一个always块
  • fork...join（或join_any，或jion_none）语句组中的每一个并行语句
  • 每一个动态进程

每一个连续赋值也可以认为是它自己的线程

Group

第九章 进程

链接
第九章 进程


9.8 进程控制

链接
第九章 进程, 主题
SystemVerilog 3.1a语言参考手册
9.8 进程控制
第九章 进程 | 主题

SystemVerilog提供了一些结构，它们允许一个进程能够中止其它进程，或者等待其它进程的结束。wait fork等待进程的结束。disable fork结构停止进程的执行。

Group

第九章 进程

主题
主题 | 描述
9.8.1 wait fork | wait fork语句被用来确保所有子进程（调用进程产生的进程）的执行都已经结束。 wait fork的语法如下：
9.8.2 disable fork | disable fork语句用来中止调用进程的所有活跃的子进程。 disable fork的语法如下：
链接
第九章 进程, 主题


9.8.1 wait fork

链接
9.8 进程控制
SystemVerilog 3.1a语言参考手册
9.8.1 wait fork
9.8 进程控制

wait fork语句被用来确保所有子进程（调用进程产生的进程）的执行都已经结束。

wait fork的语法如下：

Copy Code
wait fork; // 引用自附录A.6.5

指定wait fork会引起调用进程阻塞直到它的所有子进程结束。

当没有进一步的动作时，Verilog会中止仿真的运行。当所有的程序块停止执行的时候（也就是说，它们到达了执行块的尾部），SystemVerilog会自动中止仿真，而不管任何子进程的状态如何（参见16.6节）。wait fork语句允许一个程序块在退出之前等待它的所有并发线程的结束。

对于下面的例子，在任务do_test中，前两个进程产生后任务会阻塞直到其中一个进程结束（或者是exec1，或者是exec2）。接下来会在后台产生另外两个进程。wait fork语句能够确保任务do_test在返回调用之前能够等待产生的所有四个进程结束。

Copy Code
task do_test;
    fork
        exec1();
        exec2();
    join_any
    fork
        exec3();
        exec4();
    join_none
    wait fork; // 阻塞直到exec1 ... exec4完成
endtask
Group

9.8 进程控制

链接
9.8 进程控制


9.8.2 disable fork

链接
9.8 进程控制
SystemVerilog 3.1a语言参考手册
9.8.2 disable fork
9.8 进程控制

disable fork语句用来中止调用进程的所有活跃的子进程。

disable fork的语法如下：

Copy Code
disable fork; // 引用自附录A.6.5

disable fork语句用来中止调用进程的所有活跃的子进程，以及子进程的所有子进程。也就是说，如果任何子进程还具有它们自己的子进程，那么disable fork语句也会将它们中止。

在下面的例子中，任务get_first产生了一个任务的三个版本，每一个都用来等待一个特定的设备（1、7或13）。任务wait_device等待一个特定的设备准备就绪，然后返回设备的地址。当第一个设备有效的时候，get_first任务应该杀死正在执行的所有进程然后继续执行。

Copy Code
task get_first(output int adr);
    fork
        wait_device(1, adr);
        wait_device(7, adr);
        wait_device(13, adr);
    join_any
    disable fork;
endtask

Verilog支持disable结构，当它应用于由进程正在执行的命名块的时候，它会将这个进程中止。disable fork语句与disable的不同之处在于，disable fork会考虑动态的进程父子关系，而disable则使用被关闭块的静态的语法信息。因此，disable应该中止执行一个特定块的所有进程，无论进程是否由调用线程产生分支，而disable fork则仅仅中止那些由调用线程产生的进程。

Group

9.8 进程控制

链接
9.8 进程控制


9.9 精细的进程控制

链接
第九章 进程
SystemVerilog 3.1a语言参考手册
9.9 精细的进程控制
第九章 进程

进程是一个内建的类，一旦一个进程被启动，就允许这个进程访问和控制另外一个进程。用户可以声明进程类型的变量，并且能够通过任务对它们进行安全的传递，或者将它们结合到其它对象中。进程类的原型如下：

Copy Code
class process;
    enum state {FINISHED, RUNNING, WAITING, SUSPENDED, KILLED};

    static function process self();
    function state status();
    task kill();
    task await();
    task suspend();
    task resume();
endclass

进程类型的对象在进程产生的时候在内部产生。用户不能够产生进程类型的对象；调用new不会产生一个新的进程，相反，它还会导致一个错误。进程类不能被扩展。对进程类的扩展会导致一个编译错误。进程类型的对象是唯一的；一旦底层进程中止并且对象的所有引用都被丢弃，那么它们就变成有效的以便复用。

self()函数返回当前进程的句柄，也就是说，一个指向进行调用的进程的句柄。

status() 函数返回进程的状态，这些状态由枚举state定义：

  • FINISHED 进程正常中止。
  • RUNNING 进程当前正在运行（未处于阻塞状态）。
  • WAITING 进程正在一个阻塞语句中等待。
  • SUSPENDED 进程停止了，正在等待重新开始。
  • KILLED 进程被强制销毁（通过kill或disable）。

kill()任务中止指定的进程以及它的所有子进程，也就是说，进程通过fork语句产生的进程会被销毁。如果进程在没有等待某种其它条件（例如一个事件、wait表达式、或延时）的时候被中止，那么进程应该在当前时间步值的某个未指定的时间点被中止。

await()任务允许一个进程等待另外一个进程的结束。在当前的进程中调用这个任务是错误的，也就是说，进程不能等待它自己的结束。

suspend()任务允许一个进程挂起它自己或另外一个进程的执行。如果进程在没有等待某种其它条件（例如一个事件、wait表达式、或延时）的时候被挂起，那么进程应该在当前时间步值的某个未指定的时间点被挂起。多次调用这个方法或者对同一个进程调用这个方法不起任何效果。

resume()任务重新启动先前被挂起的进程。对一个被挂起而又被另外一个条件阻塞的进程会使进程重新敏感于事件表达式，或者等待那个等待条件为“真”，或者等待延时过期。如果等待条件现在为“真”，或者原来的延时已经过期，那么进程被调度到Active或Reactive区域，使得它在当前的时间步值继续执行。对一个挂起它本身的进程调用resume会引起在调用suspend之后的语句上继续执行。

由于将N指定为任务参数，因此下面的例子可以启动任意数目的进程。接下来，任务会等待最后一个进程被启动，然后会等待第一个进程中止。这时，父进程会强行中止所有还没有结束的分支进程。

Copy Code
task do_n_way(int N);
    process job[1:N];

    for (int j=1; j<=N; j++)
        fork
            automatic int k = j;
            begin
                job[j] = process::self();
                ... ;
            end
        join_none

    for (int j=1; j<=N; j++)  // 等待启动所有进程
        wait(job[j] != null);

    job[1].await();  // 等待第一个进程结束

    for (int k=1; k<=N; k++) begin
        if (job[k].status != process::FINISHED)
            job[k].kill();
    end
endtask
Group

第九章 进程

链接
第九章 进程


第十章 任务与函数

链接
主题
SystemVerilog 3.1a语言参考手册
第十章 任务与函数
主题
主题
主题
描述
10.1 简介（一般信息）
Verilog-2001具有静态和自动的任务和函数。在一个模块实例中，会为一个任务或函数的所有调用分配相同的存储空间。自动的任务和函数则为每一个实例分配唯一的、栈式存储空间。

SystemVerilog加入了在静态任务和函数中声明自动变量以及在自动任务和函数中声明静态变量的能力。

SystemVerilog还加入了：

  • 为声明任务和函数端口提供了更多的能力
  • 函数和输出和双向端口
  • void函数
  • 无需一个begin...end块或fork...jion块就可以在一个任务或函数中使用多条语句的能力
  • 在到达任务或函数的结尾之前从任务或函数返回的能力
  • 通过引用而不是值来传递参数的能力
  • 根据名字而不是位置来传递参数值得能力
  • 缺省的参数值
  • 通过直接编程接口（DPI）导入和导出函数的能力

10.2 任务
10.3 函数
10.4 任务与函数的参数传递
SystemVerilog提供了两种方式来为函数和任务传递参数：通过值传递和通过应用传递。参数还可以通过名字以及位置来传递。任务和函数的参数还可以指定缺省值，这就使得调用任务或函数的时候不传递参数。
10.5 导入与导出函数
函数导入和导出的语法如下：
链接
主题


10.1 简介（一般信息）

链接
第十章 任务与函数
SystemVerilog 3.1a语言参考手册
10.1 简介（一般信息）
第十章 任务与函数

Verilog-2001具有静态和自动的任务和函数。在一个模块实例中，会为一个任务或函数的所有调用分配相同的存储空间。自动的任务和函数则为每一个实例分配唯一的、栈式存储空间。

SystemVerilog加入了在静态任务和函数中声明自动变量以及在自动任务和函数中声明静态变量的能力。

SystemVerilog还加入了：

  • 为声明任务和函数端口提供了更多的能力
  • 函数和输出和双向端口
  • void函数
  • 无需一个begin...end块或fork...jion块就可以在一个任务或函数中使用多条语句的能力
  • 在到达任务或函数的结尾之前从任务或函数返回的能力
  • 通过引用而不是值来传递参数的能力
  • 根据名字而不是位置来传递参数值得能力
  • 缺省的参数值
  • 通过直接编程接口（DPI）导入和导出函数的能力
Group

第十章 任务与函数

链接
第十章 任务与函数


10.2 任务

链接
第十章 任务与函数
SystemVerilog 3.1a语言参考手册
10.2 任务
第十章 任务与函数
Copy Code
task_declaration ::= task [lifetime] task_body_declaration   // 引用自附录A.2.7

task_body_declaration ::=
    [interface_identifier.|class_scope] task_identifier;
    {tf_item_declaration}
    {statement_or_null}
    endtask [: task_identifier]
  | [interface_identifier.|class_scope] task_identifier ([tf_port_list]);
    {block_item_declaration}
    {statement_or_null}
    endtask [: task_identifier]

tf_item_declaration ::=
    block_item_declaration
  | tf_port_declaration

tf_port_list ::=
    tf_port_item {, tf_port_item}

tf_port_item ::=
    {attribute_instance}
        [tf_port_direction] data_type_or_implicit
        port_identifier variable_dimension [= expression]

tf_port_direction ::= port_direction | const ref

tf_port_declaration ::=
    {attribute_instance} tf_port_direction data_type_or_implicit list_of_tf_variable_identifiers;

lifetime ::= static | automatic      // 引用自附录A.2.1

signing ::= signed | unsigned        // 引用自附录A.2.2.1

data_type_or_implicit ::=
    data_type
  | [signing] {packed_dimension}

语法 10-1 — 任务语法（摘录自附录A）

Verilog任务声明或者在圆括号（向ANSI C一样）中，或者在声明和方向中具有形式参数。

Copy Code
task mytask1 (output int x, input logic y);
    ...
endtask

task mytask2;
    output x;
    input y;
    int x;
    logic y;
    ...
endtask

每一个形式参数可以具有下列之一的方向：

Copy Code
input   // 在开始的时候拷贝值
output  // 在结束的时候拷贝值
inout   // 在开始的时候拷贝，在结束的时候输出
ref     // 传递引用（参见10.4.2节）

在SystemVerilog中，如果没有指定参数的方向，那么它的缺省方向是输入。一旦指定了一个方向，那么它就成为后续参数的缺省方向。在下面的例子中，形式参数a和b缺省为输入，u和v都是输出。

Copy Code
task mytask3(a, b, output logic [15:0] u, v);
    ...
endtask

每一个形式参数都具有一个数据类型，它或者显式声明，或者从一个缺省类型继承。SystemVerilog中任务参数的缺省类型为logic。

SystemVerilog允许将一个数组声明为任务的形式参数。例如：

Copy Code
// b的声明结果为input [3:0][7:0] b[3:0]
task mytask4(input [3:0][7:0] a, b[3:0], output 3:0][7:0] y[1:0]);
    ...
endtask

Verilog-2001允许将任务声明成自动的，因此所有的形式参数和本地变量都被存储在堆栈当中。SystemVerilog扩展了这种能力，它允许在一个静态任务中将特定的形式参数和本地变量声明成自动的，或者，它也允许在一个自动任务内将特定的形式参数和本地变量声明成静态的。

在SystemVerilog中，多条语句可以在任务声明和endtask之间被写入，这也就意味着begin...end可以被忽略。如果begin...end被忽略，这些语句顺序地执行，这与它们被包含在begin...end组中是一样的。任务中没有任何语句也是合法的。

在Verilog中，当任务到达endtask的时候任务退出。而对于SystemVerilog，在endtask关键字之前可以使用return语句退出任务。

Group

第十章 任务与函数

链接
第十章 任务与函数


10.3 函数

链接
第十章 任务与函数, 主题
SystemVerilog 3.1a语言参考手册
10.3 函数
第十章 任务与函数 | 主题
Copy Code
function_data_type ::= data_type | void       // 引用自附录A.2.6

function_data_type_or_implicit ::=
    function_data_type
  | [signing] {packed_dimension}

function_declaration ::= function [lifetime] function_body_declaration

function_body_declaration ::=
    function_data_type_or_implicit
        [interface_identifier.|class_scope]function_identifier;
    {tf_item_declaration}
    {function_statement_or_null}
    endfunction [: function_identifier]
  | function_data_type_or_implicit
    [interface_identifier.|class_scope] function_identifier ([tf_port_list]);
    {block_item_declaration}
    {function_statement_or_null}
    endfunction [: function_identifier]

lifetime ::= static | automatic      // 引用自附录A.2.1.3

signing ::= signed | unsigned        // 引用自附录A.2.2.1

语法10-2 — 函数语法（摘录自附录A）

Verilog函数声明或者在圆括号（向ANSI C一样）中，或者在声明和方向中具有形式参数。

Copy Code
function logic [15:0] myfunc1(int x, int y);
    ...
endfunction

function logic [15:0] myfunc2;
    input int x;
    input int y;
    ...
endfunction

SystemVerilog扩展了Verilog函数的能力，它允许函数具有与任务相同的形式参数。函数参数的方向如下：

Copy Code
input   // 在开始的时候拷贝值
output  // 在结束的时候拷贝值
inout   // 在开始的时候拷贝，在结束的时候输出
ref     // 传递引用（参见10.4.2节）

如果在函数声明中没有指定形式参数的方向，那么形式参数的缺省方向是输入。一旦指定了一个方向，那么它就成为后续参数的缺省方向。在下面的例子中，形式参数a和b缺省为输入，u和v都是输出：

Copy Code
function logic [15:0] myfunc3(int a, int b, output logic [15:0] u, v);
    ...
endfunction

每一个形式参数都具有一个数据类型，它或者显式声明，或者从一个缺省类型继承。SystemVerilog中任务参数的缺省类型为logic，它与Verilog兼容。SystemVerilog允许将一个数组声明成函数的一个形式参数，例如：

Copy Code
function [3:0][7:0] myfunc4(input [3:0][7:0] a, b[3:0]);
    ...
endfunction

在一个事件表达式中、一个过程连续赋值语句内的表达式中、或者不在一个过程语句中的表达式中调用具有output、inout或ref形式参数的函数是非法的。然而，在这些关联文中将const ref作为函数参数是合法的（参见10.4.2节）。

SystemVerilog允许在函数头和endfunction之间写入多条语句，这也就意味着begin...end可以被忽略。如果begin...end被忽略，这些语句顺序地执行，这与它们被包含在begin...end组中是一样的。任务中没有任何语句也是合法的，在这种情况下，函数返回与函数具有相同名字的隐含变量的当前值。

Group

第十章 任务与函数

主题
主题 | 描述
10.3.1 返回值与void函数 | 在Verilog中，函数必须具有返回值。返回值是通过为函数的名字赋值来完成的。
10.3.2 丢弃函数返回值 | 在Verilog-2001中，函数返回的值必须使用在赋值语句或使用在一个表达式中。调用一个好象没有返回值的函数会导致一个警告信息。通过将函数返回值强制转换成void类型，SystemVerilog允许使用void数据类型来忽略一个函数的返回值。
链接
第十章 任务与函数, 主题


10.3.1 返回值与void函数

链接
10.3 函数
SystemVerilog 3.1a语言参考手册
10.3.1 返回值与void函数
10.3 函数

在Verilog中，函数必须具有返回值。返回值是通过为函数的名字赋值来完成的。

Copy Code
function [15:0] myfunc1 (input [7:0] x,y);
    myfunc1 = x * y - 1; // 返回值赋值给函数名字
endfunction

SystemVerilog允许将函数声明成void类型，它没有一个返回值。对于非void函数，像verilog一样，可以通过为函数名字赋值来返回一个值，或者使用带有一个值的return语句实现。return语句应该过载赋给函数名字的任何值。当使用return语句的时候，非void函数必须使用return指定一个表达式。

Copy Code
function [15:0] myfunc2 (input [7:0] x,y);
    return x * y - 1;    // 使用return语句指定返回值
endfunction

在SystemVerilog中，函数可以返回一个结构体或联合体。在这种情况下，函数内部可以使用一个层次化的名字，以层次化名字起始的函数名字被解释成返回值的一个成员。如果函数名字在函数外使用，这个名字指示整个函数的作用范围。如果函数名字使用在一个层次化的名字当中，它也指示整个函数的作用范围。

void类型的函数作为语句调用，除此之外的函数作为表达式调用：

Copy Code
a = b + myfunc1(c, d);  // 将myfunc1（在上面定义）作为一个表达式调用

myprint(a);             // 将myprint（在下面定义）作为一条语句调用

function void myprint (int a);
    ...
endfunction
Group

10.3 函数

链接
10.3 函数


10.3.2 丢弃函数返回值

链接
10.3 函数
SystemVerilog 3.1a语言参考手册
10.3.2 丢弃函数返回值
10.3 函数

在Verilog-2001中，函数返回的值必须使用在赋值语句或使用在一个表达式中。调用一个好象没有返回值的函数会导致一个警告信息。通过将函数返回值强制转换成void类型，SystemVerilog允许使用void数据类型来忽略一个函数的返回值。

Copy Code
void'(some_function());
Group

10.3 函数

链接
10.3 函数


10.4 任务与函数的参数传递

链接
第十章 任务与函数, 主题
SystemVerilog 3.1a语言参考手册
10.4 任务与函数的参数传递
第十章 任务与函数 | 主题

SystemVerilog提供了两种方式来为函数和任务传递参数：通过值传递和通过应用传递。参数还可以通过名字以及位置来传递。任务和函数的参数还可以指定缺省值，这就使得调用任务或函数的时候不传递参数。

Group

第十章 任务与函数

主题
主题 | 描述
10.4.1 通过值传递 | 通过值传递是向子例程传递参数的缺省机制，它也是Verilog-2001提供的唯一的参数传递机制。这种参数传递机制是通过将每一个参数拷贝到子例程区域的方式实现的。如果子例程是自动的，那么子例程在它的堆栈中保留一个参数的本地拷贝。如果参数在子例程中被改变，那么这种改变在子例程外是不可见得。当参数很大的时候，我们可能不希望拷贝这个参数。而且，有时程序需要与一个没有声明成全局的数据共享一个数据片。 例如，对下面函数的调用会在每次调用函数时拷贝1000个字节。
10.4.2 通过引用传递 | 通过引用传递的参数不会拷贝到子例程区域，相反，一个对原始参数的引用会被传递到子例程。然后子例程可以通过这个引用访问参数数据。通过引用传递的参数必须匹配于等价数据类型。参见5.8.1节，等价类型。而且不允许使用强制类型转换。为了指示通过引用传递的参数，参数声明需要以ref关键字开始。基本语法如下：
10.4.3 缺省参数值 | 为了处理一些共用的情况或者考虑一些不用的参数，SystemVerilog允许子例程声明为每一个单一参数指定一个缺省值。 在一个子例程中声明一个缺省参数的语法如下：
10.4.4 通过名字传递参数 | SystemVerilog允许任务和函数的参数通过名字或位置进行传递。这就允许指定非连续的缺省参数，并能够方便地指定调用中传递的参数。例如：
10.4.5 可选的参数列表 | 如果一个任务或函数没有指定参数，那么紧跟在任务/函数名后面的圆括号()是可选的。这条规则对于要求参数，但所有的参数都指定了缺省值的情况也是适用的。
链接
第十章 任务与函数, 主题


10.4.1 通过值传递

链接
10.4 任务与函数的参数传递
SystemVerilog 3.1a语言参考手册
10.4.1 通过值传递
10.4 任务与函数的参数传递

通过值传递是向子例程传递参数的缺省机制，它也是Verilog-2001提供的唯一的参数传递机制。这种参数传递机制是通过将每一个参数拷贝到子例程区域的方式实现的。如果子例程是自动的，那么子例程在它的堆栈中保留一个参数的本地拷贝。如果参数在子例程中被改变，那么这种改变在子例程外是不可见得。当参数很大的时候，我们可能不希望拷贝这个参数。而且，有时程序需要与一个没有声明成全局的数据共享一个数据片。

例如，对下面函数的调用会在每次调用函数时拷贝1000个字节。

Copy Code
function int crc(byte packet[1000:1]);
    for(int j=1; j<=1000; j++) begin
        crc ^= packet[j];
    end
endfunction
Group

10.4 任务与函数的参数传递

链接
10.4 任务与函数的参数传递


10.4.2 通过引用传递

链接
10.4 任务与函数的参数传递
SystemVerilog 3.1a语言参考手册
10.4.2 通过引用传递
10.4 任务与函数的参数传递

通过引用传递的参数不会拷贝到子例程区域，相反，一个对原始参数的引用会被传递到子例程。然后子例程可以通过这个引用访问参数数据。通过引用传递的参数必须匹配于等价数据类型。参见5.8.1节，等价类型。而且不允许使用强制类型转换。为了指示通过引用传递的参数，参数声明需要以ref关键字开始。基本语法如下：

Copy Code
subroutine(ref type argument);

例如，上一节的例子可以重写为：

Copy Code
function int crc(ref byte packet[1000:1]);
    for(int j=1; j<=1000; j++) begin
        crc ^= packet[j];
    end
endfunction

注意，在这个例子中，除了加入所需的ref关键字外，没有作任何改变。编译器知道现在packet是通过引用寻址的，然而，无论是在被调用者中还是在调用点上，用户都不需要显式地说明这些引用。也就是说，无论对于哪个版本的crc函数，对它的调用都是相同的：

Copy Code
byte packet1[1000:1];
int k = crc(packet1);  // 无论是通过值传递还是通过引用传递，调用方法是一样的

当通过引用传递参数的时候，调用者与子例程共享参数的相同表示，因此，在调用者内或子例程中对参数所作的任何改变对两者都是可见的。对通过引用传递的变量赋值的语义是：在子例程的外部可以立即（在子例程返回之前）看到变量的变化。只有变量才能通过引用传递，线网则不允许这样做。

通过引用传递的参数必须完全匹配，当通过引用传递参数的时候，不可能有promotion、转换、或自动的强制类型转换。特别地，数组参数必须在类型和所有的维数上完全匹配。固定尺寸的数组不能与动态数组混合，反之亦然。

通过引用传递参数是一个唯一的参数传递限定符，它不同于input、output、或inout。将ref和任何其它的方向限定符结合在一起使用是非法的。例如，下列的声明会导致一个编译错误：

Copy Code
task incr(ref input int a); // 不正确：不能使用ref限定

ref参数类似于一个inout参数，它们的不同之处在于一个inout参数会被拷贝两次：当子例程被调用的时候完成一个真实值到参数的拷贝，当子例程返回的时候完成一个参数到真实值的拷贝。传递对象句柄也没有例外，当它作为ref或inout参数传递的时候具有相似的语义，因此，一个对象句柄的ref除了允许修改对象内容外，它还允许改变对象句柄（例如指定一个新的对象）。

为了保护通过引用传递的参数不被一个子例程修改，可以将const限定符与ref一起使用，用来表明尽管这个参数是通过引用传递，但它是一个只读变量。

Copy Code
task show (const ref byte [] data);
    for (int j = 0; j < data.size; j++)
        $display(data[j]); // 数据可以被读出但不能被修改
endtask

当形式参数作为一个const ref声明的时候，子例程不能改变这个变量，试图改变变量会产生一个编译错误。

Group

10.4 任务与函数的参数传递

链接
10.4 任务与函数的参数传递


10.4.3 缺省参数值

链接
10.4 任务与函数的参数传递
SystemVerilog 3.1a语言参考手册
10.4.3 缺省参数值
10.4 任务与函数的参数传递

为了处理一些共用的情况或者考虑一些不用的参数，SystemVerilog允许子例程声明为每一个单一参数指定一个缺省值。

在一个子例程中声明一个缺省参数的语法如下：

Copy Code
subroutine([direction] [type] argument = default_value);

可选的direction可以是input、inout、或ref（不能指定输出端口的缺省值）。

default_value是一个表达式。每次子例程被调用的时候，这个表达式会在调用者的作用范围内计算。表达式的元素必须在子例程的作用范围内可见，并且，如果使用的话，也需要在调用者的作用范围内可见。如果没有使用缺省值，表达式不需要被计算并且不需要在调用者的作用范围内可见。注意，缺省值仅允许使用ANSI风格的声明。

当调用子例程的时候，具有缺省值得参数可以从调用中忽略并且编译器应该插入它们对应的值。未指定的参数（空参数）可以用作缺省参数的占位符，这就允许使用非连续的缺省参数。如果一个未指定的参数被用于一个没有缺省值的参数，软件工具会发布一个编译器错误。

Copy Code
task read(int j=0, int k, int data=1);
    ...
endtask;

这个例子声明了一个任务，read()，它具有两个缺省参数，j和data。接着这个任务就可以使用不同的缺省参数调用：

Copy Code
read( , 5);      // 等价于read(0, 5, 1);
read(2, 5);      // 等价于read(2, 5, 1);
read( , 5,  );   // 等价于read(0, 5, 1);
read( , 5, 7);   // 等价于read(0, 5, 7);
read(1, 5, 2);   // 等价于read(1, 5, 2);
read();          // 错误；k没有缺省值
Group

10.4 任务与函数的参数传递

链接
10.4 任务与函数的参数传递


10.4.4 通过名字传递参数

链接
10.4 任务与函数的参数传递
SystemVerilog 3.1a语言参考手册
10.4.4 通过名字传递参数
10.4 任务与函数的参数传递

SystemVerilog允许任务和函数的参数通过名字或位置进行传递。这就允许指定非连续的缺省参数，并能够方便地指定调用中传递的参数。例如：

Copy Code
function int fun(int j=1, string s="no");
    ...
endfunction

fun函数可以用如下方式调用：

Copy Code
fun(.j(2), .s("yes")); // fun(2, "yes");
fun(.s("yes"));        // fun(1, "yes");
fun(, "yes");          // fun(1, "yes");
fun(.j(2));            // fun(2, "no");
fun(.s("yes"), .j(2)); // fun(2 , "yes");
fun(.s(), .j());       // fun(1 , "no");
fun(2);                // fun(2, "no");
fun();                 // fun(1, "no");

如果自变量具有缺省值，那么它们当作模块实例的参数一样地对待。如果自变量没有缺省值，那么它们必须被指定一个值，否则编译器应该发布一个错误。

如果在一个子例程的调用中既使用了通过位置传递又使用了通过名字传递，那么所有位置自变量必须在命名自变量的前面。下面，使用上面相同的例子：

Copy Code
fun(.s("yes"), 2); // 非法
fun(2, .s("yes")); // 正确
Group

10.4 任务与函数的参数传递

链接
10.4 任务与函数的参数传递


10.4.5 可选的参数列表

链接
10.4 任务与函数的参数传递
SystemVerilog 3.1a语言参考手册
10.4.5 可选的参数列表
10.4 任务与函数的参数传递

如果一个任务或函数没有指定参数，那么紧跟在任务/函数名后面的圆括号()是可选的。这条规则对于要求参数，但所有的参数都指定了缺省值的情况也是适用的。

Group

10.4 任务与函数的参数传递

链接
10.4 任务与函数的参数传递


10.5 导入与导出函数

链接
第十章 任务与函数
SystemVerilog 3.1a语言参考手册
10.5 导入与导出函数
第十章 任务与函数

函数导入和导出的语法如下：

Copy Code
dpi_import_export ::=            // 引用自附录A.2.6
    import "DPI" [dpi_function_import_property] [c_identifier =] dpi_function_proto;
  | import "DPI" [dpi_task_import_property] [c_identifier =] dpi_task_proto;
  | export "DPI" [c_identifier =] function function_identifier;
  | export "DPI" [c_identifier =] task task_identifier;

dpi_import_property ::= context | pure

dpi_function_proto ::= function_prototype

语法10-3 — 导入和导出语法（摘录自附录A）

无论是import还是export，c_identifier都是外部函数的名字（导入/导出），function_identifier是同一个函数在SystemVerilog中的名字。如果没有显式地指定c_identifier，那么它应该与SystemVerilog函数的function_identifier相同。如果并且仅仅如果c_identifier中包含了在C语言函数表示中无效的字符才应该产生错误。

通过为几个fnames提供相同的c_identifier，几个SystemVerilog函数可以映射到相同的外部函数。注意：正像下一段所定义的那样，所有的这些SystemVerilog函数必须具有相同的自变量类型。

对于任何给定的c_identifier，所有的声明，无论其作用范围如何，都必须具有完全相同的函数签名。函数签名包括返回类型、数目、顺序、方向以及每一个自变量的类型。每一个类型包括维数以及任何数组/数组维数。对于import声明，自变量可以是开放数组。开放数组在27.4.6.1节中定义。签名还包括与一个导入定义相关联的pure/context限定符。

对于一个给定的function_identifier，在任意给定的作用范围内，仅仅允许一个import或export声明。更为特别的是，对于一个import，在给定的作用范围内，import必须是function_identifier的唯一声明。对于一个export，函数必须在export发生并且在这个作用范围中function_identifier只有一个导出的作用范围内声明。

对于导出的函数，导出的函数必须在包含export "DPI"声明的相同的作用范围内声明。仅仅可以导出SystemVerilog函数（特别地，这就将一个类方法的导出排除在外）。

注意：与任何普通的SystemVerilog函数相同，以这种方式声明的import "DPI"函数可以被层次化引用调用。从SystemVerilog的角度看，导出一个SystemVerilog函数不会改变函数本来的语义和行为（也就是说，除了导出的函数可以被C语言调用者访问外，它在SystemVerilog中的使用没有任何特殊之处）。

只有不带有output或inout自变量的非void函数才可以被指定成pure。在对应的SystemVerilog外部声明中指定成pure的函数应该没有边带效应；它们的结果需要仅仅依赖于输入自变量的值。这样的函数的调用可以被SystemVerilog编译器的优化所删除，或者被具有相同输入自变量值的先前的计算结果所替代。

特别地，一个pure函数假定不会间接（也就说通过调用其它函数）或直接地执行下列操作：

  • 执行文件操作
  • 以尽可能广泛的含义读或写任何东西，包括I/O、环境变量、来自操作系统的对象、或者来自于程序或其它进程、共享内存、socket等的对象。
  • 访问任何稳固的数据，例如全局或静态变量。

如果一个pure函数没有遵从上面的限制，SystemVerilog编译器优化可能会因为删除调用或使用不正确的结果而导致一个不希望的行为。

一个未限定的导入函数可以具有边带效应，但除了通过它的自变量提供的信号外，它不能读或修改任何SystemVerilog信号。未限定的导入不应该调用导出的SystemVerilog函数。

具有context限定符的导入函数可以调用导出的SystemVerilog函数，可以读或写那些除了使用它们的自变量传递、通过使用其它接口或作为调用导出的SystemVerilg函数的边带效应传递的信号外的SystemVerilog信号。context函数应该总是被隐含地提供了一个代表完全限定的实例名的作用范围，在这个作用范围中提供了导入声明（也就是说，一个导入函数总是运行在导入声明出现的实例中）。这与SystemVerilog函数具有相同的语义，它也是运行于它们被定义的范围内，而不是调用者的作用范围内。

导入context函数可以具有边带效应，并且可以使用其它SystemVerilog接口（包括但不限于VPI）。然而必须注意，声明一个导入context函数不会自动地使任何其它仿真器接口有效。为了使VPI访问（或任何其它接口访问）成为可能，仍然需要使用恰当的在实现中定义的机制来使能这些接口。还需要注意，DPI调用不会自动地创建或提供任何句柄或任何可能被其它接口所需要的特殊环境。用于有责任创建、管理或处理其它接口所需要的句柄/环境。svGetScopeName()及相关的函数提供了一个从DPI到其它接口的命名的链接。如果当前的DPI关联文指向一个定义了命名函数的实例的时候，只能调用导出的函数。

为了访问在任何其它作用范围定义的函数，外部语言代码必须恰当地改变DPI关联文。试图从并不直接可见的范围调用一个导出的SystemVerilog函数会导致一个运行时错误。如果处理这样的错误取决于具体的实现。如果一个导入函数需要调用一个当前范围内不可见的导出函数，它需要通过svSetScope将当前作用范围改变到对导出函数具有可见性的作用范围。在概念上，这等价于在SystemVerilog中进行一个层次化的限定函数调用。在一个导出函数的调用过程中，应该保留SystemVerilog关联文，即使当前的关联文已经被一个应用程序修改。注意，对于非context导入，没有定义关联文。试图从非context导入中使用任何依赖于context的功能都会导致不可预料的行为。

Group

第十章 任务与函数

链接
第十章 任务与函数


第十一章 类

链接
主题
SystemVerilog 3.1a语言参考手册
第十一章 类
主题
主题
主题
描述
11.1 简介
SystemVerilog引入了一个面向对象的类数据抽象。类允许对象动态地产生、删除、赋值、以及通过对象句柄访问。对象句柄为语言提供了一种安全的、类似于指针的机制。类提供了继承和抽象建模的能力，这就将不带有任何类型安全性问题的C函数指针的优点引入到了SystemVerilog中，因此，它为Verilog带来了真正的多态性。
11.2 语法
11.3 概述
类是一种数据类型，它包含了数据以及对数据进行操作的子程序（函数和任务）。类的数据被称为类属性，它的子程序被称为方法，无论是类属性还是方法都是类的成员。类属性和方法结合在一起，定义了某种类型的对象的内容和能力。

例如，一个数据包可以是一个对象。它可能具有一个命令域、一个地址、一个序列号、一个时戳、以及一个数据包净荷。另外，一个数据包可以实现多项不同的任务：初始化数据包、设置命令、读取数据包的状态、或者检查序列号。尽管每一个数据包都是不同的，然而作为一个类，数据包具有某些固有的属性，这些固有属性可以在类的定义中进行说明。
11.4 对象（类实例）
类定义了一个数据类型。对象是类的实例。在使用一个类的时候，需要首先声明一个类型为该类的变量（这个变量保存了一个对象句柄），然后使用new函数产生该类的一个对象，然后再将它赋值给变量。
11.5 对象属性
一个对象的数据域可以通过将类属性名限定到一个实例名的方法来使用。继续使用先前的例子，Packet对象p的命令域可以按如下方式使用：
11.6 对象方法
我们可以使用与访问类属性相同的语法来访问一个对象的方法：
11.7 构造器
SystemVerilog没有要求C++那样的复杂的内存分配和释放。一个对象的构造是直接的，并且碎片收集象Java中那样是隐含的并且是自动的。它没有内存泄漏或其它微妙的行为，而这些往往成为C++程序员的噩梦。

SystemVerilog提供了一种机制在产生对象的时候初始化一个实例。当对象被产生的时候，例如：
11.8 静态类属性
前面的例子仅仅声明了实例类属性。每一个类的实例（也就是Packet类型的每一个对象）的每一个变量都有它自己的拷贝。有时要求所有的实例共享变量的一个版本。这些类属性使用关键字static产生。下面的例子演示了一个类的所有实例需要访问一个共用的文件描述符的情况：
11.9 静态方法
方法也可以被声明成静态的。一个静态方法遵从于所有的类范围和访问规则，但在表现上它就像一个常规的子例程一样可以在类的外部被调用，即使没有该类的实例。一个静态方法不能访问非静态的成员（类属性和方法），但它可以直接访问静态类属性或调用同一个类的静态方法。在一个静态方法体内部访问非静态成员或访问特殊的this句柄是非法的，并且会导致一个编译错误。静态方法不能是虚拟的。
11.10 this
this关键字被用来明确地引用当前实例的类属性或类方法。this关键字指示了一个预定义的对象句柄，这个句柄引用了被用来调用this在其中使用的子例程的对象。this关键字应该仅仅使用在非静态的类方法中，否则会发布一个错误。例如，下面的声明是一个用来编写初始化任务的基本方法：
11.11 赋值、重命名与拷贝
声明一个类变量仅仅产生一个名字，这个名字表示了一个对象。因此：
11.12 继承与子类
前一节定义了一个称为Packet的类。我们可以扩展这个类以便使packet串接在一起形成一个链表。一种解决方案是产生一个新的被称为LinkedPacket的类，它包含一个类型为Packet的变量：packet_c。

为了引用Packet类属性，需要引用变量packet_c。
11.13 过载成员
子类对象也是它们的父类对象的有效表示。例如，每一个LinkPacket对象都是一个完全合法的Packet对象。

一个LinkedPacket对象的句柄可以赋值到一个Packet变量：
11.14 super
super关键字在一个继承类的内部使用，可以用来引用其父类的成员。当父类成员被继承类成员过载的时候就有必要使用super关键字来访问负类的成员。
11.15 强制类型转换
将一个子类变量赋值给层次树中较高的类变量是合法的。将一个超类变量直接赋值给一个子类变量则是非法的。然而，如果超类句柄引用了指定子类的句柄，那么将一个超类句柄赋值给一个子类变量则是合法的。

为了检查赋值是否合法，需要使用动态强制类型转换函数$cast（参见3.15节）。

$cast()的语法如下：
11.16 串接构造器
一个子类在实例化的时候会调用类方法new()。在函数中定义的任何代码执行之前，new()执行的一个动作是调用其超类的new()方法，并且会沿着继承树按这种方式一直向上调用。因此，所有的构造器都会按正确的顺序调用，它们都是起始于根基类并结束于当前的类。

如果超类的初始化方法需要参数，那么会有两种选择：一种选择是总是提供相同的参数，另外一种选择是使用super关键字。如果参数总是相同的，那么它们可以在被扩展的时候指定：
11.17 数据隐藏与封装
到目前为止，所有的类属性和方法都毫无限制地在类外可见。然而，我们有时希望通过隐藏类属性和类方法的名字来限制在类的外部访问类属性和类方法。这就使得其它程序员能够不依赖于一个特定的实现，而且它还防止仅对类内部有效的类属性被偶然地修改。当所有的数据都变成隐藏的（仅能被公共方法访问），代码的维护和测试都变得更加容易。

在SystemVerilog中，未被限定的类属性和方法是公共的，它们对访问对象名字的任何人都是有效的。

一个被标识成local的成员仅对类内的方法有效。而且这些本地成员在子类内是不可见得。当然，访问本地类属性或方法的非本地方法可以被继承，并且作为子类的方法它可以正确地工作。

除了可以被继承以及对子类可见外，一个被标识成protected的类属性或方法具有本地成员的所有特性。

注意：在类的内部，一个本地方法或类属性可以被引用，即使它处于一个不同的实例中。例如：
11.18 常量类属性
与任何其它SystemVerilog变量一样，类属性可以通过const声明成只读的。然而，由于类属性是动态的对象，类属性允许两种形式的只读变量：全局常量和实例常量。

全局常量类属性是那些在声明中包含了初始值得常量类属性。它们与其它的const变量类似，也就是它们不能在除声明之外的其它地方赋值。
11.19 抽象类与虚拟方法
我们可以产生一组类，它们可以看作是来源于一个共用的基类。例如，一个类型为BasePacket的公用基类设置了一个包的初始结构，但这个结构并不完整，因此它永远也不会被实例化。然而从这个基类开始，我们可以派生许多子类，例如以太网包、令牌环包、GPSS包、卫星包。这些包的每一个可能看上去很相似，它们都需要相同的方法集合，但它们在内部的实现细节上则存在明显的不同。

一个基类设置了其子类的原型。由于设置基类的目的就不是为了实例化，所以可以将类指定成virtual以便使其变得抽象：
11.20 多态性：动态方法查找
多态性使得超类中的一个变量能够保存子类对象，并且能够直接从超类变量中引用这些子类的方法。考虑一个例子，假设Packet对象的基类BasePacket通过虚拟函数定义了通常由它的子类使用的所有公开方法（例如send、receive、print等）。这时，尽管BasePacket是抽象的，它仍然可以用来声明一个变量：
11.21 类范围解析操作符 ::
类范围操作符 :: 被用来指定在一个类作用范围内定义的一个标识符。它具有下列形式：
11.22 块外声明
如果能够将方法定义放在类声明体的外部，那将是很方便的。这个功能可以通过两个步骤完成。首先，在类声明体内声明方法的原型（无论它是任务还是函数）、任何限定符（local、protected或virtual）、以及完整的参数说明加上extern限定符。extern限定符指示方法体（它的实现）在类声明的外部。接着，在类声明的外部声明完整的方法（与原型类似但没有限定符），并将这个方法绑定回它所属的类：使用一对冒号（::）将方法名限定为类名字。
11.23 参数化的类
如果定义一个基本类，它的对象在实例化的时候可以具有不同的数组尺寸或数据类型，那么这种功能通常很有用。我们可以不必为每一个尺寸或类型编写相同的代码，并且可以为本质上不同并且不可互换的对象使用同一个说明（这与C++的类模板类似）。

普通的Verilog参数机制可以用来参数化一个类：
11.24 typedef类
有时一个类变量需要在类本身被声明之前声明。例如，如果两个类中的每一个类都需要另外一个类的句柄。在编译器处理第一个类的声明期间，编译器遇到了第二个类的引用，而这个引用是未定义的，因此编译器会将它标记为一个错误。

通过使用typedef来为第二个类提供提前声明就可以解决这个问题：
11.25 类与结构体
SystemVerilog加入了面向对象的类结构。从表面上看，类与结构体似乎提供了等价的功能，似乎只需要其中的一个就足够了。然而，事实并非如此；类在下述四个基本方面与结构体是不同的：

  1. SystemVerilog结构体是严格的静态对象；它们或者在一个静态的存储位置（全局或模块的作用范围）或者在一个自动任务的堆栈中产生。相反，SystemVerilog对象（也就是类实例）则是动态的，它们的声明不会产生对象，产生对象是通过调用new实现的。
  2. SystemVerilog结构体是类型兼容的，只要它们的位尺寸是相同的，因此拷贝具有不同的构成但尺寸相等的结构体是合法的。相反，SystemVerilog对象具有严格强类型。将一种类型的对象拷贝到另外一个类型的对象是不被允许的。
  3. SystemVerilog对象使用句柄实现，因此它提供了类似于C语言指针的功能。但SystemVerilog不允许为其它类型产生句柄，因此，与C语言不同的是，能够保证SystemVerilog句柄是安全的。
  4. SystemVerilog对象构成了面向对象数据抽象的基础，它提供了真正的多态性。类实例、抽象类、以及动态强制类型转换提供了强大的机制，它远远超过了结构体仅能提供的封装机制。

11.26 内存管理
对象、字符串、动态数组、以及联合数组的内存是动态分配的。当创建对象的时候，SystemVerilog会分配更多的内存。当对象不再需要的时候，SystemVerilog自动地释放内存以便这些内存能够被重新使用。自动的内存管理系统是SystemVerilog的整体组成部分。如果没有自动的内存管理，SystemVerilog的多线程、重进入环境会增加许多导致用户出错的机会。一个手工的内存管理系统（就像C语言的malloc和free所提供的那样）是不够的。

例如，考虑下面的例子：
链接
主题


11.1 简介

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.1 简介
第十一章 类

SystemVerilog引入了一个面向对象的类数据抽象。类允许对象动态地产生、删除、赋值、以及通过对象句柄访问。对象句柄为语言提供了一种安全的、类似于指针的机制。类提供了继承和抽象建模的能力，这就将不带有任何类型安全性问题的C函数指针的优点引入到了SystemVerilog中，因此，它为Verilog带来了真正的多态性。

Group

第十一章 类

链接
第十一章 类


11.2 语法

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.2 语法
第十一章 类
Copy Code
class_declaration ::=          // 引用自附录A.1.3
    [virtual] class [lifetime] class_identifier [parameter_port_list]
        [extends class_type[(list_of_arguments)]];
        {class_item}
    endclass [ : class_identifier]

class_item ::=                // 引用自附录A.1.8
    {attribute_instance} class_property
  | {attribute_instance} class_method
  | {attribute_instance} class_constraint
  | {attribute_instance} type_declaration
  | {attribute_instance} class_declaration
  | {attribute_instance} timeunits_declaration

class_property ::=
    {property_qualifier} data_declaration
  | const {class_item_qualifier} data_type const_identifier [= constant_expression];

class_method ::=
    {method_qualifier} task_declaration
  | {method_qualifier} function_declaration
  | extern {method_qualifier} method_prototype;
  | {method_qualifier} class_constructor_declaration
  | extern {method_qualifier} class_constructor_prototype

class_constructor_prototype ::=
    function new ([tf_port_list]);

class_constraint ::=
    constraint_prototype
  | constraint_declaration

class_item_qualifier ::=
    static
  | protected
  | local

property_qualifier ::=
    rand
  | randc
  | class_item_qualifier

method_qualifier ::=
    virtual
  | class_item_qualifier

method_prototype ::=
    task_prototype;
  | function_prototype;

class_constructor_declaration ::=
    function [class_scope] new [([tf_port_list])];
        {block_item_declaration}
        [super . new [(list_of_arguments)];]
        {function_statement_or_null}
    endfunction [: new]

语法 11-1—类语法（摘录自附录A）

Group

第十一章 类

链接
第十一章 类


11.3 概述

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.3 概述
第十一章 类

类是一种数据类型，它包含了数据以及对数据进行操作的子程序（函数和任务）。类的数据被称为类属性，它的子程序被称为方法，无论是类属性还是方法都是类的成员。类属性和方法结合在一起，定义了某种类型的对象的内容和能力。

例如，一个数据包可以是一个对象。它可能具有一个命令域、一个地址、一个序列号、一个时戳、以及一个数据包净荷。另外，一个数据包可以实现多项不同的任务：初始化数据包、设置命令、读取数据包的状态、或者检查序列号。尽管每一个数据包都是不同的，然而作为一个类，数据包具有某些固有的属性，这些固有属性可以在类的定义中进行说明。

Copy Code
class Packet;
    // 数据或类属性
    bit [3:0] command;
    bit [40:0] address;
    bit [4:0] master_id;
    integer time_requested;
    integer time_issued;
    integer status;

    // 初始化
    function new();
        command = IDLE;
        address = 41'b0;
        master_id = 5'bx;
    endfunction

    // 方法
    // 公共访问入口点
    task clean();
        command = 0;
        address = 0;
        master_id = 5'bx;
    endtask

    task issue_request(int delay);
        // 向总线发送请求
    endtask

    function integer current_status();
        current_status = status;
    endfunction
endclass

一个通常的惯例是以大写字母形式书写类名字的第一个字母，这样我们能够很容易地识别类声明。

Group

第十一章 类

链接
第十一章 类


11.4 对象（类实例）

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.4 对象（类实例）
第十一章 类

类定义了一个数据类型。对象是类的实例。在使用一个类的时候，需要首先声明一个类型为该类的变量（这个变量保存了一个对象句柄），然后使用new函数产生该类的一个对象，然后再将它赋值给变量。

Copy Code
Packet p;  // 声明一个类型为Packet的变量
p = new;   // 将变量初始化成Packet新分配的一个对象

变量p保存了一个对象句柄，该句柄指向了Packet类的一个对象。

缺省情况下，未初始化的对象句柄被设置成一个特殊值null。我们可以通过将一个对象的句柄与null进行比较来确定对象是否已被初始化。

例如：下面的任务task1检查是否对象已经被初始化。如果没有，它会通过new命令产生一个新的对象。

Copy Code
class obj_example;
    ...
endclass

task task1(integer a, obj_example myexample);
    if (myexample == null) myexample = new;
endtask

通过一个null对象句柄访问非静态成员（参见11.8节）或虚拟方法（参见11.19节）是非法的。使用一个null对象的无效访问会产生不确定的结果，并且实现工具可以发布一个错误信息。

SystemVerilog对象使用一个对象句柄来引用。在C语言指针和SystemVerilog对象句柄之间存在许多不同之处。在怎样使用C语言指针上面，C语言给编程者提供了许多自由。而SystemVerilog对象句柄的使用则存在许多限制。例如，C语言指针可以递增，而SystemVerilog对象句柄则不能。除了对象句柄外，3.6节引入了chandle数据类型，它可以与DPI直接编程接口一起使用（参见第二十七章）。

表11-1：指针和句柄类型的比较

操作 | C指针 | SV对象句柄 | SV chandle
算术运算（例如递增） | 允许 | 不允许 | 不允许
指向任意数据类型 | 允许 | 不允许 | 不允许
当为null时废弃 | 错误 | 不允许 | 不允许
强制类型转换 | 允许 | 受限制 | 不允许
赋值为一个数据类型的地址 | 允许 | 不允许 | 不允许
未引用的对象被当作无用数据（垃圾数据）收集 | 不是 | 是的 | 不是
缺省值 | 未定义 | null | null
指向类 | (C++) | 允许 | 不允许
Group

第十一章 类

链接
第十一章 类


11.5 对象属性

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.5 对象属性
第十一章 类

一个对象的数据域可以通过将类属性名限定到一个实例名的方法来使用。继续使用先前的例子，Packet对象p的命令域可以按如下方式使用：

Copy Code
Packet p = new;
p.command = INIT;
p.address = $random;
packet_time = p.time_requested;

除线网类型外的任何数据类型都可以声明成一个类属性。线网类型之所以不能声明成类属性是因为这种类型与动态分配的数据不兼容。

Group

第十一章 类

链接
第十一章 类


11.6 对象方法

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.6 对象方法
第十一章 类

我们可以使用与访问类属性相同的语法来访问一个对象的方法：

Copy Code
Packet p = new;
status = p.current_status();

注意，不能对status作如下的赋值：

Copy Code
status = current_status(p);

面向对象编程的焦点是对象（在上面的例子中是Packet）而不是函数调用。另外，对象是自包含的，它使用自己的方法来处理自己的属性。所以对象不能作为一个参数传递给current_status()。一个类属性可以被这个类的方法自由地使用，但每一个方法只能访问与它的对象（也就是它的实例）相关联的属性。

Group

第十一章 类

链接
第十一章 类


11.7 构造器

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.7 构造器
第十一章 类

SystemVerilog没有要求C++那样的复杂的内存分配和释放。一个对象的构造是直接的，并且碎片收集象Java中那样是隐含的并且是自动的。它没有内存泄漏或其它微妙的行为，而这些往往成为C++程序员的噩梦。

SystemVerilog提供了一种机制在产生对象的时候初始化一个实例。当对象被产生的时候，例如：

Copy Code
Packet p = new;

系统执行与这个类关联的new函数：

Copy Code
class Packet;
    integer command;

    function new();
      command = IDLE;
    endfunction
endclass

注意：new现在被用在两个具有不同语义的完全不同的关联文中。变量声明产生了Packet类的一个对象。在产生这个实例的过程中，new函数被调用，在这个过程中，任何要求的特殊初始化都会完成。new函数也被称作是类构造器。

new操作被定义成一个没有返回类型的函数，象任何其它函数一样，它必须是无阻塞的。尽管new没有指定一个返回类型，但赋值语句左侧的部分会决定它的返回类型。

在声明中包括了一个初始化器的类属性在用户定义的类构造器被执行之前完成初始化。因此，初始化器的值可以被类构造器过载。

每一个类都有一个缺省（内建）的new方法。缺省构造器首先调用它的父类构造器（super.new()，在11.14节中描述），然后继续将当前对象的每一个成员初始化成它的初始值（或未初始化的值）。

向构造器传递参数也是可能的，这就允许一个对象的运行时定制：

Copy Code
Packet p = new(STARTUP, $random, $time);

其中Packet中的new初始化任务可能具有如下的形式：

Copy Code
function new(int cmd=IDLE, bit[12:0] adrs=0, int cmd_time);
    command = cmd;
    address = adrs;
    time_requested = cmd_time;
endfunction

对其中自变量的规定与任何其它过程子例程相同，例如缺省参数的使用。

Group

第十一章 类

链接
第十一章 类


11.8 静态类属性

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.8 静态类属性
第十一章 类

前面的例子仅仅声明了实例类属性。每一个类的实例（也就是Packet类型的每一个对象）的每一个变量都有它自己的拷贝。有时要求所有的实例共享变量的一个版本。这些类属性使用关键字static产生。下面的例子演示了一个类的所有实例需要访问一个共用的文件描述符的情况：

Copy Code
class Packet;
    static integer fileId = $fopen("data","r");

现在，fileID应该仅仅被产生和初始化一次。此后，每一个Packet对象可以使用统一的方式访问文件描述符：

Copy Code
Packet p;
c = $fgetc(p.fileID);

注意：对于静态类属性，无需产生一个该类型的对象就可以直接使用。

Group

第十一章 类

链接
第十一章 类


11.9 静态方法

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.9 静态方法
第十一章 类

方法也可以被声明成静态的。一个静态方法遵从于所有的类范围和访问规则，但在表现上它就像一个常规的子例程一样可以在类的外部被调用，即使没有该类的实例。一个静态方法不能访问非静态的成员（类属性和方法），但它可以直接访问静态类属性或调用同一个类的静态方法。在一个静态方法体内部访问非静态成员或访问特殊的this句柄是非法的，并且会导致一个编译错误。静态方法不能是虚拟的。

Copy Code
class id;
    static int current = 0;
    static function int next_id();
        next_id = ++current;  // 正确，访问静态类属性
    endfunction
endclass

一个静态方法不同于一个具有静态生命周期的方法。前者指的是类内部的方法的生命周期，而后者指的是任务内部的参数和变量的生命周期。

Copy Code
class TwoTasks;
    static task foo(); ... endtask // 具有自动变量生命周期的静态类方法

    task static bar(); ... endtask // 具有静态变量生命周期的非静态类方法

endclass

缺省情况下，类方法的参数和变量具有自动的生命周期。

Group

第十一章 类

链接
第十一章 类


11.10 this

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.10 this
第十一章 类

this关键字被用来明确地引用当前实例的类属性或类方法。this关键字指示了一个预定义的对象句柄，这个句柄引用了被用来调用this在其中使用的子例程的对象。this关键字应该仅仅使用在非静态的类方法中，否则会发布一个错误。例如，下面的声明是一个用来编写初始化任务的基本方法：

Copy Code
class Demo;
    integer x;

    function new(integer x)
        this.x = x;
    endfunction
endclass

现在x既是类的一个属性也是函数new的一个自变量。在函数new中，对x的未限定的应用会通过查看最内层的作用范围来解析，在上面的情况中就是子例程的自变量声明。为了访问实例类属性，它使用this关键字进行限定，用来引用当前的实例。

注意，在编写方法的时候，成员可以使用this限定以便引用当前的实例，但这通常是不必要的。

Group

第十一章 类

链接
第十一章 类


11.11 赋值、重命名与拷贝

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.11 赋值、重命名与拷贝
第十一章 类

声明一个类变量仅仅产生一个名字，这个名字表示了一个对象。因此：

Copy Code
Packet p1;

上面的例子产生了一个变量，p1，它保存了一个类型为Packet的类对象的句柄，但p1的初始值为null。在Packet类型的一个实例被产生之前，对象并不存在，并且p1没有包含一个真实的句柄：

Copy Code
p1 = new;

因此，如果声明了另外一个变量，并且将先前的句柄赋值为新的句柄，就像下面的例子所示：

Copy Code
Packet p2;
p2 = p1;

那么，仍然只有一个对象，它可以使用p1或p2引用。注意：new仅仅执行一次，所以只产生了一个对象。

然而，如果上面的例子按如下的方式重写，那么会产生一个p1的拷贝：

Copy Code
Packet p1;
Packet p2;
p1 = new;
p2 = new p1;

最后一条语句使得new第二次执行，因此产生了一个新的对象p2，它的类属性拷贝自p1。这种方式的拷贝被称作浅拷贝（shallow copy）。所有的变量都被拷贝：整数、字符串、实例句柄等。然而其中包含的对象没有被拷贝，拷贝的是它的句柄；与前面的例子一样，产生了相同对象的两个名字。即使类声明中包含了操作符new的实例化的时候也是如此：

Copy Code
class A;
    integer j = 5;
endclass

class B;
    integer i = 1;
    A a = new;
endclass

function integer test;
    B b1 = new;    // 产生一个B类的对象
    B b2 = new b1; // 产生一个拷贝自b1的对象
    b2.i = 10;     // i在b2中改变，然而在b1中没有改变
    b2.a.j = 50;   // 改变a.j，为b1和b2共享
    test = b1.i;   // test被设置成1（b1.i没有改变）
    test = b1.a.j; // test被设置成50（a.j已经改变了）
endfunction

有几件事需要注意。第一，类属性和实例对象可以直接在类声明中初始化。第二，shallow copy不会拷贝对象。第三，在需要的时候实例限定可以被串接起来以便到达对象或通过对象到达：

Copy Code
b1.a.j               // reaches into a, which is a property of b1
p.next.next.next.val // 通过一系列句柄的串接来获得val

为了实现完整（深度）拷贝，其中每一个东西（包括嵌套的对象）都被拷贝，典型情况下需要定制代码。例如：

Copy Code
Packet p1 = new;
Packet p2 = new;
p2.copy(p1);

其中copy(Packet p)是一个定制的方法，它用来拷贝作为参数传递给它的实例的对象。

Group

第十一章 类

链接
第十一章 类


11.12 继承与子类

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.12 继承与子类
第十一章 类

前一节定义了一个称为Packet的类。我们可以扩展这个类以便使packet串接在一起形成一个链表。一种解决方案是产生一个新的被称为LinkedPacket的类，它包含一个类型为Packet的变量：packet_c。

为了引用Packet类属性，需要引用变量packet_c。

Copy Code
class LinkedPacket;
    Packet packet_c;
    LinkedPacket next;

    function LinkedPacket get_next();
        get_next = next;
    endfunction
endclass

由于LinkedPacket是Packet的一个特例，所以一个更合理的解决方案是扩展Packet类以便产生一个新的子类，这个子类继承父类的成员。例如：

Copy Code
class LinkedPacket extends Packet;
    LinkedPacket next;

    function LinkedPacket get_next();
        get_next = next;
    endfunction
endclass

现在，Packet的所有方法和类成员都是LinkedPacket的一部分，就好像它们在LinkedPacket中定义一样，并且LinkedPacket具有额外的类属性和方法。

父类的方法也可以被过载，这样就可以改变它们的定义。

SystemVerilog所提供的机制被称为单继承，也就是说，每一个子类都由一个单一的父类继承而来。

Group

第十一章 类

链接
第十一章 类


11.13 过载成员

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.13 过载成员
第十一章 类

子类对象也是它们的父类对象的有效表示。例如，每一个LinkPacket对象都是一个完全合法的Packet对象。

一个LinkedPacket对象的句柄可以赋值到一个Packet变量：

Copy Code
LinkedPacket lp = new;
Packet p = lp;

在这种情况下，对p的引用访问Packet类的方法和类属性。因此，例如，如果LinkPacket中的类属性和方法被过载，那么通过p引用这些过载的成员会获得Packet类中的原始成员。从p的角度看，LinkedPacket中的new和所有过载的成员都被隐藏了。

Copy Code
class Packet;
    integer i = 1;

    function integer get();
        get = i;
    endfunction
endclass

class LinkedPacket extends Packet;
    integer i = 2;

    function integer get();
        get = -i;
    endfunction
endclass

LinkedPacket lp = new;

Packet p = lp;

j = p.i;     // j=1，而不是2

j = p.get(); // j=1，不是-1或–2

为了通过一个父类对象（在本例中为p）调用被过载的方法，这个方法需要使用vitual声明（参见11.19节）。

Group

第十一章 类

链接
第十一章 类


11.14 super

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.14 super
第十一章 类

super关键字在一个继承类的内部使用，可以用来引用其父类的成员。当父类成员被继承类成员过载的时候就有必要使用super关键字来访问负类的成员。

Copy Code
class Packet;  // 负类
    integer value;

    function integer delay();
        delay = value * value;
    endfunction
endclass

class LinkedPacket extends Packet; // 继承类
    integer value;

    function integer delay();
        delay = super.delay() + value * super.value;
    endfunction
endclass

成员可以是在上一级声明的成员或者通过类的上一级继承而来。但没有办法到达更高的层次（例如，super.super.count是不允许使用的）。

子类（或继承类）是当前类的扩展。而超类（父类或基类）是扩展到当前类的类，它起始于一个最初的基类。

当在new中使用super的时候，super.new应该是构造器执行的第一条语句。这是因为，超类在当前类之前被初始化，并且，如果用户代码没有提供一个初始化器，那么编译器会自动地调用super.new。

Group

第十一章 类

链接
第十一章 类


11.15 强制类型转换

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.15 强制类型转换
第十一章 类

将一个子类变量赋值给层次树中较高的类变量是合法的。将一个超类变量直接赋值给一个子类变量则是非法的。然而，如果超类句柄引用了指定子类的句柄，那么将一个超类句柄赋值给一个子类变量则是合法的。

为了检查赋值是否合法，需要使用动态强制类型转换函数$cast（参见3.15节）。

$cast()的语法如下：

Copy Code
task $cast(singular dest_handle, singular source_handle);

或者

Copy Code
function int $cast(singular dest_handle, singular source_handle);

当与对象句柄一起使用的时候，$cast()检查source_expr的层次树（super和子类）以便确定它是否包含了dest_handle的类。如果包含的话，$cast()进行赋值。否则会引起错误，有关错误的处理参见3.15节。

Group

第十一章 类

链接
第十一章 类


11.16 串接构造器

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.16 串接构造器
第十一章 类

一个子类在实例化的时候会调用类方法new()。在函数中定义的任何代码执行之前，new()执行的一个动作是调用其超类的new()方法，并且会沿着继承树按这种方式一直向上调用。因此，所有的构造器都会按正确的顺序调用，它们都是起始于根基类并结束于当前的类。

如果超类的初始化方法需要参数，那么会有两种选择：一种选择是总是提供相同的参数，另外一种选择是使用super关键字。如果参数总是相同的，那么它们可以在被扩展的时候指定：

Copy Code
class EtherPacket extends Packet(5);

这个例子将5传递到与Packet相关联的new例程。

一个更加通用的方法是使用super关键字来调用超类构造器：

Copy Code
function new();
    super.new(5);
endfunction

为了使用这个方法，super.new(5)必须是new函数执行的第一条语句。

Group

第十一章 类

链接
第十一章 类


11.17 数据隐藏与封装

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.17 数据隐藏与封装
第十一章 类

到目前为止，所有的类属性和方法都毫无限制地在类外可见。然而，我们有时希望通过隐藏类属性和类方法的名字来限制在类的外部访问类属性和类方法。这就使得其它程序员能够不依赖于一个特定的实现，而且它还防止仅对类内部有效的类属性被偶然地修改。当所有的数据都变成隐藏的（仅能被公共方法访问），代码的维护和测试都变得更加容易。

在SystemVerilog中，未被限定的类属性和方法是公共的，它们对访问对象名字的任何人都是有效的。

一个被标识成local的成员仅对类内的方法有效。而且这些本地成员在子类内是不可见得。当然，访问本地类属性或方法的非本地方法可以被继承，并且作为子类的方法它可以正确地工作。

除了可以被继承以及对子类可见外，一个被标识成protected的类属性或方法具有本地成员的所有特性。

注意：在类的内部，一个本地方法或类属性可以被引用，即使它处于一个不同的实例中。例如：

Copy Code
class Packet;
    local integer i;

    function integer compare (Packet other);
        compare = (this.i == other.i);
    endfunction
endclass

关于封装的一个严格的解释可能是：other.i在当前的包中不应该是可见的，因为它是一个在其实例外引用的本地类属性。然而，在同一个类内这样的引用是被允许的。在这个例子中，this.i应该与other.i比较，并返回逻辑比较的结果。

类成员可以被标识成local或protected；类属性可以进一步定义成const，方法可以进一步定义成virtual。在指定这些修饰符的时候没有预定义的顺序；然而，对于每一个成员它们只能出现一次。既将成员定义成local又定义成protected，或者复制任何其它修饰符都是错误的。

Group

第十一章 类

链接
第十一章 类


11.18 常量类属性

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.18 常量类属性
第十一章 类

与任何其它SystemVerilog变量一样，类属性可以通过const声明成只读的。然而，由于类属性是动态的对象，类属性允许两种形式的只读变量：全局常量和实例常量。

全局常量类属性是那些在声明中包含了初始值得常量类属性。它们与其它的const变量类似，也就是它们不能在除声明之外的其它地方赋值。

Copy Code
class Jumbo_Packet;
    const int max_size = 9 * 1024; // 全局常量
    byte payload[];

    function new(int size);
        payload = new[size > max_size ? max_size : size];
    endfunction
endclass

实例常量在声明中不包含初始值，仅包含const限定符。这种类型的常量可以在运行时赋一个值，但赋值只能在对应的类构造器中完成一次。

Copy Code
class Big_Packet;
    const int size; // 实例常量
    byte payload[];

    function new();
        size = $random % 4096; // 在new中完成一次赋值 -> 正确
        payload = new[size];
    endfunction
endclass

典型情况下，全局常量还被声明成static，因为它们对于类的所有实例都是相同的。然而，一个实例常量不能声明成static，因为它们在构造器不接受所有的赋值。

Group

第十一章 类

链接
第十一章 类


11.19 抽象类与虚拟方法

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.19 抽象类与虚拟方法
第十一章 类

我们可以产生一组类，它们可以看作是来源于一个共用的基类。例如，一个类型为BasePacket的公用基类设置了一个包的初始结构，但这个结构并不完整，因此它永远也不会被实例化。然而从这个基类开始，我们可以派生许多子类，例如以太网包、令牌环包、GPSS包、卫星包。这些包的每一个可能看上去很相似，它们都需要相同的方法集合，但它们在内部的实现细节上则存在明显的不同。

一个基类设置了其子类的原型。由于设置基类的目的就不是为了实例化，所以可以将类指定成virtual以便使其变得抽象：

Copy Code
virtual class BasePacket;

抽象类还可以具有虚拟方法。虚拟方法是一个基本的多态性结构。一个虚拟方法过载所有基类中的一个方法，而一个普通的方法则只能过载该类及其后代类中的一个方法。看待这个问题的一个方面是每个类层次的一个虚拟方法只有一个实现，并且它总是位于最后一个继承类。虚拟方法为子例程提供了原型，所有的信息基本上都可以在一个方法声明的第一行找到：封装标准、参数的类型和数目、如果需要的话还包括返回类型。当子类在以后过载成员方法的时候，它们必须完全地遵从那个原型。因此，虚拟方法的所有版本在所有的子类中看上去都是相同的：

Copy Code
virtual class BasePacket;
    virtual function integer send(bit[31:0] data);
    endfunction
endclass

class EtherPacket extends BasePacket;
    function integer send(bit[31:0] data);
        // 函数体
        ...
    endfunction
endclass

现在，EtherPacket是一个可以被实例化的类。通常，如果一个抽象类具有虚拟方法，为了使子类能够被实例化，所有这些方法都必须被过载（并且拥有一个方法体）。如果任何虚拟方法没有具体的实现，那么子类需要是抽象的。

一个抽象类可以包含只有一个原型而没有具体实现的方法（也就是不完整的类）。一个抽象类不能被实例化，它只能被继承。普通类的方法也可以被声明成虚拟的。在这种情况下，方法必须具有一个方法体。如果这个方法具有一个方法体，那个这个类以及它的子类可以被实例化。

Group

第十一章 类

链接
第十一章 类


11.20 多态性：动态方法查找

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.20 多态性：动态方法查找
第十一章 类

多态性使得超类中的一个变量能够保存子类对象，并且能够直接从超类变量中引用这些子类的方法。考虑一个例子，假设Packet对象的基类BasePacket通过虚拟函数定义了通常由它的子类使用的所有公开方法（例如send、receive、print等）。这时，尽管BasePacket是抽象的，它仍然可以用来声明一个变量：

Copy Code
BasePacket packets[100];

现在，我们可以产生不同包对象的实例，并将它们放入到数组当中：

Copy Code
EtherPacket ep = new;  // extends BasePacket
TokenPacket tp = new;  // extends BasePacket
GPSSPacket gp = new;   // extends EtherPacket
packets[0] = ep;
packets[1] = tp;
packets[2] = gp;

如果数据类型为诸如整数、位和字符串子类的数据类型，那么所有的这些类型都不能被存储到一个单一数组中。然而，使用多态性，这个功能就能够实现。在这个例子中，由于方法被声明成虚拟的，所以可以从超类变量中访问恰当的子类方法，即使编译器在编译的时候并不知道它将要加载哪一个方法。

例如，对于packets[1]：

Copy Code
packets[1].send();

应该调用与TokenPacket类相关联的send方法。在运行的时候，系统能够从合适的类中正确地绑定方法。

这就是多态性工作的一个典型例子，它比非面向对象的框架提供更为强大的能力。

Group

第十一章 类

链接
第十一章 类


11.21 类范围解析操作符 ::

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.21 类范围解析操作符 ::
第十一章 类

类范围操作符 :: 被用来指定在一个类作用范围内定义的一个标识符。它具有下列形式：

Copy Code
class_identifier::{class_identifier::}identifier

范围解析操作符（::）左侧的标识符可以是类名字或者包名字（参见18.2节）。

类和其它的范围可能具有相同的标识符，使用范围解析操作符，我们可以唯一地标识特定类的一个成员。另外，为了消除类范围标识符的歧义，::操作符还可以从类的外部访问静态成员（类属性和方法），并能够在继承类内访问超类的公开和保护元素。

Copy Code
class Base;
    typedef enum {bin, oct, dec, hex} radix;

    static task print(radix r, integer n);
        ...
    endtask
endclass

...

Base b = new;
int bin = 123;
b.print(Base::bin, bin);  // Base::bin与bin是不同的
Base::print(Base::hex, 66);

在SystemVerilog中，类范围操作符应用于一个类的所有静态元素：静态类属性、静态方法、typedef、枚举、结构体、联合体以及嵌套的类声明。类范围解析表达式可以被读取（在表达式中）、写入（在参数或子例程调用中）或触发（在事件表达式中）。它们也可以用作一个类型的名字或一个方法调用。

像模块一样，类是范围并且可以嵌套。嵌套允许隐藏本地名字和资源的本地分配。这在一个新的类型需要作为类实现的一部分时经常很有用。在一个类内声明类型能够阻止命名冲突，并能够避免外界与仅在类内使用的符号之间的混乱。嵌套在一个类范围内的类型声明是公开的，并且可以在类外访问。

Copy Code
class StringList;
    class Node;  // 链表中一个节点的嵌套类
        string name;
        Node link;
    endclass
endclass

class StringTree;
    class Node;   // 二分树中一个节点的嵌套类
        string name;
        Node left, right;
    endclass
endclass
// StringList::Node不同于StringTree::Node

范围解析操作符能够：

  • 从类层次的外部访问静态公开成员（方法和类属性）。
  • 从继承类的内部访问超类的公开或保护的类成员。
  • 从类层次外部或在继承类内部访问类中的类型声明和枚举命名常量。
Group

第十一章 类

链接
第十一章 类


11.22 块外声明

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.22 块外声明
第十一章 类

如果能够将方法定义放在类声明体的外部，那将是很方便的。这个功能可以通过两个步骤完成。首先，在类声明体内声明方法的原型（无论它是任务还是函数）、任何限定符（local、protected或virtual）、以及完整的参数说明加上extern限定符。extern限定符指示方法体（它的实现）在类声明的外部。接着，在类声明的外部声明完整的方法（与原型类似但没有限定符），并将这个方法绑定回它所属的类：使用一对冒号（::）将方法名限定为类名字。

Copy Code
class Packet;
    Packet next;

    function Packet get_next();
        get_next = next;
    endfunction

    // 体外（外部）声明
    extern protected virtual function int send(int value);
endclass

function int Packet::send(int value);
    // 将virtual关键字丢弃，为函数体加入了Packet::
    ...
endfunction

块外方法声明必须与它的原型声明完全一致；语法上的唯一不同点是方法名字前面加入了类名字和范围操作符（::）。

块外方法声明必须在与类声明相同的作用范围内声明。

Group

第十一章 类

链接
第十一章 类


11.23 参数化的类

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.23 参数化的类
第十一章 类

如果定义一个基本类，它的对象在实例化的时候可以具有不同的数组尺寸或数据类型，那么这种功能通常很有用。我们可以不必为每一个尺寸或类型编写相同的代码，并且可以为本质上不同并且不可互换的对象使用同一个说明（这与C++的类模板类似）。

普通的Verilog参数机制可以用来参数化一个类：

Copy Code
class vector #(int size = 1);
    bit [size-1:0] a;
endclass

接下来，这个类的实例就可以像模块或接口一样实例化：

Copy Code
vector #(10) vten;        // 尺寸为10的vector对象
vector #(.size(2)) vtwo;  // 尺寸为2的vector对象
typedef vector#(4) Vfour; // vector尺寸为4的类

当将类型作为参数的时候，这个功能特别有用：

Copy Code
class stack #(type T = int);
    local T items[];

    task push(T a);
        ...
    endtask

    task pop(ref T a);
        ...
    endtask
endclass

上面的类定义了一个基本的stack类，它可以使用任意类型实例化：

Copy Code
stack is;             // 缺省：int类型的堆栈
stack#(bit[1:10]) bs; // 10位向量的堆栈
stack#(real) rs;      // 实数的堆栈

任何类型都可以用作参数，包括用户定义的类型，例如类或结构体。

基本类和真实参数值的组合被称作一个特例（或变种）。类的每一个特例又具有一组单独的静态成员变量（这与C++模板类一致）。为了在多个类特例间共享静态成员变量，这些变量必须放置在一个非参数化的基类中。

Copy Code
class vector #(int size = 1);
    bit [size-1:0] a;
    static int count = 0;

    function void disp_count();
        $display("count: %d of size %d", count, size);
    endfunction
endclass

上面例子中的变量count只能通过对应的disp_count方法访问。对于vector类的每一个特例，count都具有它自己的唯一的拷贝。

为了避免必须在声明中或产生该类的参数中重复特例，我们应该使用typedef：

Copy Code
typedef vector#(4) Vfour;
typedef stack#(Vfour) Stack4;
Stack4 s1, s2;  // 声明Stack4类型的对象

一个参数化的类可以扩展另外一个参数化的类，例如：

Copy Code
class C #(type T = bit); ... endclass           // 基类
class D1 #(type P = real) extends C;            // T的类型为bit（缺省）
class D2 #(type P = real) extends C #(integer); // T的类型为integer
class D3 #(type P = real) extends C #(P);       // T的类型为P

D1类使用基类的缺省类型（bit）参数扩展了基类C。 D2类使用一个integer参数扩展了基类。D3类使用参数化类型（P，它使得扩展类被参数化）扩展了基类C。

Group

第十一章 类

链接
第十一章 类


11.24 typedef类

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.24 typedef类
第十一章 类

有时一个类变量需要在类本身被声明之前声明。例如，如果两个类中的每一个类都需要另外一个类的句柄。在编译器处理第一个类的声明期间，编译器遇到了第二个类的引用，而这个引用是未定义的，因此编译器会将它标记为一个错误。

通过使用typedef来为第二个类提供提前声明就可以解决这个问题：

Copy Code
typedef class C2; // C2被声明成class类型

class C1;
    C2 c;
endclass

class C2;
    C1 c;
endclass

在这个例子中，C2先被声明成class类型，然后再在源代码中进行增强。注意，类结构总是产生一个类型，而不需要使用typedef声明来达到这个目的（使用typedef class ...这样的形式）。这与基本的C++使用一致。

注意：typedef class C2;语句中的class关键字不是必需的，在这条语句中使用class关键字仅仅是为了建立文档的目的。它与typedef C2;语句是等价的并且以相同的方式工作。

Group

第十一章 类

链接
第十一章 类


11.25 类与结构体

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.25 类与结构体
第十一章 类

SystemVerilog加入了面向对象的类结构。从表面上看，类与结构体似乎提供了等价的功能，似乎只需要其中的一个就足够了。然而，事实并非如此；类在下述四个基本方面与结构体是不同的：

  1. SystemVerilog结构体是严格的静态对象；它们或者在一个静态的存储位置（全局或模块的作用范围）或者在一个自动任务的堆栈中产生。相反，SystemVerilog对象（也就是类实例）则是动态的，它们的声明不会产生对象，产生对象是通过调用new实现的。
  2. SystemVerilog结构体是类型兼容的，只要它们的位尺寸是相同的，因此拷贝具有不同的构成但尺寸相等的结构体是合法的。相反，SystemVerilog对象具有严格强类型。将一种类型的对象拷贝到另外一个类型的对象是不被允许的。
  3. SystemVerilog对象使用句柄实现，因此它提供了类似于C语言指针的功能。但SystemVerilog不允许为其它类型产生句柄，因此，与C语言不同的是，能够保证SystemVerilog句柄是安全的。
  4. SystemVerilog对象构成了面向对象数据抽象的基础，它提供了真正的多态性。类实例、抽象类、以及动态强制类型转换提供了强大的机制，它远远超过了结构体仅能提供的封装机制。
Group

第十一章 类

链接
第十一章 类


11.26 内存管理

链接
第十一章 类
SystemVerilog 3.1a语言参考手册
11.26 内存管理
第十一章 类

对象、字符串、动态数组、以及联合数组的内存是动态分配的。当创建对象的时候，SystemVerilog会分配更多的内存。当对象不再需要的时候，SystemVerilog自动地释放内存以便这些内存能够被重新使用。自动的内存管理系统是SystemVerilog的整体组成部分。如果没有自动的内存管理，SystemVerilog的多线程、重进入环境会增加许多导致用户出错的机会。一个手工的内存管理系统（就像C语言的malloc和free所提供的那样）是不够的。

例如，考虑下面的例子：

Copy Code
myClass obj = new;

fork
    task1(obj);
    task2(obj);
join_none

在这个例子中，主进程（产生两个任务分支的那个进程）并不知道什么时候这两个进程会结束对对象obj。类似地，无论是task1还是task2都不知道什么时候另外一个进程不再使用对象obj。从这个简单的例子可以明显看出，单个进程无法获得足够的信息来确定对对象的释放是否安全。对于用户来说，仅存在两个可能的选择：(1)自己要小心谨慎并且永远不回收对象，或者(2)加入某种形式的引用计数，这些计数可以用来确定什么时候回收对象可能是安全的。采用第一个选择会引起系统快速地耗光内存。第二个选择对用户则是一个大的负担，用户除了需要管理他们的testbench外，还需要采用不太理想的机制来管理内存。为了避免这些缺点，SystemVerilog自动地管理所有的动态内存。用户不需要担心悬挂的引用、过早的释放、或者内存泄漏。系统应该自动地回收任何不再被使用的对象。在上面的例子中，用户需要作的就是将不再需要的句柄obj赋值为null。类似地，当一个对象超出范围的时候，系统会隐式地将对象赋值为null。

Group

第十一章 类

链接
第十一章 类


第十二章 随机约束

链接
主题
SystemVerilog 3.1a语言参考手册
第十二章 随机约束
主题
主题
主题
描述
12.1 简介（一般信息）
约束驱动的测试生成方法使得用户能够自动地为功能验证产生测试。随机测试比一个传统的、直接的测试方法更有效率。通过指定约束，我们可以很容易地为难于到达的边界条件产生测试。SystemVerilog允许用户以一种紧凑、明了的方式指定约束。约束接下来会被一个求解器处理，这个求解器用来产生满足约束的随机值。

典型情况下，随机约束在一个面向对象的数据抽象之上指定。它将需要被随机化的数据建模成包含随机变量和用户定义约束的对象。约束确定了可以被赋值给随机变量的有效值。对象很适合于表示复杂的集合数据类型以及诸如以太网包之类的协议。

第12.2节提供了基于对象的随机化和约束编程的概述。本章余下的部分提供了有关随机变量、约束块、以及处理它们的机制的详细信息。
12.2 概述
本章介绍了在对象内产生随机激励的基本概念和用法。SystemVerilog使用一个面向对象的方法来为对象的成员变量赋随机值，它以用户定义的约束为准。例如：
12.3 随机变量
类变量可以使用rand和randc类型修饰符关键字声明成随机的。

在一个类中声明随机变量的语法如下：
12.4 约束块
随机变量的值通过由约束块声明的约束表达式来确定。像任务、函数和变量一样，随机块是类的成员。在一个类中，约束块的名字必须是唯一的。

声明约束块的语法如下：
12.5 随机化方法
12.6 内联约束 — randomize() with
通过使用randomize()...with结构，用户可以在randomize()方法的调用点上声明内联约束。这些额外的约束与对象约束一起应用。

randomize()...with的语法如下：
12.7 使用rand_mode()关闭随机变量
rand_mode()可以用来控制激活或关闭一个随机变量。当一个随机变量处于未激活状态的时候，这个随机变量就好像没有使用rand或randc声明一样。未激活的随机变量不会被rand_mode()方法随机化，并且它们的值会被求解器当作状态变量。所有的随机变量最初都是激活的。

rand_mode()方法的语法如下：
12.8 使用constraint_mode()控制约束
constraint_mode()方法可以用来控制激活或关闭一个约束。当约束处于未激活（关闭）状态时，它不会被randomize()方法所考虑。所有的约束最初都是激活的。

constraint_mode()方法的语法如下：
12.9 动态的约束修改
SystemVerilog中提供了几种方法来动态地修改随机化方法：

  • 蕴涵以及if...else风格的约束允许声明具有判决条件的约束。
  • 可以使用contraint_mode()内建方法来激活或关闭约束块。初始情况下，所有的约束块均处于激活状态。未激活的约束会被randomize()函数忽略。
  • 可以使用rand_mode()内建方法来激活或关闭随机变量。初始情况下，所有的rand和randc变量都处于激活状态。未激活的随机变量会被randomize()函数忽略。
  • 在dist约束中的权重可以被改变，从而影响了被选定集合中特定值出现的概率。

12.10 内联随机变量控制
randomize()方法可以用来临时性地控制一个类实例或对象中的随机变量和状态变量的集合。当调用无参数的randomize方法的时候，它的行为就像前一节所描述的那样，也就是说，它会为对象中所有使用rand或randc声明的随机变量赋新的值，这样所有的约束都会被满足。当调用带有参数的randomize的时候，它的参数指定了该对象内随机变量的完整集合；对象中的所有其它变量都被认为是状态变量。例如，考虑下面的类以及对randomize方法的调用：
12.11 范围变量的随机化 — std::randomize()
内建的类随机化方法对类成员变量执行专有的操作。使用类来对需要随机化的数据建模是一种强大的机制，它使得我们能够产生通用、可复用的包含随机变量的对象，并能够产生可以在以后扩展、继承、约束、过载、使能、关闭、以及从其它对象合并或分离的约束。类及与其关联的随机变量和约束在处理上的方便性使得类非常适合描述和处理随机数据和约束。然而，某些要求较少的问题并不需要类的这些完整的灵活性，它可以使用一个较为简单的机制来随机化不属于一个类的数据。范围随机函数（std::randomize()）使得用户能够随机化当前范围内的数据，而无需定义一个类或实例化一个类对象。

范围随机化函数的语法如下：
12.12 随机数系统函数与方法
12.13 随机稳定性
随机数发生器（RNG）对于线程和对象是本地的。因为被一个线程或对象返回的随机值序列独立于其它线程或对象的RNG，所以这个特性被称为随机稳定性。随机稳定性应用于：

  • 系统随机化调用，$urandom()和$urandom_range()。
  • 对象和进程随机播种方法，srandom()。
  • 对象随机化方法，randomize()。

在面对用户代码小的改变的时候，具有这种特点的测试平台能够展示更加稳定的RNG行为。另外，对于通过手工设置种子的线程和对象，它能够更精确地控制随机值的产生。

12.14 为随机化手工设置种子
每一个对象维护了它自己的内部随机数发生器，这个随机数发生器它的randomize()方法所专用。这就使得对象能够各自独立地被随机化并能够相对于其它的随机化函数独立地调用。当产生一个对象的时候，它的随机数发生器（RNG）能够使用来自产生这个对象的线程的RNG的下一个值设置种子。这个过程被称为层次化的对象播种。

有时我们希望能够使用srandom()方法手工地设置种子。这种功能或者在一个类方法中，或者在类定义的外部完成。

作为一个类方法在内部为RNG设置种子的例子如下：
12.15 随机加权的条件 — randcase
12.16 随机序列产生 — randsequence
分析程序生成器，例如yacc，使用巴科斯-诺尔范式（BNF）或类似的符号来描述被分析语言的文法。因此文法被用来产生一个程序，它能够检查一个标记流是否代表了该语言中一个语法正确的表达方式。SystemVerilog的序列产生器反转了这个过程。它使用文法来随机地产生一个文法所描述的语言的正确的表达方式（也就是一个标记流）。随机序列发生器对于随机地产生结构化的激励序列（例如指令或网络流量模式）非常有用。

序列发生器使用个randsequence块内的一组规则和生成式。randsequence块的语法如下：
链接
主题


12.1 简介（一般信息）

链接
第十二章 随机约束
SystemVerilog 3.1a语言参考手册
12.1 简介（一般信息）
第十二章 随机约束

约束驱动的测试生成方法使得用户能够自动地为功能验证产生测试。随机测试比一个传统的、直接的测试方法更有效率。通过指定约束，我们可以很容易地为难于到达的边界条件产生测试。SystemVerilog允许用户以一种紧凑、明了的方式指定约束。约束接下来会被一个求解器处理，这个求解器用来产生满足约束的随机值。

典型情况下，随机约束在一个面向对象的数据抽象之上指定。它将需要被随机化的数据建模成包含随机变量和用户定义约束的对象。约束确定了可以被赋值给随机变量的有效值。对象很适合于表示复杂的集合数据类型以及诸如以太网包之类的协议。

第12.2节提供了基于对象的随机化和约束编程的概述。本章余下的部分提供了有关随机变量、约束块、以及处理它们的机制的详细信息。

Group

第十二章 随机约束

链接
第十二章 随机约束


12.2 概述

链接
第十二章 随机约束
SystemVerilog 3.1a语言参考手册
12.2 概述
第十二章 随机约束

本章介绍了在对象内产生随机激励的基本概念和用法。SystemVerilog使用一个面向对象的方法来为对象的成员变量赋随机值，它以用户定义的约束为准。例如：

Copy Code
class Bus;
    rand bit[15:0] addr;
    rand bit[31:0] data;
    constraint word_align {addr[1:0] == 2’b0;}
endclass

Bus类建模了一个简化的总线，它具有两个随机变量：addr和data，分别代表总线上的地址和数据。word_align约束指出：addr的随机值必须能够使addr字对齐（低两位为0）。

randomize()方法被调用以便为一个总线对象产生新的随机值：

Copy Code
Bus bus = new;

repeat (50) begin
    if (bus.randomize() == 1)
        $display ("addr = %16h data = %h\n", bus.addr, bus.data);
    else
        $display ("Randomization failed.\n");
end

调用randomize()会为一个对象中的所有的随机变量选择新的值以便所有的约束都为真（满足约束）。在上面的程序test中产生了一个总线对象，接着将这个对象随机化50次。每一次随机化都会检查结果是否成功。如果随机化成功，那么会打印addr和data的新值；如果随机化失败，那么会打印一条错误信息。在这个例子中，仅仅约束了addr的值，而data的值未被约束。未被约束的变量被赋值为它们声明范围内的任意值。

约束编程是一个强大的方法，它使得用户能够构建通用的、可服用的对象，这些对象在以后可以被扩展或约束以便执行特定的功能。这个方法与传统的过程化和面向对象的编程不同，例如在下面这个扩展Bus类的例子中：

Copy Code
typedef enum {low, mid, high} AddrType;

class MyBus extends Bus;
    rand AddrType atype;

    constraint addr_range
    {
        (atype == low ) -> addr inside {[0:15]};
        (atype == mid ) -> addr inside {[16:127]};
        (atype == high) -> addr inside {[128:255]};
    }
endclass

MyBus类从Bus类中继承了所有的随机变量和约束，并加入了一个被称为atype的随机变量，这个随机变量被用来使用另外一个约束控制地址的范围。addr_range约束根据atype的随机值隐含地选择三个范围约束中的一个。当一个MyBus对象被随机化的时候会计算addr、data、和atype的值以便所有的约束都能够满足。使用继承来构建分层的约束系统能够开发通用的模型，这些模型可以被约束以便执行专用的功能。

对象还可以使用randomize() with作进一步约束，这个结构调用randomize()并声明了额外的内联约束：

Copy Code
task exercise_bus (MyBus bus);
    int res;

    // 例子1：限制低地址
    res = bus.randomize() with {atype == low;};

    // 例子2：将地址限制在10和20之间
    res = bus.randomize() with {10 <= addr && addr <= 20;};

    // 例子3: 将数据值限制成2的n次方
    res = bus.randomize() with {data & (data-1) == 0;};
endtask

这个例子演示了有关约束的几个重要特性：

  • 约束可以是任何带有integral类型（bit、reg、logic、integer、enum、压缩结构体等等）的变量和常量表达式。
  • 约束解决器必须能够处理多种等式，例如代数因式分解、复杂的布尔表达式、以及混合整数和位的表达式。在上面的例子中，2的n次方约束使用算术表达式。它还可以用使用移位操作的表达式来定义。例如，1 << n，其中n是一个5位的随机变量。
  • 如果约束存在一个解的话，那么约束求解器必须找到这个解。求解器只有在问题被过约束并且没有随机值的组合能够满足约束的时候才可以失败。
  • 约束双向地影响。在这个例子中，addr的值的选择依赖于atype以及它怎样被约束，并且atype值的选择依赖于addr以及它怎样被约束。所有的表达式操作符都被双向地对待，包括蕴含操作符（->）。
  • 约束仅仅支持两态值。四态值（X或Z）或四态操作符（例如，===、!==）是非法的并且会导致错误。

有时我们希望关闭随机变量的约束。例如，为了故意地产生一个非法的地址（非字对齐的地址）：

Copy Code
task exercise_illegal(MyBus bus, int cycles);
    int res;

    // 关闭字对齐约束
    bus.word_align.constraint_mode(0);

    repeat (cycles) begin
        // 情况1: 限制到小地址
        res = bus.randomize() with {addr[0] || addr[1];};
        ...
    end

    // 重新使能字对齐约束
    bus.word_align.constraint_mode(1);
endtask

constraint_mode()可以用来使能或关闭一个对象中任何命名的约束。在这个例子中，字对齐约束被关闭，接着对象使用其它的约束来随机化以便将低位地址强制成非零值（不再字对齐）。

使能或关闭约束的能力使得用户能够设计约束层次。在这些层次中，最底层的约束可以代表物理限制，这些物理限制通过公用的特性分组成命名的约束块，它们可以独立地使能或关闭。

类似地，rand_mode()方法可以用来使能或关闭任何随机变量。当一个随机变量被关闭的时候，它与其它非随机的变量具有完全一致的行为。

偶尔我们也希望在随机化之前或之后立即执行一些操作。这种功能可以通过两个内建方法完成：pre_randomize()和post_randomize()，这两个方法在随机化之前或之后被自动调用。这些方法可以使用希望的功能来过载：

Copy Code
class XYPair;
    rand integer x, y;
endclass

class MyXYPair extends XYPair
    function void pre_randomize();
        super.pre_randomize();
        $display("Before randomize x=%0d, y=%0d", x, y);
    endfunction

    function void post_randomize();
        super.post_randomize();
        $display("After randomize x=%0d, y=%0d", x, y);
    endfunction
endclass

缺省情况下，pre_randomize()和post_randomize()调用它们过载的父类方法。当pre_randomize()或post_randomize()被过载的时候，必须小心地调用父类方法，除非父类是一个基类（没有父类），否则应该调用基类方法。

随机激励产生能力以及面向对象的基于约束的验证方法使得用户能够快速地开发覆盖了复杂功能的测试，并能够更好地保证设计的正确性。

Group

第十二章 随机约束

链接
第十二章 随机约束


12.3 随机变量

链接
第十二章 随机约束, 主题
SystemVerilog 3.1a语言参考手册
12.3 随机变量
第十二章 随机约束 | 主题

类变量可以使用rand和randc类型修饰符关键字声明成随机的。

在一个类中声明随机变量的语法如下：

Copy Code
class_property ::=           // 引用自附录A.1.8
    {property_qualifier} data_declaration

property_qualifier ::=
    rand
  | randc

语法 12-1 — 随机变量声明语法（摘录自附录A）

  • 求解器可以随机化任何integral类型的单一变量。
  • 数组可以声明成rand或randc，在这种情况下，数组的所有成员元素都被当作rand或randc看待。
  • 动态数组和联合数组可以使用rand或randc声明。数组中的所有元素都被随机化，并会重写先前的任何数据。如果数组元素是对象句柄，所有数组元素的值必须不等于null。我们可以约束单个的数组元素，在这种情况下索引表达式必须是一个文本常量。
  • 使用rand或randc声明的动态数组的尺寸也可以被约束。在这种情况下，数组应该根据尺寸约束被重新调整尺寸，并且会接着随机化所有的数组元素。数组尺寸约束使用尺寸方法进行声明。例如：
Copy Code
rand bit [7:0] len;
rand integer data[];
constraint db {data.size == len;}

变量len具有8位的宽度。随机化器会在8位的范围内（0到255）为len变量计算一个随机值，接着会随机化data数组的第一个len元素。

如果一个动态数组的尺寸没有被约束，那么randomize()会随机化数组中的所有元素。

  • 一个对象句柄可以使用rand声明，在这种情况下，该对象的所有变量和约束都被并发地求解。对象不能使用randc声明。
Group

第十二章 随机约束

主题
主题 | 描述
12.3.1 rand修饰符 | 使用rand关键字声明的变量是标准的随机变量。它们的值在其取值范围内均匀分布。例如：
12.3.2 randc修饰符 | 使用randc声明的变量是周期随机变量，它在一个它们声明范围内的一个随机排列中循环地选择所有的值。周期随机变量只能是bit类型或枚举类型，并且可以被限制到一个最大的尺寸。 为了理解randc，考虑一个两位的随机变量y：
链接
第十二章 随机约束, 主题


12.3.1 rand修饰符

链接
12.3 随机变量
SystemVerilog 3.1a语言参考手册
12.3.1 rand修饰符
12.3 随机变量

使用rand关键字声明的变量是标准的随机变量。它们的值在其取值范围内均匀分布。例如：

Copy Code
rand bit [7:0] y;

这是一个8位的无符号整数，取值范围为0到255。如果未被约束，这个变量应该以相同的概率被赋值为0到255范围内的任意值。在本例中，连续地调用随机化产生相同值的概率为1/256。

Group

12.3 随机变量

链接
12.3 随机变量


12.3.2 randc修饰符

链接
12.3 随机变量
SystemVerilog 3.1a语言参考手册
12.3.2 randc修饰符
12.3 随机变量

使用randc声明的变量是周期随机变量，它在一个它们声明范围内的一个随机排列中循环地选择所有的值。周期随机变量只能是bit类型或枚举类型，并且可以被限制到一个最大的尺寸。

为了理解randc，考虑一个两位的随机变量y：

Copy Code
randc bit [1:0] y;

变量y可以在0、1、2和3之间取值。随机化的过程会为y的取值范围计算一个初始的随机排列，然后再连续的调用中按顺序返回这些值。当返回一个排列的最后一个元素后，它会通过计算一个新的随机排列来重复这一过程。

randc的基本思想是在取值范围内的所有值上随机地迭代，并且在一次迭代中不会有重复的值。当本次迭代结束后，会自动启动一个新的迭代。

对于任意指定的randc变量，当针对该变量的约束发生变化或者排列中余下的数值都不能满足这个约束的时候会重新计算排列顺序。

为了减少内存的要求，具体实现时可以在randc变量上强加一个限制，但这个变量不能小于8位。

周期随机变量的语义要求它们必须在其它随机变量之前求解。一组既包含了rand变量也包含了randc变量的一组约束应该保证randc变量首先被求解，并且有时可能导致randmize()失败。

Group

12.3 随机变量

链接
12.3 随机变量


12.4 约束块

链接
第十二章 随机约束, 主题
SystemVerilog 3.1a语言参考手册
12.4 约束块
第十二章 随机约束 | 主题

随机变量的值通过由约束块声明的约束表达式来确定。像任务、函数和变量一样，随机块是类的成员。在一个类中，约束块的名字必须是唯一的。

声明约束块的语法如下：

Copy Code
constraint_declaration ::=              // 引用自附录A.1.9
    [static] constraint constraint_identifier constraint_block

constraint_block ::= {{constraint_block_item}}

constraint_block_item ::=
    solve identifier_list before identifier_list;
  | constraint_expression

constraint_expression ::=
    expression_or_dist;
  | expression –> constraint_set
  | if (expression) constraint_set [else constraint_set]
  | foreach (array_identifier [loop_variables]) constraint_set

constraint_set ::=
    constraint_expression
  | {{constraint_expression}}

dist_list ::= dist_item {, dist_item}

dist_item ::= value_range [dist_weight]

dist_weight ::=
    := expression
  | :/ expression

constraint_prototype ::= [static] constraint constraint_identifier;

extern_constraint_declaration ::=
    [static] constraint class_scope constraint_identifier constraint_block

identifier_list ::= identifier{, identifier}

expression_or_dist ::= expression [dist{dist_list}]    // 引用自附录A.2.10

loop_variables ::= [index_variable_identifier]{, [index_variable_identifier]}
                                                            // 引用自附录A.6.8

语法12-2 — 约束语法（摘录自附录A）

constraint_identifier是约束块的名字。使用constraint_mode()（参见12.8节）方法，这个名字可以用来使能或关闭一个约束。

constraint_block是一个表达式语句的列表，它用来限制一个变量的取值范围或者定义变量间的关系。constraint_expression是任意SystemVerilog表达式，或者是约束专用操作符->和dist（参见12.4.4节和12.4.5节）中的一个。

约束的说明状态对约束表达式强加了下列限制：

  • 函数可以具有某种限制（参见12.4.11节）。
  • 不允许使用具有边带效应的操作符，例如++和--。
  • 在排序约束中不能指定randc变量（参见12.4.9节中的solve...before）。
  • dist表达式不能出现在其它表达式中。
Group

第十二章 随机约束

主题
主题
描述
12.4.1 外部约束块
约束体可以像外部任务和函数体一样在一个类声明之外声明：
12.4.2 继承
对于继承而言，约束与类变量、任务和函数遵从相同的规则：

  • 如果一个继承类中的约束与它父类中的约束具有相同的名字，那么它会过载基类约束。例如：

12.4.3 集合成员资格
约束支持整数值集合以及集合成员资格操作符（在7.20节定义）。

如果没有其它的约束，inside操作符在选择值的时候，所有的值（包括单一值或范围值）都具有相等的概率。

inside操作符的否定形式指示表达式位于集合范围之外：!(expression inside {set})。

例如：
12.4.4 分布
除了集合成员资格外，约束支持被称为分布的加权值的集合。分布具有两个特性：它们是集合成员资格的关系测试，并且它们为结果指定了一个统计分布函数。

定义一个分布表达式的语法如下：
12.4.5 蕴含
约束提供了两种结构来声明有条件（判定的）的关系：蕴含和if...else。

蕴含操作符（->）可以用来声明隐含了一个约束的表达式。

定义一个蕴含约束的语法如下：
12.4.6 if...else约束
SystemVerilog还支持if...else类型的约束。

定义if...else约束的语法如下：
12.4.7 迭代约束
迭代约束让我们能够使用循环变量和索引表达式以一种参数化的方式约束数组变量。

定义一个迭代约束的语法如下：
12.4.8 全局约束
当类中的一个对象成员使用rand声明的时候，类中的所有约束和随机变量都会与其它的类变量和约束同时随机化。包含来自其它对象的约束变量的约束表达式被称为全局约束。
12.4.9 变量排序
求解器必须确保选择的值在有效的值组合中具有均匀的值分布（也就是说，所有的有效值组合在求解过程中具有相等的概率）。这个重要的特性能够保证所有的值组合的可能性是相等的，这也就允许随机化能够更好地探索整个设计空间。

然而，有时我们希望强制某种组合出现的频率更高一些。考虑一个案例，其中1位的控制变量s约束了一个32位的数据值d：
12.4.10 静态约束块
一个约束块可以通过在其定义中包含static关键字来被定义成静态的。

声明一个静态约束块的语法如下：
12.4.11 约束中的函数
某些特性很难或不可能在单一的表达式中表达。例如，在计算一个压缩数组中1的数目的时候，最普通的方法是使用一个循环语句：
12.4.12 约束守卫者
约束守卫者是一些判决表达式，它的作用并不是为了求解约束需要满足的逻辑关系，而是作为产生约束的守卫者。这些判决表达式在约束被求解之前计算，并且只能调用下列条目：

  • 常量
  • 状态变量
  • 对象句柄比较（两个句柄之间比较或者在句柄与常量null之间比较）

除了上面描述的条目外，迭代约束（参见12.4.7节）还会将循环变量以及正在被迭代的数组的尺寸当作状态变量。

将这些判决表达式作为约束守卫者能够在某些表面上看起来正确的约束上失败，因此也就可以防止求解器产生计算错误。这就使得用户能够编写约束来防止由于无效句柄或越界的数组索引导致的错误。例如，下面的例子实现了一个singlylinked链表（名字为SList），使用它的sort约束能够赋值一个按降序排列的数字随机序列。然而，对于最后一个元素，next.n会由于无效句柄产生一个计算错误，因此约束表达式会在最后一个元素失败。

链接
第十二章 随机约束, 主题


12.4.1 外部约束块

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.1 外部约束块
12.4 约束块

约束体可以像外部任务和函数体一样在一个类声明之外声明：

Copy Code
// 类声明
class XYPair;
    rand integer x, y;
    constraint c;
endclass

// 外部约束体声明
constraint XYPair::c {x < y;}
Group

12.4 约束块

链接
12.4 约束块


12.4.2 继承

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.2 继承
12.4 约束块

对于继承而言，约束与类变量、任务和函数遵从相同的规则：

  • 如果一个继承类中的约束与它父类中的约束具有相同的名字，那么它会过载基类约束。例如：
Copy Code
class A;
    rand integer x;
    constraint c {x < 0;}
endclass

class B extends A;
    constraint c {x > 0;}
endclass

类A的一个实例包含了x小于0的约束，而类B的一个实例包含了x大于0的约束。扩展的类B过载了约束c的定义。从这个意义讲，约束与虚拟函数相同地对待，所以将B的实例强制转换到A不会改变约束设置。

  • randomize()任务是虚拟的。因此，它以一个虚拟的方式对待类约束。当一个命名约束在一个扩展类中重新定义的时候，前一个定义会被过载。
Group

12.4 约束块

链接
12.4 约束块


12.4.3 集合成员资格

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.3 集合成员资格
12.4 约束块

约束支持整数值集合以及集合成员资格操作符（在7.20节定义）。

如果没有其它的约束，inside操作符在选择值的时候，所有的值（包括单一值或范围值）都具有相等的概率。

inside操作符的否定形式指示表达式位于集合范围之外：!(expression inside {set})。

例如：

Copy Code
rand integer x, y, z;
constraint c1 {x inside {3, 5, [9:15], [24:32], [y:2*y], z};}

rand integer a, b, c;
constraint c2 {a inside {b, c};}
integer fives[0:3] = {5, 10, 15, 20};

rand integer v;
constraint c3 {v inside fives;}

很重要的一点是，我们必须注意：inside操作符是双向的，因此，上面的第二个例子等价于a == b || a == c。

Group

12.4 约束块

链接
12.4 约束块


12.4.4 分布

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.4 分布
12.4 约束块

除了集合成员资格外，约束支持被称为分布的加权值的集合。分布具有两个特性：它们是集合成员资格的关系测试，并且它们为结果指定了一个统计分布函数。

定义一个分布表达式的语法如下：

Copy Code
constraint_block ::=              // 引用自附录A.1.9
    ...
  | expression dist {dist_list};

dist_list ::= dist_item{, dist_item}

dist_item ::= value_range [dist_weight]

dist_weight ::=
    := expression
  | :/ expression

dist_item ::=
    value_range := expression
  | value_range :/ expression

expression_or_dist ::= expression [dist{dist_list}]   // 引用自附录A.2.10

语法12-3 — 约束分布语法（摘录自附录A）

expression可以是任何integral SystemVerilog表达式。

如果表达式的值包含在集合中，那么分布操作符dist的计算结果为“真”；否则计算结果为“假”。

如果没有任何其它约束，那么表达式匹配列表中任意值的概率与为它指定的权重成比例。

分布集合是一个以逗号分割的integral表达式和范围的列表。列表中的每一项都可以带有一个可选的权重，这个权重使用:=或:/操作符说明。如果没有为某一条目指定权重，那么缺省权重是:= 1。权重可以是任意integral SystemVerilog表达式。

:=操作符为一个条目指定一个权重，如果条目是一个范围，它为范围中的每一个值指定权重。

:/操作符为一个条目指定权重，如果条目是一个范围，它会将范围作为一个整体指定权重。如果范围中有n个值，那么范围中每个值的权重为range_weight/n。

例如：

Copy Code
x dist {100 := 1, 200 := 2, 300 := 5}

上面的例子意味着x可以是100、200、或300，它们的权重比为1-2-5。如果添加了另外的约束来说明x不能等于200：

Copy Code
x != 200;
x dist {100 := 1, 200 := 2, 300 := 5}

那么x等于100或300，它们的权重比为1-5。

相对于真实的概率，混合比率（例如1-2-5）更加容易考虑，因为混合比例不需要规格化成100%。将概率转换成婚和比率是直接的。

当权重应用于范围的时候，它们可以应用到范围中的每一个值，或者它们可以将范围作为一个整体应用。例如：

Copy Code
x dist {[100:102] := 1, 200 := 2, 300 := 5}

上面的例子意味着x可以等于100、101、102、200或300中的一个，并且它们的权重比为1-1-1-2-5。

Copy Code
x dist {[100:102] :/ 1, 200 := 2, 300 := 5}

上面的例子意味着x可以等于100、101、102、200或300中的一个，并且它们的权重比为1/3-1/3-1/3-2-5。

通常，分布保证了两个特性：集合成员关系以及无变化的加权，这意味着增加一个权重会增加选择那些值的可能性。

限制：

  • 一个dist操作不应该应用到randc变量。
  • 一个dist表达式要求表达式至少包含一个rand变量。
Group

12.4 约束块

链接
12.4 约束块


12.4.5 蕴含

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.5 蕴含
12.4 约束块

约束提供了两种结构来声明有条件（判定的）的关系：蕴含和if...else。

蕴含操作符（->）可以用来声明隐含了一个约束的表达式。

定义一个蕴含约束的语法如下：

Copy Code
constraint_expression ::=  // 引用自附录A.1.9
    ...
  | expression –> constraint_set

语法12-4 — 约束蕴含语法（摘录自附录A）

expression可以是任意integral SystemVerilog表达式。

蕴含操作符在布尔表达式上等价于：a -> b等价于(!a || b)。它表明：如果表达式为真，那么产生的随机数被其后的约束（或约束集合）所约束。否则，产生的随机数是未施加约束的。

constraint_set代表任意有效的约束或一个未命名的约束集合。如果表达式为真，那么约束集合中的所有约束也必须被满足。

例如：

Copy Code
mode == small -> len < 10;
mode == large -> len > 100;

在这个例子中，mode的值意味着：如果mode == small，那么len的值应该被约束成小于10；如果mode == large，那么len的值应该被约束成大于100；否则，len的值是未约束的。

在下面的例子中：

Copy Code
bit [3:0] a, b;
constraint c {(a == 0) -> (b == 1);}

无论是a还是b都是4位的，因此a和b的组合会有256种可能。约束c表明，a==0意味着b==1，因此排除了15种组合：{0,0}, {0,2}, … {0,15}。因此，a==0的概率为1/(256-15)或1/241。

Group

12.4 约束块

链接
12.4 约束块


12.4.6 if...else约束

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.6 if...else约束
12.4 约束块

SystemVerilog还支持if...else类型的约束。

定义if...else约束的语法如下：

Copy Code
constraint_expression ::=         // 引用自附录A.1.9
    ...
  | if (expression) constraint_set [else constraint_set]

语法12-5 — if...else约束语法（摘录自附录A）

expression可以是任意integral SystemVerilog表达式。

constraint_set代表了任意有效的约束或一个未命名的约束块。如果表达式为真，那么第一个约束或约束集合中的约束必须被满足，否则在可选的else约束或约束块中的约束必须被满足。约束集合可以用来聚合多个约束。

if...else类型的约束声明具有等价的蕴含约束，例如：

Copy Code
if (mode == small)
    len < 10;
else if (mode == large)
    len > 100;

等价于

Copy Code
mode == small -> len < 10;
mode == large -> len > 100;

在这个例子中，mode的值意味着len小于10，或者大于100，或者未约束。

与蕴含一样，if...else类型的约束也是双向的。在上面的声明中，mode约束的值约束了len的值，并且len约束的值约束了mode的值。

因为一个if...else类型的约束声明的else部分是可选的，所以当在一个嵌套的if序列中忽略else的时候会引起混淆。这个问题通过总是将else与最近的前一个缺少else的if相关联来解决。在下面的例子中，else匹配于内层的if，就像缩进格式所指示的那样：

Copy Code
if (mode != large)
    if (mode == small)
        len < 10;
    else     // else应用于前一个if
        len > 100;
Group

12.4 约束块

链接
12.4 约束块


12.4.7 迭代约束

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.7 迭代约束
12.4 约束块

迭代约束让我们能够使用循环变量和索引表达式以一种参数化的方式约束数组变量。

定义一个迭代约束的语法如下：

Copy Code
constraint_expression ::=     // 引用自附录A.1.9
    ...
  | foreach (array_identifier [loop_variables]) constraint_set

loop_variables ::= [index_variable_identifier] {, [index_variable_identifier]}
                                                              // 引用自附录A.6.8

语法12-6 — foreach迭代约束语法（摘录自附录A）

foreach结构指定了数组元素上的迭代。它的参数是一个标识符跟着一个包围在方括号中的循环变量，这个标识符说明了任意类型的数组（固定尺寸、动态数组、联合数组、或队列）。每一个循环变量均对应于数组的某一维。

例如：

Copy Code
class C;
    rand byte A[];
    constraint C1 {foreach (A[i]) A[i] inside {2,4,8,16};}
    constraint C2 {foreach (A[j]) A[j] > 2*j;}
endclass

C1将数组A的每一个元素约束成位于集合[2,4,8,16]之内。C2将数组A中的每一个元素约束成大于其索引值的两倍。

循环变量的数目不能超过数组变量的维数。每一个循环变量的作用范围是foreach约束结构，包括它的constraint_set。每一个循环变量的类型被隐含地声明成与数组索引类型一致。一个空的循环变量指示在数组的该维上没有迭代。与缺省参数一样，尾部的逗号列表可以被忽略，因此，foreach(arr[j])等价于foreach(arr[j, , , ,])。任何循环变量都不能与数组具有相同的标识符。

循环变量与数组索引的映射由维基数确定，参见23.7节。

Copy Code
//    1  2  3         3    4      1   2   -> Dimension numbers
int A[2][3][4]; bit [3:0][2:1] B[5:1][4];
foreach(A[i,j,k]) ...
foreach(B[q,r, ,s]) ...

第一个foreach引起i从0到1迭代，j从0到2迭代，k从0到3迭代。第二个foreach引起q从5到1迭代，r从0到3迭代，s从2到1迭代。

迭代约束可以包含判定条件。例如：

Copy Code
class C;
    rand int A[];
    constraint c1 {arr.size inside {[1:10]};}
    constraint c2 {foreach (A[k]) (k < A.size-1) -> A[k+1] > A[k];}
endclass

第一个约束，c1将数组A的尺寸约束在1到10之间。第二个约束，c2将每一个数组值约束成大于前面一个的值，也就是数组按降序排列。

在一个foreach结构内，仅包含常量、状态变量、对象句柄比较、循环变量、正在被迭代的数组的尺寸的判定表达式的作用是作为产生约束的守卫者，而不是作为逻辑关系操作。例如，上面例子中约束c2中的蕴涵仅包括一个循环变量和正在被迭代的数组的尺寸，它仅当k < A.size-1时才允许产生一个约束，这样可以阻止约束中的越界访问。有关约束守卫的更多细节在12.4.12节中描述。

索引表达式可以包含循环变量、常量、和状态变量。无效或越界的数组索引不会被自动地消除；用户必须使用判定条件来显式地排除这些索引。

动态数组或联合数组的size方法可以被用来约束数组的尺寸（参见上面例子中的c1）。如果一个数组既被尺寸约束所约束也被迭代约束所约束，那么尺寸约束首先被解析，然后才是迭代约束。作为尺寸约束和迭代约束间隐含排序的结果，size方法应该被当作对应数组的foreach块内的状态变量。例如，表达式A.size被当作约束c1中的一个随机变量，并被作为约束c2中的一个状态变量。这个隐含的排序在某些情况下会导致求解器失败。

Group

12.4 约束块

链接
12.4 约束块


12.4.8 全局约束

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.8 全局约束
12.4 约束块

当类中的一个对象成员使用rand声明的时候，类中的所有约束和随机变量都会与其它的类变量和约束同时随机化。包含来自其它对象的约束变量的约束表达式被称为全局约束。

Copy Code
class A; // 叶子节点
    rand bit [7:0] v;
endclass

class B extends A; // 堆节点
    rand A left;
    rand A right;
    constraint heapcond {left.v <= v; right.v <= v;}
endclass

这个例子使用全局约束来定义一个有序二叉树的有效值。类A代表一个具有8位值v的叶子节点。类B扩展了类A并表示了一个堆节点，这个堆节点包含值v、一个left子树、一个right子树。为了与其它类变量同时随机化这两个子树，这两个子树都使用rand声明。被命名为heapcond的约束块具有两个全局约束，它们将left和right子树的值与堆节点的值关联起来。当类B的一个实例被初始化的时候，求解器同时为B以及它的left和right子节点求解，这可以类推到叶子节点或更多的堆节点。

下列规则决定了哪一个对象、变量和约束被随机化：

  1. 首先确定那些作为一个整体随机化的对象的集合。起始于一个调用randomize()方法的对象，加入其中包含的、使用rand声明的、以及活跃（参见12.7节中的rand_mode）的所有对象。这个定义是递归的，并且包含可以从起始对象到达的所有的活跃随机对象。这一步中选择的对象被称为活跃随机对象。
  2. 接下来从活跃随机变量的集合中选择所有的活跃约束。这些都是需要求解的约束。
  3. 最后从活跃随机对象的集合中选择所有的活跃随机变量。这些是需要被随机化的变量。所有其它的变量引用都被当作是状态变量，它们的当前值被当作一个常量时候。
Group

12.4 约束块

链接
12.4 约束块


12.4.9 变量排序

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.9 变量排序
12.4 约束块

求解器必须确保选择的值在有效的值组合中具有均匀的值分布（也就是说，所有的有效值组合在求解过程中具有相等的概率）。这个重要的特性能够保证所有的值组合的可能性是相等的，这也就允许随机化能够更好地探索整个设计空间。

然而，有时我们希望强制某种组合出现的频率更高一些。考虑一个案例，其中1位的控制变量s约束了一个32位的数据值d：

Copy Code
class B;
    rand bit s;
    rand bit [31:0] d;
    constraint c {s -> d == 0;}
endclass

约束c表明“s蕴含着d等于0”。尽管表面上看好像由s确定d，但事实上s和d是一起确定的。{s,d}共有233种组合，但s仅在{1,0}这种组合时才为真。因此s为真的可能性为1/233，它近似于等于0。

约束为排序变量提供了一种机制，这样s可以独立于d被选择。这种机制在变量的计算上定义了一个部分排序，并使用solve关键字说明。

Copy Code
class B;
    rand bit s;
    rand bit [31:0] d;
    constraint c {s -> d == 0;}
    constraint order {solve s before d;}
endclass

在这个例子中，order约束向求解器指示s在d被求解之前求解。这么做的效果就是s具有50%的概率被选择为真，接下来d根据s的值被选择。相应地，d == 0的概率为50%，d != 0的概率也为50%。

变量排序可以被用来强制被选择的边界条件出现的机会更频繁一些。然而，一个“solve...before ...”约束不会改变求解空间，并且不会引起求解器失败。

在一个约束块中定义变量顺序的语法如下：

Copy Code
constraint_block_item ::=         // 引用自附录A.1.9
    solve identifier_list before identifier_list;
  | constraint_expression

语法12-7 — Solve...before约束排序语法（摘录自附录A）

solve和before使用一个逗号分割的integral变量或数组元素。

下列限制应用于变量排序：

  • 仅允许随机变量，也就说它们必须使用rand声明。
  • 不允许使用randc变量。randc变量总是在其它变量之前求解。
  • 变量必须是integral值。
  • 约束块既可以包含单一值约束也可以包含排序约束。
  • 在排序上不能有循环的依赖性，就好像“在b之前求解a”与“在a之前求解b”那样。
  • 没有被显式排序的变量应该与最后一组排序变量一起求解。这些值的求解被尽可能晚地推迟以便确保一个好的值分布。
  • 只要结果相同，变量可以以排序约束不一致的顺序求解。一个可能的例子如下：
Copy Code
x == 0;
x < y;
solve y before x;

在这个例子中，由于x具有唯一可能的赋值（0），所以x可以在y之前求解。约束求解器可以使用这种灵活性来加速求解过程。

Group

12.4 约束块

链接
12.4 约束块


12.4.10 静态约束块

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.10 静态约束块
12.4 约束块

一个约束块可以通过在其定义中包含static关键字来被定义成静态的。

声明一个静态约束块的语法如下：

Copy Code
constraint_declaration ::=          // 引用自附录A.1.9
    [static] constraint constraint_identifier constraint_block

语法12-8 — 静态约束语法（摘录自附录A）

如果一个约束块被声明成静态的，那么对constraint_mode()的调用会影响所有对象中指定约束的所有实例。因此，如果一个静态约束被设置成OFF，那么它会关闭特定类的所有实例。

Group

12.4 约束块

链接
12.4 约束块


12.4.11 约束中的函数

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.11 约束中的函数
12.4 约束块

某些特性很难或不可能在单一的表达式中表达。例如，在计算一个压缩数组中1的数目的时候，最普通的方法是使用一个循环语句：

Copy Code
function int count_ones (bit [9:0] w);
    for(count_ones=0; w!=0; w=w>>1)
        count_ones += w & 1'b1;
endfunction

这样的一个函数可以用来约束其它随机变量中1的数目：

Copy Code
constraint C1 {length == count_ones(v);}

如果没有调用函数的能力，那么这个约束需要将循环展开并将它表示成一个单独位的和：

Copy Code
constraint C2
{
    length == ((v>>9)&1) + ((v>>8)&1) + ((v>>7)&1) + ((v>>6)&1) + ((v>>5)&1) +
        ((v>>4)&1) + ((v>>3)&1) + ((v>>2)&1) + ((v>>1)&1) + ((v>>0)&1);
}

与count_ones函数不同，一些更为复杂的特性需要使用临时状态或使用庞大的循环，因此它不可能转换成一个单独的表达式。因此，调用函数的能力增强了约束语言的表达能力并减少了出错的可能性。注意，上面的两个约束并不是完全等价的；C2是双向的（length可以约束v，反之亦然），而C1则不是。

为了处理这些基本情况，SystemVerilog允许约束表达式包含函数调用，但在语义上它强加了某些限制。

  • 出现在约束表达式中的函数不能包含output或ref参数（但允许使用const ref参数）。
  • 出现在约束表达式中的函数不应该是自动的（或者不应该没保存状态信息）并且不应该有边带效应。
  • 出现在约束表达式中的函数不能修改约束，例如调用rand_mode或constraint_mode方法。
  • 函数应该在约束被求解之前调用，并且它们的返回值应该被当作状态变量。
  • 作为函数参数使用的随机变量应该建立一个隐含的变量排序或优先级。仅包含具有较高优先级的变量会被首先求解，然后才是具有较低优先级的变量。被求解成一个较高优先级约束集合一部分的随机变量在余下的约束集合中变成状态变量。例如：
Copy Code
class B;
    rand int x, y;
    constraint C {x <= F(y);}
    constraint D {y inside {2, 4, 8};}
endclass

上面的例子强制y在x之前求解。因此，约束D在约束C之前被独立地求解，而约束C使用y和F(y)的值作为状态变量。注意：由函数参数隐含的变量排序的行为不同于使用“solve...before...”约束说明的变量排序；函数参数变量排序可以细分求解空间，因此也就会对它改变。由于较高优先级变量上的约束在求解的时候根本不考虑低优先级的约束，所以这种细分会导致整个约束失败。在每一个具有优先级的约束集合中，循环（randc）变量被首先求解。

  • 由隐含变量排序所产生的循环依赖性会导致一个错误。
  • 活跃约束中的函数调用执行的次数未被指定（至少一次），并且执行次序也是未指定的。
Group

12.4 约束块

链接
12.4 约束块


12.4.12 约束守卫者

链接
12.4 约束块
SystemVerilog 3.1a语言参考手册
12.4.12 约束守卫者
12.4 约束块

约束守卫者是一些判决表达式，它的作用并不是为了求解约束需要满足的逻辑关系，而是作为产生约束的守卫者。这些判决表达式在约束被求解之前计算，并且只能调用下列条目：

  • 常量
  • 状态变量
  • 对象句柄比较（两个句柄之间比较或者在句柄与常量null之间比较）

除了上面描述的条目外，迭代约束（参见12.4.7节）还会将循环变量以及正在被迭代的数组的尺寸当作状态变量。

将这些判决表达式作为约束守卫者能够在某些表面上看起来正确的约束上失败，因此也就可以防止求解器产生计算错误。这就使得用户能够编写约束来防止由于无效句柄或越界的数组索引导致的错误。例如，下面的例子实现了一个singlylinked链表（名字为SList），使用它的sort约束能够赋值一个按降序排列的数字随机序列。然而，对于最后一个元素，next.n会由于无效句柄产生一个计算错误，因此约束表达式会在最后一个元素失败。

Copy Code
class SList;
    rand int n;
    rand Slist next;
    constraint sort {n < next.n;}
endclass

上面例子中的错误条件可以通过编写一个守卫这个条件的判决表达式来避免：

Copy Code
constraint sort {if(next != null) n < next.n;}

在上面例子中的sort约束中，if会防止在next==null的时候产生一个约束，因此，在这种情况下可以避免访问一个无效对象。无论是蕴含（->）还是if...else都可以用作约束守卫者。

守卫表达式本身可以包含会引起计算错误的子表达式（例如空引用），并且它们还被守卫以免产生错误。通过使用下列的四态表示来计算判决子表达式可以完成这个逻辑转移：

  • 0 FALSE子表达式计算成FALSE
  • 1 TRUE子表达式计算成TRUE
  • E ERROR子表达式引起一个计算错误
  • R RANDOM表达式包含随机变量并且不能被计算

判决表达式内的每一个子表达式都会被计算以便产生上述四个值中的一个。子表达式以任意顺序计算，并且计算结果加上逻辑操作以四态表示形式定义了结果。子表达式的联合（&&）、分离（||）或非（!）可以包含某些（或许所有）守卫子表达式。下列规则说明了守卫的结果值：

  • 联合（&&）：如果任意一个子表达式计算成FALSE，那么守卫会被计算成FALSE。另外，如果任意一个子表达式计算成ERROR，那么守卫计算成ERROR，否则计算成TRUE。
    • 如果守卫计算成FALSE，那么约束会被消除。
    • 如果守卫计算成TRUE，那么会产生一个约束（可能是有条件的）。
    • 如果守卫计算成ERROR，那么会产生一个错误并且随机化会失败。
  • 分离（||）：如果任何一个子表达式计算成TRUE，那么守卫会被计算成TRUE。另外，如果任意个子表达式计算成ERROR的话，那么守卫会被计算成ERROR，否则守卫计算成FALSE。
    • 如果守卫计算成FALSE，那么会产生一个约束（可能是有条件的）。
    • 如果守卫计算成TRUE，那么会产生一个无条件的约束。
    • 如果守卫计算成ERROR，那么会产生一个错误并且随机化会失败。
  • 非（!）：如果子表达式计算成ERROR，那么守卫计算成ERROR。另外，如果子表达式计算成TRUE或FALSE，那么守卫会被分别计算成FALSE或TRUE。

这些规则可以使用下列的真值表表示：

上述规则会被递归地应用直到所有的子表达式被计算。判决表达式的最终值按下列规则确定结果：

  • 如果结果为TRUE，那么会产生一个无条件约束。
  • 如果结果为FALSE，那么约束会被消除并且不会产生错误。
  • 如果结果为ERROR，那么会产生一个无条件错误并且约束会失败。
  • 如果最终的计算结果为RANDOM，那么会产生一个有条件约束。

当最终结果是RANDOM的时候，需要遍历判决表达式树以便收集计算成RANDOM的所有有条件守卫。当最终结果为ERROR的时候，不需要遍历后续的表达式树，这就使得实现时只发布一个错误。

例子1：

Copy Code
class D;
    int x;
endclass

class C;
    rand int x, y;
    D a, b;
    constraint c1 {(x < y || a.x > b.x || a.x == 5) -> x+y == 10;}
endclass

在上面的例子中，判决表达式为(x < y)、(a.x > b.x)、以及(a.x == 5)，它们被分离（||）连接起来。一些可能的情况有：

  • 情况1：a为非空，b为null，a.x为5。

因为(a.x == 5)为真，所以b.x产生错误的事实不会导致一个错误。

无条件约束(x+y == 10)会被产生。

  • 情况2：a为null

这种情况总会导致错误而不管其它的条件。

  • 情况3：a为非空，b为非空，a.x为10，b.x为20

所有的守卫子表达式计算成FALSE。

产生有条件约束(x<y) -> (x+y) == 10。

例子2：

Copy Code
class D;
    int x;
endclass

class C;
    rand int x, y;
    D a, b;
    constraint c1 {(x < y && a.x > b.x && a.x == 5) -> x+y == 10;}
endclass

在上面的例子中，判决表达式为(x < y)、(a.x > b.x)、以及(a.x == 5)，它们被联合（&&）连接起来。一些可能的情况为：

  • 情况1：a为非空，b为null，a.x为6。

因为(a.x==5)为假，b.x产生一个错误的事实不会导致一个错误。

约束被消除。

  • 情况2：a为null

这种情况总会导致错误而不管其它的条件。

  • 情况3：a为非空，b为非空，a.x为5，b.x为2。

所有的守卫子表达式计算成TRUE，产生有条件约束(x<y) -> (x+y) == 10。

例子3：

Copy Code
class D;
    int x;
endclass

class C;
    rand int x, y;
    D a, b;
    constraint c1 {(x < y && (a.x > b.x || a.x == 5)) -> x+y == 10;}
endclass

在上面的例子中，判决表达式为(x < y)以及(a.x > b.x || a.x == 5)，有一个表达式使用分离（||）连接起来。一些可能的情况如下：

  • 情况1：a为非空，b为null，a.x为5。

守卫表达式计算成(ERROR || a.x==5)，进一步计算成(ERROR || TRUE)。

守卫子表达式计算成TRUE。

产生有条件约束(x<y) -> (x+y) == 10。

  • 情况2：a为非空，b为null，a.x为8。

守卫表达式计算成(ERROR || FALSE)，并产生一个错误。

  • 情况3：a为null

这种情况总会导致错误而不管其它的条件。

  • 情况4：a为非空，b为非空，a.x为5，b.x为2。

所有的守卫子表达式计算成TRUE。

产生有条件约束(x<y) -> (x+y) == 10。

Group

12.4 约束块

链接
12.4 约束块


12.5 随机化方法

链接
第十二章 随机约束, 主题
SystemVerilog 3.1a语言参考手册
12.5 随机化方法
第十二章 随机约束 | 主题
Group

第十二章 随机约束

主题
主题
描述
12.5.1 randomize()
一个对象中的变量使用randomize()类方法进行随机化。每一个类都有一个内建的randomize()虚拟方法，它的声明原型如下：
12.5.2 pre_randomize()与post_randomize()
每一个类都包含了内建的pre_randomize()和post_randomize()函数，它们在计算新的随机值之前和之后被 randomize()自动调用。

pre_randomize()的内建定义如下：
12.5.3 随机化方法注意事项

  • 被声明成static的随机变量被随机变量在其中声明的类的所有实例所共享。每次调用randomize()方法的时候，在每一个类实例中的变量都会被改变。
  • 如果randomize()失败，那么约束是不可实行的并且变量保持为原来的值。
  • 如果randomize()失败，post_randomize()方法不会被调用。
  • randomize()方法是内建的并且不能被过载。
  • randomize()方法实现了对象的随机稳定性。一个对象可以通过调用它的srandom()方法来设置种子（参见12.12.3节）。
  • pre_randomize()和post_randomize()内建方法是函数并且不能被阻塞。

链接
第十二章 随机约束, 主题


12.5.1 randomize()

链接
12.5 随机化方法
SystemVerilog 3.1a语言参考手册
12.5.1 randomize()
12.5 随机化方法

一个对象中的变量使用randomize()类方法进行随机化。每一个类都有一个内建的randomize()虚拟方法，它的声明原型如下：

Copy Code
virtual function int randomize();

randomize()方法是一个虚拟函数，它为对象中的所有活跃随机变量产生随机值，产生的随机值应该符合活跃的约束。

如果randomize()方法成功地设置了所有的随机变量和对象的有效值，那么它返回1；否则返回0。

例子：

Copy Code
class SimpleSum;
    rand bit [7:0] x, y, z;
    constraint c {z == x + y;}
endclass

这个类定义声明了三个随机变量x、y、和z。调用randomize()方法应该随机化类SimpleSum的一个实例：

Copy Code
SimpleSum p = new;
int success = p.randomize();
if (success == 1) ...

检查返回状态是很有必要的，因为状态变量或继承类中约束的增加都会导致表面上简单的约束不再满足。

Group

12.5 随机化方法

链接
12.5 随机化方法


12.5.2 pre_randomize()与post_randomize()

链接
12.5 随机化方法
SystemVerilog 3.1a语言参考手册
12.5.2 pre_randomize()与post_randomize()
12.5 随机化方法

每一个类都包含了内建的pre_randomize()和post_randomize()函数，它们在计算新的随机值之前和之后被 randomize()自动调用。

pre_randomize()的内建定义如下：

Copy Code
function void pre_randomize;
    if (super) super.pre_randomize(); // 检测super以便确定对象句柄是否存在

    // 可选的在随机化之前的编程从这里开始
endfunction

post_randomize()的内建定义如下：

Copy Code
function void post_randomize;
    if (super) super.post_randomize(); // 检测super以便确定对象句柄是否存在

    //可选的在随机化之后的编程从这里开始
endfunction

当调用obj.randomize()的时候，它首先调用obj的pre_randomize()方法以及它的所有被使能的随机对象成员。接下来pre_randomize()会调用super.pre_randomize()。在新的随机值被计算并赋值后，randomize()会调用obj的post_randomize()方法以及它的所有被使能的随机对象成员。接下来post_randomize()会调用super.post_randomize()。

用户可以在任何类中过载pre_randomize()方法以便执行对象被随机化之前的初始化和预处理。

用户可以在任何类中过载post_randomize()方法以便执行对象被随机化之后的清除、打印诊断、以及后处理。

如果这些方法被过载，那么它们必须调用对应的父类方法，否则它们在随机化之前和之后的处理步骤会被忽略。

pre_randomize()和post_randomize()方法不是虚拟的。然而，因为它们会被虚拟的randomize()方法自动调用，所以它们看上去像是虚拟的。

Group

12.5 随机化方法

链接
12.5 随机化方法


12.5.3 随机化方法注意事项

链接
12.5 随机化方法
SystemVerilog 3.1a语言参考手册
12.5.3 随机化方法注意事项
12.5 随机化方法
  • 被声明成static的随机变量被随机变量在其中声明的类的所有实例所共享。每次调用randomize()方法的时候，在每一个类实例中的变量都会被改变。
  • 如果randomize()失败，那么约束是不可实行的并且变量保持为原来的值。
  • 如果randomize()失败，post_randomize()方法不会被调用。
  • randomize()方法是内建的并且不能被过载。
  • randomize()方法实现了对象的随机稳定性。一个对象可以通过调用它的srandom()方法来设置种子（参见12.12.3节）。
  • pre_randomize()和post_randomize()内建方法是函数并且不能被阻塞。
Group

12.5 随机化方法

链接
12.5 随机化方法


12.6 内联约束 — randomize() with

链接
第十二章 随机约束
SystemVerilog 3.1a语言参考手册
12.6 内联约束 — randomize() with
第十二章 随机约束

通过使用randomize()...with结构，用户可以在randomize()方法的调用点上声明内联约束。这些额外的约束与对象约束一起应用。

randomize()...with的语法如下：

Copy Code
inline_constraint _declaration ::=             // 没有包含在附录A中
    class_variable_identifier.randomize[([variable_identifier_list | null])]
        with constraint_block

语法12-9 — 内联约束语法（没有包含在附录A中）

class_variable_identifier是一个被实例的对象的名字。

未命名的constraint_block包含了额外的内联约束，这些内联约束与在类内声明的对象约束一起应用。

例如：

Copy Code
class SimpleSum
    rand bit [7:0] x, y, z;
    constraint c {z == x + y;}
endclass

task InlineConstraintDemo(SimpleSum p);
    int success;
    success = p.randomize() with {x < y;};
endtask

这个简单的例子在前面章节已经使用过，然而在这里我们使用randomize()...with来引入一个额外的x < y的约束。

randomize()...with结构可以出现在表达式可以出现的任何地方。紧跟在with之后的约束块可以包含在类中声明的所有相同的约束类型和格式。randomize()...with约束块还可以引用本地变量以及任务和函数的参数，因此我们不需要将一个本地状态映射成对象类中的成员变量。一个约束块中变量名的作用范围由内而外为：randomize()...with对象类、自动和本地变量、任务和函数参数、类变量、包围范围内的变量。randomize()...with类在最内层的嵌套中被引入到作用范围。

在下面的例子中，randomize()...with类是foo。

Copy Code
class Foo;
    rand integer x;
endclass

class Bar;
    integer x;
    integer y;

    task doit(Foo f, integer x, integer z);
        int result;
        result = f.randomize() with {x < y + z;};
    endtask
endclass

在f.randomize() with约束块中，x是foo类的一个成员，并将x隐藏在Bar类中。它还将x参数隐藏在doit()任务中。v是Bar的一个成员。z是一个本地参数。

Group

第十二章 随机约束

链接
第十二章 随机约束


12.7 使用rand_mode()关闭随机变量

链接
第十二章 随机约束
SystemVerilog 3.1a语言参考手册
12.7 使用rand_mode()关闭随机变量
第十二章 随机约束

rand_mode()可以用来控制激活或关闭一个随机变量。当一个随机变量处于未激活状态的时候，这个随机变量就好像没有使用rand或randc声明一样。未激活的随机变量不会被rand_mode()方法随机化，并且它们的值会被求解器当作状态变量。所有的随机变量最初都是激活的。

rand_mode()方法的语法如下：

Copy Code
task object[.random_variable]::rand_mode(bit on_off);

或者

Copy Code
function int object.random_variable::rand_mode();

object是能够产生对象句柄的任何表达式，并且随机变量在其中定义。

random_variable是操作被应用的随机变量的名字。如果没有指定随机变量的名字（仅在作为任务调用是才允许出现这种情况），那么这个动作会被应用到对象内的所有随机变量。

当作为任务调用时，rand_mode方法的参数确定了执行的操作：

表格12-1：rand_mode参数

值 | 含义 | 描述
0 | OFF | 将指定的随机变量设置为未激活状态。这样，它们不会被后来调用的randomize()方法随机化。
1 | ON | 将指定的随机变量设置为激活状态。这样，它们能够被后来调用的randomize()方法随机化。

对于非压缩数组变量，random_variable可以使用索引来指定数组中单独的元素。省略索引会导致数组中的所有元素都被调用所影响。

对于非压缩结构体变量，random_variable可以使用对应的成员来指定单独的成员。省略成员会导致结构体中的所有成员都被调用所影响。

如果随机变量是一个对象句柄，那么仅仅变量的模式会被改变，这个对象内的随机变量的模式不会改变（参见12.4.8节中有关全局约束的内容）。

如果指定的变量在类层次中不存在或者它虽然存在但没有使用rand或randc声明，那么编译器应该发布一个错误信息。

如果作为一个函数调用，那么rand_mode()返回指定变量当前的激活状态。如果随机变量处于激活状态（ON）返回1；如果随机变量处于未激活状态（OFF）则返回0。

rand_mode()方法的函数形式仅能接受单一变量，因此，如果指定的变量是一个非压缩数组，那么必须使用索引来选择单一的元素。

例子：

Copy Code
class Packet;
    rand integer source_value, dest_value;
    // ... 其它声明
endclass

int ret;

Packet packet_a = new;

// 关闭对象中的所有随机变量
packet_a.rand_mode(0);

// ... 其它代码
// 使能source_value
packet_a.source_value.rand_mode(1);
ret = packet_a.dest_value.rand_mode();

这个例子首先关闭对象packet_a中的所有随机变量，然后仅仅使能source_value变量。最后它将ret变量设置为变量dest_value的激活状态。

rand_mode()方法是内建的，并且不能被过载。

Group

第十二章 随机约束

链接
第十二章 随机约束


12.8 使用constraint_mode()控制约束

链接
第十二章 随机约束
SystemVerilog 3.1a语言参考手册
12.8 使用constraint_mode()控制约束
第十二章 随机约束

constraint_mode()方法可以用来控制激活或关闭一个约束。当约束处于未激活（关闭）状态时，它不会被randomize()方法所考虑。所有的约束最初都是激活的。

constraint_mode()方法的语法如下：

Copy Code
task object[.constraint_identifier]::constraint_mode(bit on_off);

或者

Copy Code
function int object.constraint_identifier::constraint_mode();

object是能够产生对象句柄的任何表达式，并且约束在其中定义。

constraint_identifier是约束被应用的约束块的名字。约束名字可以是类层次中任意约束块的名字。如果没有指定约束名字（仅在作为任务调用是才允许出现这种情况），这个操作应用于指定对象中的所有约束。

当作为任务调用的时候，constraint_mode方法的参数确定了需要执行的操作：

表格12-2：constraint_mode参数

值 | 含义 | 描述
0 | OFF | 将指定的约束块设置成未激活状态，这样它就不会被后来对randomize()方法的调用所强制。
1 | ON | 将指定的约束块设置成激活状态，这样它会被后来对randomize()方法的调用所考虑。

如果指定的约束块在类层次中不存在，那么编译器应该发布一条错误信息。

当作为函数调用的时候，constraint_mode()方法返回指定约束块当前的激活状态。如果约束处于激活状态（ON），那么它返回1；如果约束处于未激活状态（OFF），那么它返回0。

例子：

Copy Code
class Packet;
    rand integer source_value;
    constraint filter1 {source_value > 2 * m;}
endclass

function integer toggle_rand(Packet p);
    if (p.filter1.constraint_mode())
        p.filter1.constraint_mode(0);
    else
        p.filter1.constraint_mode(1);

    toggle_rand = p.randomize();
endfunction

在这个例子中，toggle_rand函数首先检查指定的Packet对象p中约束filter1当前的激活状态。如果约束处于激活状态，函数会将它设置为处于非激活状态；如果约束处于非激活状态，那么函数会将它激活。最后，函数会调用randomize方法来为随机变量source_value产生一个新的随机值。

constraint_mode()方法是内建的并且不能被过载。

Group

第十二章 随机约束

链接
第十二章 随机约束


12.9 动态的约束修改

链接
第十二章 随机约束
SystemVerilog 3.1a语言参考手册
12.9 动态的约束修改
第十二章 随机约束

SystemVerilog中提供了几种方法来动态地修改随机化方法：

  • 蕴涵以及if...else风格的约束允许声明具有判决条件的约束。
  • 可以使用contraint_mode()内建方法来激活或关闭约束块。初始情况下，所有的约束块均处于激活状态。未激活的约束会被randomize()函数忽略。
  • 可以使用rand_mode()内建方法来激活或关闭随机变量。初始情况下，所有的rand和randc变量都处于激活状态。未激活的随机变量会被randomize()函数忽略。
  • 在dist约束中的权重可以被改变，从而影响了被选定集合中特定值出现的概率。
Group

第十二章 随机约束

链接
第十二章 随机约束


12.10 内联随机变量控制

链接
第十二章 随机约束, 主题
SystemVerilog 3.1a语言参考手册
12.10 内联随机变量控制
第十二章 随机约束 | 主题

randomize()方法可以用来临时性地控制一个类实例或对象中的随机变量和状态变量的集合。当调用无参数的randomize方法的时候，它的行为就像前一节所描述的那样，也就是说，它会为对象中所有使用rand或randc声明的随机变量赋新的值，这样所有的约束都会被满足。当调用带有参数的randomize的时候，它的参数指定了该对象内随机变量的完整集合；对象中的所有其它变量都被认为是状态变量。例如，考虑下面的类以及对randomize方法的调用：

Copy Code
class CA;
    rand byte x, y;
    byte v, w;
    constraint c1 {(x < v && y > w)};
endclass

CA a = new;
a.randomize();       // 随机变量：x, y  状态变量：v, w
a.randomize(x);      // 随机变量：x     状态变量：y, v, w
a.randomize(v, w);   // 随机变量：v, w  状态变量：x, y
a.randomize(w, x);   // 随机变量：w, x  状态变量：y, v

这种机制在randomize的调用期内控制了活跃随机变量的集合，它在概念上等价于调用一组rand_mode()方法来关闭或使能对应的随机变量。调用带有参数的randomize()方法能够改变任意类属性的随机模式，即使是那些没有使用rand或randc声明的类属性。然而，这种机制不会影响循环随机模式；它不能将一个非随机变量改变成一个循环随即变量（randc），并且不能将一个循环随机变量改变成一个非循环随机变量（从randc改变成rand）。

randomize方法参数的范围是目标类。参数被限制成调用对象的属性的名字，并且不允许使用表达式。本地类成员的随机模式仅在randomize方法的调用能够访问这些属性的时候才能够改变，也就是在本地成员被声明的类范围内。

Group

第十二章 随机约束

主题
主题 | 描述
12.10.1 内联约束检查器 | 通常，调用一个没有随机变量的类的randomize方法会导致这个方法作为一个检查器使用，也就是说它不会赋随机值，而是仅仅返回一个状态：如果所有的约束都被满足返回1，否则返回0。内联随机变量控制机制还可以用来强制randomize()方法作为一个检查器使用。 randomize方法可以接受特殊的参数null，它用来指示在调用期内没有随机变量。也就是说，所有的类成员均作为状态变量使用。这会导致randomize方法作为一个检查器使用而不是作为一个产生器使用。一个检查器会计算所有的约束并简单地在所有的约束都被满足时返回1，否则返回0。例如，如果上面定义的类CA执行了下列的调用：
链接
第十二章 随机约束, 主题


12.10.1 内联约束检查器

链接
12.10 内联随机变量控制
SystemVerilog 3.1a语言参考手册
12.10.1 内联约束检查器
12.10 内联随机变量控制

通常，调用一个没有随机变量的类的randomize方法会导致这个方法作为一个检查器使用，也就是说它不会赋随机值，而是仅仅返回一个状态：如果所有的约束都被满足返回1，否则返回0。内联随机变量控制机制还可以用来强制randomize()方法作为一个检查器使用。

randomize方法可以接受特殊的参数null，它用来指示在调用期内没有随机变量。也就是说，所有的类成员均作为状态变量使用。这会导致randomize方法作为一个检查器使用而不是作为一个产生器使用。一个检查器会计算所有的约束并简单地在所有的约束都被满足时返回1，否则返回0。例如，如果上面定义的类CA执行了下列的调用：

Copy Code
success = a.randomize(null);  // 没有随机变量

那么，求解器将所有的变量作为状态变量使用，并仅仅检查约束是否满足，也就是检查当使用x、y、v和w的当前值的时候(x < v && y > w)的关系是否为真。

Group

12.10 内联随机变量控制

链接
12.10 内联随机变量控制


12.11 范围变量的随机化 — std::randomize()

链接
第十二章 随机约束, 主题
SystemVerilog 3.1a语言参考手册
12.11 范围变量的随机化 — std::randomize()
第十二章 随机约束 | 主题

内建的类随机化方法对类成员变量执行专有的操作。使用类来对需要随机化的数据建模是一种强大的机制，它使得我们能够产生通用、可复用的包含随机变量的对象，并能够产生可以在以后扩展、继承、约束、过载、使能、关闭、以及从其它对象合并或分离的约束。类及与其关联的随机变量和约束在处理上的方便性使得类非常适合描述和处理随机数据和约束。然而，某些要求较少的问题并不需要类的这些完整的灵活性，它可以使用一个较为简单的机制来随机化不属于一个类的数据。范围随机函数（std::randomize()）使得用户能够随机化当前范围内的数据，而无需定义一个类或实例化一个类对象。

范围随机化函数的语法如下：

Copy Code
scope_randomize ::=               // 没有包含在附录A中
    [std::]randomize([variable_identifier_list]) [with constraint_block]

语法12-10 — 范围随机化函数语法（没有包含在附录A中）

范围随机化函数与类的随机化方法的作用相同，只是它操作于当前范围内的变量而不是类成员变量。函数的参数指定了那些需要赋值为随机值的变量，也就是随机变量。

例如：

Copy Code
module stim;
    bit [15:0] addr;
    bit [31:0] data;

    function bit gen_stim();
        bit success, rd_wr;
        success = randomize(addr, data, rd_wr);  // 调用std::randomize
        return rd_wr;
    endfunction

    ...
endmodule

函数gen_stim调用std::randomize()函数并带有三个变量作为参数：addr、data、和rd_wrstd::randomize()将新的随机变量赋值到那些在gen_stim函数范围内可见的变量。注意，addr和data具有模块级的作用范围，而rd_wr具有函数内的本地作用范围。我们也可以使用类来编写上面的例子：

Copy Code
class stimc;
    rand bit [15:0] addr;
    rand bit [31:0] data;
    rand bit rd_wr;
endclass

function bit gen_stim(stimc p);
    bit success;
    success = p.randomize();
    addr = p.addr;
    data = p.data;
    return p.rd_wr;
endfunction

然而，对于这个简单的应用，范围随机化函数能够产生一个更直接的实现。

如果范围随机化函数成功地为所有的随机变量设置了有效值，那么它返回1；否则它返回0。如果调用范围随机化函数的时候没有指定参数，那么它作为一个检查器使用，并简单地返回状态。

Group

第十二章 随机约束

主题
主题 | 描述
12.11.1 为范围变量添加约束 — std::randomize() with | 范围随机化函数的std::randomize() with形式允许用户为本地范围变量指定随机约束。当说明约束的时候，范围随机化函数的参数指定的变量变成了随机变量，所有其它变量被认为是状态变量。
链接
第十二章 随机约束, 主题


12.11.1 为范围变量添加约束 — std::randomize() with

链接
12.11 范围变量的随机化 — std::randomize()
SystemVerilog 3.1a语言参考手册
12.11.1 为范围变量添加约束 — std::randomize() with
12.11 范围变量的随机化 — std::randomize()

范围随机化函数的std::randomize() with形式允许用户为本地范围变量指定随机约束。当说明约束的时候，范围随机化函数的参数指定的变量变成了随机变量，所有其它变量被认为是状态变量。

Copy Code
task stimulus (int length);
    int a, b, c, success;
    success = std::randomize(a, b, c) with {a < b; a + b < length};
    ...
    success = std::randomize(a, b) with {b - a > length};
    ...
endtask

上面例子中的任务（stimulus）将std::randomize调用了两次，从而为它的本地变量a、b和c产生了两组随机值。在第一次调用中，a和b被约束成a小于b，并且它们的和小于任务参数length（它被指定成一个状态变量）。在第二次调用中，变量a和b被约束成它们的差大于状态变量length。

Group

12.11 范围变量的随机化 — std::randomize()

链接
12.11 范围变量的随机化 — std::randomize()


12.12 随机数系统函数与方法

链接
第十二章 随机约束, 主题
SystemVerilog 3.1a语言参考手册
12.12 随机数系统函数与方法
第十二章 随机约束 | 主题
Group

第十二章 随机约束

主题
主题
描述
12.12.1 $urandom
$urandom系统函数提供了一种机制来产生伪随机数。每次调用这个函数的时候都会返回一个新的32位的随机数。这个随机数应该是无符号的。

$urandom的语法如下：
12.12.2 $urandom_range()
$urandom_range()函数返回一个指定范围内的无符号整数。

$urandom_range()的语法如下：
12.12.3 srandom()
srandom()方法允许我们手工地为对象或线程的随机数发生器（RNG）设置种子。一个进程的RNG可以使用进程的srandom()方法来设置种子（参见9.9节）。

srandom()方法的原型如下：
12.12.4 get_randstate()
get_randstate()方法重新获得一个对象的随机数发生器（RNG）的当前状态。与一个进程相关联的RNG的状态可以使用进程的get_randstate()方法重新获得（参见9.9节）。

get_randstate()方法的原型如下：
12.12.5 set_randstate()
set_randstate()方法设置一个对象的随机数发生器（RNG）的状态。与一个进程相关联的RNG的状态使用进程的set_randstate()方法来设置（参见9.9节）。

set_randstate()方法的原型如下：
链接
第十二章 随机约束, 主题


12.12.1 $urandom

链接
12.12 随机数系统函数与方法
SystemVerilog 3.1a语言参考手册
12.12.1 $urandom
12.12 随机数系统函数与方法

$urandom系统函数提供了一种机制来产生伪随机数。每次调用这个函数的时候都会返回一个新的32位的随机数。这个随机数应该是无符号的。

$urandom的语法如下：

Copy Code
function int unsigned $urandom [(int seed)];

seed是一个可选的参数，它确定了随机数产生的顺序。seed可以是任意integral表达式。如果使用相同的seed，随机数发生器应该在每次调用时产生相同的随机数序列。

随机数发生器具有确定性。每次程序执行的时候，它会循环相同的随机序列。我们可以通过一个带有外部随机变量（例如日期时间）的$urandom函数来设置种子，从而使得这个序列具有不确定性。

例如：

Copy Code
bit [64:1] addr;
$urandom(254);                // 初始化随机数发生器
addr = {$urandom, $urandom};  // 64位随机数
number = $urandom & 15;       // 4位随机数

$urandom函数类似于$random系统函数，但具有两个不同之处。$urandom返回无符号数并且自动成为线程稳定的（参见12.13.2节）。

Group

12.12 随机数系统函数与方法

链接
12.12 随机数系统函数与方法


12.12.2 $urandom_range()

链接
12.12 随机数系统函数与方法
SystemVerilog 3.1a语言参考手册
12.12.2 $urandom_range()
12.12 随机数系统函数与方法

$urandom_range()函数返回一个指定范围内的无符号整数。

$urandom_range()的语法如下：

Copy Code
function int unsigned $urandom_range(int unsigned maxval, int unsigned minval=0);

函数应该返回位于maxval ... minval范围内的一个无符号整数。

例子：

Copy Code
val = $urandom_range(7,0);

如果minval被省略，函数应该返回maxval...0范围内的一个值。

例子：

Copy Code
val = $urandom_range(7);

如果maxval小于minval，参数会被自动反转以便第一个参数大于第二个参数。

例子：

Copy Code
val = $urandom_range(0,7);

前面三个例子都产生0到7中的一个值。

$urandom_range()自动地成为线程稳定的（参见12.13.2节）。

Group

12.12 随机数系统函数与方法

链接
12.12 随机数系统函数与方法


12.12.3 srandom()

链接
12.12 随机数系统函数与方法
SystemVerilog 3.1a语言参考手册
12.12.3 srandom()
12.12 随机数系统函数与方法

srandom()方法允许我们手工地为对象或线程的随机数发生器（RNG）设置种子。一个进程的RNG可以使用进程的srandom()方法来设置种子（参见9.9节）。

srandom()方法的原型如下：

Copy Code
function void srandom(int seed);

srandom()方法使用指定的种子值初始化一个对象的随机数发生器。

Group

12.12 随机数系统函数与方法

链接
12.12 随机数系统函数与方法


12.12.4 get_randstate()

链接
12.12 随机数系统函数与方法
SystemVerilog 3.1a语言参考手册
12.12.4 get_randstate()
12.12 随机数系统函数与方法

get_randstate()方法重新获得一个对象的随机数发生器（RNG）的当前状态。与一个进程相关联的RNG的状态可以使用进程的get_randstate()方法重新获得（参见9.9节）。

get_randstate()方法的原型如下：

Copy Code
function string get_randstate();

get_randstate()方法返回与指定对象相关联的RNG的状态的一份拷贝。

RNG状态是一个未指定长度和格式的字符串。字符串的长度和内容依赖于具体实现。

Group

12.12 随机数系统函数与方法

链接
12.12 随机数系统函数与方法


12.12.5 set_randstate()

链接
12.12 随机数系统函数与方法
SystemVerilog 3.1a语言参考手册
12.12.5 set_randstate()
12.12 随机数系统函数与方法

set_randstate()方法设置一个对象的随机数发生器（RNG）的状态。与一个进程相关联的RNG的状态使用进程的set_randstate()方法来设置（参见9.9节）。

set_randstate()方法的原型如下：

Copy Code
function void set_randstate(string state);

set_randstate()方法将指定的状态拷贝到一个对象的RNG的内部状态。

RNG状态是一个未指定长度和格式的字符串。在调用set_randstate()方法的时候，如果字符串的值不是从get_randstate()获得的，或者这个字符串是从get_randstate的一个不同实现获得的，那么对set_randstate()方法的调用是未定义的。

Group

12.12 随机数系统函数与方法

链接
12.12 随机数系统函数与方法


12.13 随机稳定性

链接
第十二章 随机约束, 主题
SystemVerilog 3.1a语言参考手册
12.13 随机稳定性
第十二章 随机约束 | 主题

随机数发生器（RNG）对于线程和对象是本地的。因为被一个线程或对象返回的随机值序列独立于其它线程或对象的RNG，所以这个特性被称为随机稳定性。随机稳定性应用于：

  • 系统随机化调用，$urandom()和$urandom_range()。
  • 对象和进程随机播种方法，srandom()。
  • 对象随机化方法，randomize()。

在面对用户代码小的改变的时候，具有这种特点的测试平台能够展示更加稳定的RNG行为。另外，对于通过手工设置种子的线程和对象，它能够更精确地控制随机值的产生。

Group

第十二章 随机约束

主题
主题
描述
12.13.1 随机稳定性的特性
随机稳定性包含下列特性：

  • 线程稳定性

每一个线程对于在该进程中发生的所有随机化系统调用都具有一个独立的RNG。当产生一个新的线程的时候，它的RNG的种子在父进程中被设置成下一个随机值。这个特性被称为层次化播种。

只要进程的产生和随机数产生是以前面相同的顺序完成，那么程序和线程稳定性就能得到保证。当为一个现存的测试加入新的进程的时候，为了维持先前产生的工作的随机数稳定性，它们可以在一个代码块的尾部加入。

  • 对象稳定性

每一个类实例（对象）对于类中的所有随机化方法都具有一个独立的RNG。当使用new产生一个对象的时候，它的RNG的种子会在产生对象的进程中设置为下一个随机值。

只要对象和线程的产生以及随机数的产生是与以前相同的顺序完成，对象稳定性就能得到保证。为了维持随机数稳定性，新的对象、线程和随机数可以在现存对象被产生以后产生。

  • 手工设置种子

所有RNG的种子都可以手工设置。与层次化的播种结合起来，这个便利性使得用户能够完全定义在系统根线程上具有单个种子的子系统（层次子树）的操作。

12.13.2 线程稳定性
从$urandom系统调用返回的随机值独立于线程的执行顺序。例如：
12.13.3 对象稳定性
构建在每一个类中的randomize()方法展示了对象稳定性。这种特性使得一个实例中对randomize()的调用独立于其它实例对randomize()的调用，并且独立于其它随机化函数的调用。

例如：
链接
第十二章 随机约束, 主题


12.13.1 随机稳定性的特性

链接
12.13 随机稳定性
SystemVerilog 3.1a语言参考手册
12.13.1 随机稳定性的特性
12.13 随机稳定性

随机稳定性包含下列特性：

  • 线程稳定性

每一个线程对于在该进程中发生的所有随机化系统调用都具有一个独立的RNG。当产生一个新的线程的时候，它的RNG的种子在父进程中被设置成下一个随机值。这个特性被称为层次化播种。

只要进程的产生和随机数产生是以前面相同的顺序完成，那么程序和线程稳定性就能得到保证。当为一个现存的测试加入新的进程的时候，为了维持先前产生的工作的随机数稳定性，它们可以在一个代码块的尾部加入。

  • 对象稳定性

每一个类实例（对象）对于类中的所有随机化方法都具有一个独立的RNG。当使用new产生一个对象的时候，它的RNG的种子会在产生对象的进程中设置为下一个随机值。

只要对象和线程的产生以及随机数的产生是与以前相同的顺序完成，对象稳定性就能得到保证。为了维持随机数稳定性，新的对象、线程和随机数可以在现存对象被产生以后产生。

  • 手工设置种子

所有RNG的种子都可以手工设置。与层次化的播种结合起来，这个便利性使得用户能够完全定义在系统根线程上具有单个种子的子系统（层次子树）的操作。

Group

12.13 随机稳定性

链接
12.13 随机稳定性


12.13.2 线程稳定性

链接
12.13 随机稳定性
SystemVerilog 3.1a语言参考手册
12.13.2 线程稳定性
12.13 随机稳定性

从$urandom系统调用返回的随机值独立于线程的执行顺序。例如：

Copy Code
integer x, y, z;

fork
    // 在线程的起始处设置一个种子
    begin process::self.srandom(100); x = $urandom; end

    // 在一个线程执行期间设置一个种子
    begin y = $urandom; process::self.srandom(200); end

    // 从线程RNG中移动2个值
    begin z = $urandom + $urandom; end
join

上面的程序片断演示了几个特性：

  • 线程局部性。为x、y和z返回的值独立于线程执行的顺序。这是一个很重要的特性，因为它使得子系统的开发具有独立性、可控性和可预测性。
  • 层次化播种。当一个线程被产生的时候，它的随机状态在初始化的时候将来自父线程的下一个随机值作为种子。这三个分叉的线程都从父线程中设置种子。

每一个线程都使用一个唯一的值设置种子，种子主要由它的父线程确定。一个线程执行子树的根确定了它的子线程的随机播种。这就使得整个子树可以被移动，并通过手工为它们的根线程设置种子来保留它们的行为。

Group

12.13 随机稳定性

链接
12.13 随机稳定性


12.13.3 对象稳定性

链接
12.13 随机稳定性
SystemVerilog 3.1a语言参考手册
12.13.3 对象稳定性
12.13 随机稳定性

构建在每一个类中的randomize()方法展示了对象稳定性。这种特性使得一个实例中对randomize()的调用独立于其它实例对randomize()的调用，并且独立于其它随机化函数的调用。

例如：

Copy Code
class Foo;
    rand integer x;
endclass

class Bar;
    rand integer y;
endclass

initial begin
    Foo foo = new();
    Bar bar = new();
    integer z;
    void'(foo.randomize());
    // z = $random;
    void'(bar.randomize());
end
  • 为foo.x和bar.y返回的值相互之间是独立的。
  • 对randomize()的调用独立于$random系统调用。如果将上面的z = $random解除注释，那么对foo.x和bar.y的赋值不会发生变化。
  • 每一个实例的随机值由具有一个唯一的源，它们可以被独立地设置种子。当实例被产生的时候，这个随机种子从父线程中获取。
  • 对象可以在使用srandom()方法的任何时候设置种子。
Copy Code
class Foo;
    function new (integer seed);
        // 为this实例设置一个新的种子
        this.srandom(seed);
    endfunction
endclass

一旦产生了一个对象，那么在另外的线程访问对象之前不能保证产生线程能够改变对象的随机状态。因此，最好的方法是对象在它的new方法中自己设置种子而不是在外部设置种子。

一个对象的种子可以从任何线程中设置。然而，一个线程的种子只能在线程本身中设置。

Group

12.13 随机稳定性

链接
12.13 随机稳定性


12.14 为随机化手工设置种子

链接
第十二章 随机约束
SystemVerilog 3.1a语言参考手册
12.14 为随机化手工设置种子
第十二章 随机约束

每一个对象维护了它自己的内部随机数发生器，这个随机数发生器它的randomize()方法所专用。这就使得对象能够各自独立地被随机化并能够相对于其它的随机化函数独立地调用。当产生一个对象的时候，它的随机数发生器（RNG）能够使用来自产生这个对象的线程的RNG的下一个值设置种子。这个过程被称为层次化的对象播种。

有时我们希望能够使用srandom()方法手工地设置种子。这种功能或者在一个类方法中，或者在类定义的外部完成。

作为一个类方法在内部为RNG设置种子的例子如下：

Copy Code
class Packet;
    rand bit[15:0] header;
    ...

    function new (int seed);
        this.srandom(seed);
        ...
    endfunction
endclass

在外部设置RNG种子的例子如下：

Copy Code
Packet p = new(200); // 使用200作为种子产生p
p.srandom(300);      // 重新使用300设置p的种子

在一个对象的new()函数中调用srandom()能够确保对象的RNG在任何类成员值被随机化之前被设置新的种子。

Group

第十二章 随机约束

链接
第十二章 随机约束


12.15 随机加权的条件 — randcase

链接
第十二章 随机约束
SystemVerilog 3.1a语言参考手册
12.15 随机加权的条件 — randcase
第十二章 随机约束
Copy Code
statement_item ::=         // 引用自附录A.6.4
    ...
  | randcase_statement

randcase_statement ::=     // 引用自附录A.6.7
    randcase randcase_item {randcase_item} endcase

randcase_item ::= expression : statement_or_null

语法12-11 — randcase语法（摘录自附录A）

randcase关键字引入了一个条件语句，它可以随机地选择它的一条分支。randcase条目表达式是非负的integral值，它们构成了分支权重。一个条目的权重除以所有权重的和指定了该分支被选中的概率。例如：

Copy Code
randcase
    3 : x = 1;
    1 : x = 2;
    4 : x = 3;
endcase

在这个例子中，所有权重的和为8，所以第一条分支被选中的概率为0.375，第二条分支被选中的概率为0.125，第三条语句被选中的概率为0.5。

如果一条分支被指定了为0的权重，那么这条分支不会被选中。如果所有的randcase条目的权重都被指定为0，那么没有条目会被选中，并且可以发布一个警告信息。

randcase权重可以是任意表达式，而不仅仅是常量。例如：

Copy Code
byte a, b;

randcase
    a + b : x = 1;
    a - b : x = 2;
    a ^ ~b : x = 3;
    12'b800 : x = 4;
endcase

每一个权重表达式的精度是依据自决的。权重的和使用标准的加法语义计算（所有权重的最大精度），其中被一个被加数都是无符号的。每一个权重表达式以一个未指定的顺序至多计算一次（具体的实现可以缓存相同的表达式）。在上面的例子中，前三个权重表达式使用8位的精度计算，第四个表达式使用12位精度计算；结果权重以12位精度以无符号值相加。权重选择接下来会使用无符号的12位比较。

每一次对rancase的调用都会在0到权重之和的范围内重新获得一个随机数。接下来权重以声明的顺序被选择：较小的随机数对应于第一条（最上面的）权重语句。

rancase语句展示了线程稳定性。随机数从$urandom_range()获得，因此随机数独立于线程执行的顺序。这能够导致对$urandom_range()的多次调用以便处理大于32位的情况。

Group

第十二章 随机约束

链接
第十二章 随机约束


12.16 随机序列产生 — randsequence

链接
第十二章 随机约束, 主题
SystemVerilog 3.1a语言参考手册
12.16 随机序列产生 — randsequence
第十二章 随机约束 | 主题

分析程序生成器，例如yacc，使用巴科斯-诺尔范式（BNF）或类似的符号来描述被分析语言的文法。因此文法被用来产生一个程序，它能够检查一个标记流是否代表了该语言中一个语法正确的表达方式。SystemVerilog的序列产生器反转了这个过程。它使用文法来随机地产生一个文法所描述的语言的正确的表达方式（也就是一个标记流）。随机序列发生器对于随机地产生结构化的激励序列（例如指令或网络流量模式）非常有用。

序列发生器使用个randsequence块内的一组规则和生成式。randsequence块的语法如下：

Copy Code
statement_item ::=           // 引用自附录A.6.4
    ...
  | randsequence_statement

randsequence_statement ::= randsequence([production_identifier])  // 引用自附录A.6.12
        production {production}
    endsequence

production ::= [function_data_type] production_name[(tf_port_list)]:rs_rule{|rs_rule};

rs_rule ::= rs_production_list [:= expression[rs_code_block]]

rs_production_list ::=
    rs_prod {rs_prod}
  | rand join [(expression)] production_item production_item {production_item}

rs_code_block ::= {{data_declaration} {statement_or_null}}

rs_prod ::=
    production_item
  | rs_code_block
  | rs_if_else
  | rs_repeat
  | rs_case

production_item ::= production_identifier[(list_of_arguments)]

rs_if_else ::= if(expression) production_item [else production_item]

rs_repeat ::= repeat(expression) production_item

rs_case ::= case(expression) rs_case_item {rs_case_item} endcase

rs_case_item ::=
    expression{, expression}:production_item
  | default [:] production_item

语法12-12 — randsequence语法（摘录自附录A）

一个randsequence文法有一个或多个生成式组成。每一个生成式都包含了一个名字和一个生成式条目的列表。生成式条目可以进一步分类成端接和非端接。非端接根据端接和其它的非端接定义。一个端接是一个不可分割的条目，除了与其关联的代码块外它不需要进一步的定义。最终，每一个非端接被分解成它的端接。一个生成式列表包含了一连串的生成式条目，它指示这些条目必须按顺序形成流。单个生成式可以包含以|符号分割的多个生成式列表。以|符号分割的生成式列表意味着一组选择，发生器能够随机地对它们做出选择。

下面的简单的例子演示了一些基本概念：

Copy Code
randsequence(main)
    main   : first second done;
    first  : add | dec;
    second : pop | push;
    done   : {$display("done");};
    add    : {$display("add");};
    dec    : {$display("dec");};
    pop    : {$display("pop");};
    push   : {$display("push");};
endsequence

生成式main依据三个非端接（first、second和done）定义。当main被选择的时候，它产生序列first，second和done。当first被产生的时候，它被分解成它的生成式，它在add和dec之间指定一个随机选择。类似地，second生成式在pop和push之间指定一个选择。所有其它的生成式都是端接；它们被它们的代码块完全指定，在这个例子中就是显示生成式名字。因此，文法会导致下列可能的结果：

Copy Code
add pop done
add push done
dec pop done
dec push done

当randsequence语句被执行的时候，它产生一个文法驱动的随机生成式的流。当每一个生成式被产生的时候，执行它的相关代码块的边带效应产生了期望的激励。除了基本文法外，序列发生器规定了随机权重、交叉和其它的控制机制。尽管randsequence语句在本质上不会产生一个循环，然而一个递归的生成式会导致循环。

randsequence语句产生一个自动的范围。所有的生成式标识符对于这个范围来讲是本地的。另外，在randsequence块内部的每一个代码块都产生一个匿名的自动范围。对在代码块内部的变量的层次化引用是不被允许的。为了声明一个静态变量，必须使用static前缀。randsequence关键字可以跟着一个可选的生成式名字（在圆括号内），它指定了顶层生成式的名字。如果没有指定的话，第一个生成式成为顶层生成式。

Group

第十二章 随机约束

主题
主题 | 描述
12.16.1 随机生成式权重 | 一个生成式列表被产生的概率可以通过为生成式列表赋值一个权重来改变。一个特定的生成式列表被产生的概率与它的权重成比例。
12.16.2 If...else生成式语句 | 通过if...else生成式语句可以使得一个生成式成为有条件的。if...else生成式语句的语法如下：
12.16.3 case生成式语句 | 一个生成式可以使用case生成式语句从一组可选项中选择。case生成式语句的语法如下：
12.16.4 repeat生成式语句 | repeat生成式语句被用来在一个生成式上迭代指定的次数。repeat生成式语句的语法如下：
12.16.5 交叉生成式 — rand join | rand join生成式控制被用来随机地交叉两个或多个生成式序列而又能维持每一个序列的相对顺序。rand join生成式控制的语法如下：
12.16.6 中止生成式 — break和return | 两个过程化语句可以用来提前中止一个生成式：break和return。这两个语句可以出现在任意代码块中；它们的不同之处在于它们退出的范围不同。 break语句中止序列的产生。当在一个生成式代码块中执行break语句的时候，它会强制跳出randsequence块。例如：
12.16.7 生成式间的值传递 | 数据可以传递到将要产生的生成式，并且产生的生成式可以将数据返回到触发的非端接生成式。向生成式传递数据类似于一个任务调用，并且使用相同的语法。从一个生成式返回数据要求为生成式声明一个类型，这与函数声明使用相似的语法。 接收数据的生成式包含一个形式参数列表。为生成式声明参数的语法类似于一个任务原型；向生成式传递数据的语法与一个任务调用相同。
链接
第十二章 随机约束, 主题


12.16.1 随机生成式权重

链接
12.16 随机序列产生 — randsequence
SystemVerilog 3.1a语言参考手册
12.16.1 随机生成式权重
12.16 随机序列产生 — randsequence

一个生成式列表被产生的概率可以通过为生成式列表赋值一个权重来改变。一个特定的生成式列表被产生的概率与它的权重成比例。

Copy Code
production ::= [function_data_type] production_name[(tf_port_list)]:rs_rule{|rs_rule};

rs_rule ::= rs_production_list[:=expression[rs_code_block]]

:=操作符将表达式指定的权重赋值到它的生成式列表。权重表达式必须计算成integral非负的值。权重只有当它被赋值到可供选择的生成式的时候才有意义，也就是使用一个|分割的生成式列表。当包含权重表达式的生成式被选择的时候权重表达式会被计算，因此使得权重能够动态地改变。例如，前面例子中的第一个生成式可以按如下方式重写：

Copy Code
first : add := 3
      | dec := 2
      ;

在这里根据两个加权生成式列表add和dec定义了生成式first。生成式add会以60%的概率产生，生成式dec会以40%的概率产生。如果没有指定权重，一个生成式会将1作为它的权重。如果仅仅指定了某些权重，那么未指定的权重应该使用1作为权重。

Group

12.16 随机序列产生 — randsequence

链接
12.16 随机序列产生 — randsequence


12.16.2 If...else生成式语句

链接
12.16 随机序列产生 — randsequence
SystemVerilog 3.1a语言参考手册
12.16.2 If...else生成式语句
12.16 随机序列产生 — randsequence

通过if...else生成式语句可以使得一个生成式成为有条件的。if...else生成式语句的语法如下：

Copy Code
rs_if_else ::= if (expression) production_item [else production_item]

expression可以是能够计算成一个布尔值的任意表达式。如果表达式计算成真，那么会产生紧跟在表达式后面的生成式，否则产生跟在可选的else语句后面的生成式。例如：

Copy Code
randsequence()
    ...
    PP_PO : if (depth < 2) PUSH else POP;
    PUSH  : {++depth; do_push();};
    POP   : {--depth; do_pop();};
endsequence

这个例子定义了生成式PP_OP。如果depth变量小于2，那么产生生成式PUSH，否则产生生成式POP。depth变量既被PUSH生成式的代码块更新也被POP生成式的代码块更新。

Group

12.16 随机序列产生 — randsequence

链接
12.16 随机序列产生 — randsequence


12.16.3 case生成式语句

链接
12.16 随机序列产生 — randsequence
SystemVerilog 3.1a语言参考手册
12.16.3 case生成式语句
12.16 随机序列产生 — randsequence

一个生成式可以使用case生成式语句从一组可选项中选择。case生成式语句的语法如下：

Copy Code
rs_case ::= case (expression) rs_case_item {rs_case_item} endcase

rs_case_item ::=
    expression {, expression} : production_item
  | default [:] production_item

除了下述的说明外，case生成式语句类似于过程化的case语句。case表达式被计算，它的值与每一个case条目表达式（它们以指定的顺序计算和比较）进行比较。产生的生成式是与case表达式匹配的第一个case条目表达式对应的生成式。如果没有找到匹配的case条目表达式，那么产生与可选的default条目相对应的生成式。

在一个case生成式语句中具有多个缺省语句是非法的。使用逗号分割多个case条目表达式能够共享相同的生成式。例如：

Copy Code
randsequence()
    SELECT : case (device & 7)
                 0       : NETWORK
                 1, 2    : DISK
                 default : MEMORY
             endcase;
    ...
endsequence

上面的例子定义了具有一个case语句的生成式SELECT。case表达式(device & 7)被计算并与两个case条目表达式进行比较。如果表达式与0匹配，那么产生生成式NETWORK；如果与1或2匹配，那么产生DISK生成式；否则产生MOMORY生成式。

Group

12.16 随机序列产生 — randsequence

链接
12.16 随机序列产生 — randsequence


12.16.4 repeat生成式语句

链接
12.16 随机序列产生 — randsequence
SystemVerilog 3.1a语言参考手册
12.16.4 repeat生成式语句
12.16 随机序列产生 — randsequence

repeat生成式语句被用来在一个生成式上迭代指定的次数。repeat生成式语句的语法如下：

Copy Code
rs_repeat ::= repeat (expression) production_item

重复表达式必须被计算为一个非负的integral值。这个值指定了对应的生成式被产生的次数。例如：

Copy Code
randsequence()
    ...
    PUSH_OPER : repeat($urandom_range(2, 6)) PUSH;
    PUSH : ...
endsequence

在这个例子中，PUSH_OPER生成式指出：根据$urandom_range()返回值的不同，PUSH生成式可以被产生一个随机的次数（在2和6之间）。

repeat生成式语句本身不会被提前中止。我们应该使用一个break语句中止整个randsequence块（参见12.16.6节）。

Group

12.16 随机序列产生 — randsequence

链接
12.16 随机序列产生 — randsequence


12.16.5 交叉生成式 — rand join

链接
12.16 随机序列产生 — randsequence
SystemVerilog 3.1a语言参考手册
12.16.5 交叉生成式 — rand join
12.16 随机序列产生 — randsequence

rand join生成式控制被用来随机地交叉两个或多个生成式序列而又能维持每一个序列的相对顺序。rand join生成式控制的语法如下：

Copy Code
rs_production_list ::=
    rs_prod {rs_prod}
  | rand join [(expression)] production_item production_item {production_item}

例如：

Copy Code
randsequence(TOP)
    TOP : rand join S1 S2;
    S1  : A B;
    S2  : C D;
endsequence

这个发生器会随机地产生下列的序列：

Copy Code
A B C D
A C B D
A C D B
C D A B
C A B D
C A D B

紧跟在rand join关键字之后的可选的表达式必须是位于0.0到1.0范围内的一个实数。这个表达式的值代表了被交叉的序列长度影响一个序列被选择概率的程度。序列的长度是在一个给定的时间没有交叉的生成式的数目。如果表达式为0.0，那么最短的序列具有较高的优先级；如果表达式为1.0，那么最长的序列被指定了优先级。例如，使用前面的例子：

Copy Code
TOP : rand join (0.0) S1 S2;

对序列A B C D C D A B给出了较高的优先级。

Copy Code
TOP : rand join (1.0) S1 S2;

给序列A C B D A C D B C A B D C A D B赋予了较高的优先级。

如果没有说明的话，发生器使用0.5作为缺省值，它不会对任何序列长度区分优先级。

在每一个步骤，发生器将非端接符号交叉成深度1。

Group

12.16 随机序列产生 — randsequence

链接
12.16 随机序列产生 — randsequence


12.16.6 中止生成式 — break和return

链接
12.16 随机序列产生 — randsequence
SystemVerilog 3.1a语言参考手册
12.16.6 中止生成式 — break和return
12.16 随机序列产生 — randsequence

两个过程化语句可以用来提前中止一个生成式：break和return。这两个语句可以出现在任意代码块中；它们的不同之处在于它们退出的范围不同。

break语句中止序列的产生。当在一个生成式代码块中执行break语句的时候，它会强制跳出randsequence块。例如：

Copy Code
randsequence()
    WRITE : SETUP DATA;
    SETUP : {if(fifo_length >= max_length) break;} COMMAND;
    DATA  : ...
endsequence

next_statement : ...

当上面的例子在SETUP生成式中执行break语句的时候，不会产生COMMAND生成式，并会继续执行标记为next_statement的行。在一个循环语句中break语句的使用与8.6节中描述的方式相同。因此，break语句中止最小包围的循环语句，否则是randsequence块。

return语句中止生成当前的生成式。当在一个生成式代码块中执行一个return语句的时候，会中止当前的生成式。序列产生会继续紧跟在被中止的生成式之后的下一个生成式。例如：

Copy Code
randsequence()
    TOP : P1 P2;
    P1  : A B C;
    P2  : A {if(flag == 1) return;} B C;
    A   : {$display("A");};
    B   : {if(flag == 2) return; $display("B");};
    C   : {$display("C");};
endsequence

根据flag变量值的不同，上面的例子具有下列的结果：

Copy Code
flag == 0 ==> A B C A B C
flag == 1 ==> A B C A
flag == 2 ==> A C A C

当flag == 1的时候，生成式P2会在产生A之后中止。当flag == 2的时候，生成式B会中止两次（一次在P1中，另外一次在P2中），但每一次都会继续产生下一个生成式C。

Group

12.16 随机序列产生 — randsequence

链接
12.16 随机序列产生 — randsequence


12.16.7 生成式间的值传递

链接
12.16 随机序列产生 — randsequence
SystemVerilog 3.1a语言参考手册
12.16.7 生成式间的值传递
12.16 随机序列产生 — randsequence

数据可以传递到将要产生的生成式，并且产生的生成式可以将数据返回到触发的非端接生成式。向生成式传递数据类似于一个任务调用，并且使用相同的语法。从一个生成式返回数据要求为生成式声明一个类型，这与函数声明使用相似的语法。

接收数据的生成式包含一个形式参数列表。为生成式声明参数的语法类似于一个任务原型；向生成式传递数据的语法与一个任务调用相同。

Copy Code
production ::= [function_data_type] production_name[(tf_port_list)]:rs_rule{| rs_rule};

production_item ::= production_identifier[(list_of_arguments)]

例如，前面的第一个例子可以按如下方式重写：

Copy Code
randsequence(main)
    main   : first second gen;
    first  : add | dec;
    second : pop | push;
    add    : gen("add");
    dec    : gen("dec");
    pop    : gen("pop");
    push   : gen("push");
    gen(string s = "done"):{$display(s);};
endsequence

在这个例子中，生成式gen接受一个字符串参数，其缺省值为"done"。五个其它的生成式产生这个生成式，每一个都具有一个不同的参数（main中的一个使用缺省知）。

一个生成式产生了一个范围，这个范围包含了这个生成式的所有规则和代码块。因此，传递给一个生成式的参数在整个生成式中有效。

返回数据的生成式要求一个类型声明。可选的返回类型位于生成式的前面。没有说明一个返回类型的生成式被假定为具有void类型。

我们使用带有一个表达式的return语句从一个生成式中返回一个值。当return语句被用于一个具有返回值的生成式中的时候，它必须说明一个具有正确类型的表达式，这就像一个非void函数一样。return语句将指定的表达式赋值到对应的生成式。返回值可以在触发返回一个值得生成式的产生的生成式的代码块中读取。在这些代码块中，返回值使用生成式名字加上一个可选的索引表达式来访问。在每一个生成式中，一个具有相同名字的变量会被隐含地为每一个返回一个值的生成式声明。

如果相同的生成式出现了多次，那么一个起始于1的一维数组会被隐含地声明。例如：

Copy Code
randsequence(bin_op)
    void bin_op : value operator value  // void类型是可选的
                  {$display("%s %b %b", operator, value[1], value[2]);}
                  ;
    bit [7:0] value : {return $urandom};
    string operator : add  := 5 {return "+";}
                    | dec  := 2 {return "-";}
                    | mult := 1 {return "*";}
                    ;
endsequence

在上面的例子中，operator和value生成式分别返回一个字符串和一个8位的值。生成式bin_op包含了这两个具有返回值的生成式。因此，与生成式bin_op相关联的代码块具有下列隐含的变量声明访问：

Copy Code
bit [7:0] value [1:2];
string operator;

访问这些隐含变量产生从对应的生成式返回的值。当执行的时候，上面的例子显示一个简单的三条目的随机序列：一个操作符跟着两个8位的值。操作符+、-、和*分别以5/8、2/8、和1/8的分布被选择。

只有已经被产生的生成式的返回值（也就是访问它们的代码块的左侧）可以被重新获取。试图读取一个还没有产生的生成式的返回值会导致一个为定义的值。例如：

Copy Code
X : A {int y = B;} B;                  // 对B的无效的访问
X : A {int y = A[2];} B A;             // 对A[2]的无效的访问
X : A {int y = A;} B {int j = A + B;}; // 有效

randsequence产生的序列可以作为生成式产生的边带效应被直接驱动到一个系统当中，或者这个序列可以被产生以便进行后续的处理。例如，下列的函数产生并返回一个位于其参数给定范围内的随机数队列。第一个和最后一个队列条目分别对应于下边界和上边界。而且，队列的尺寸根据生成式的权重被随机地选择。

Copy Code
function int[$] GenQueue(int low, int high);
    int[$] q;

    randsequence()
        TOP          : BOUND(low) LIST BOUND(high);
        LIST         : LIST ITEM := 8{q = {q, ITEM};}
                          | ITEM := 2{q = {q, ITEM};}
                          ;
        int ITEM     : {return $urandom_range(low, high);};
        BOUND(int b) : {q = {q, b};};
    endsequence

    GenQueue = q;
endfunction

当函数GenQueue中的randsequence执行的时候，它产生TOP生成式，TOP生成式会产生三个生成式：具有参数low的BOUND、LIST和具有参数high的BOUND。BOUND生成式简单地将它的参数附加到队列当中。LIST生成式包含了一个加权的LIST ITEM生成式和一个ITEM生成式。产生LIST ITEM生成式的概率为80%，它会引起LIST生成式被递归地产生，因此延缓了ITEM生成式的产生。LIST ITEM和ITEM的选择会被重复直到选择ITEM（它会中止LIST生成式）。每次产生ITEM生成式的时候，它会在指定的范围内产生一个随机数，这个随机数会在以后附加到队列。

下面的例子使用一个randsequence块为一个DSL包网络产生随机流量。

Copy Code
class DSL; ... endclass  // 产生有效DSL包的类

randsequence (STREAM)
    STREAM               : GAP DATA := 80
                         | DATA := 20;
    DATA                 : PACKET(0) := 94{transmit(PACKET);}
                         | PACKET(1) := 6{transmit(PACKET);};
    DSL PACKET (bit bad) : { DSL d = new;
                             if (bad) d.crc ^= 23;  // 损坏的crc
                             return d;
                           };
    GAP                  : {##{$urandom_range(1, 20)};};
endsequence

在这个例子中，流量包含了一个数据包（好的和坏的）和及其间隙的流。第一个生成式STREAM指出：在80%的时间里流量包含了一个GAP然后跟着一些DATA，在20%的时间里流量仅仅包含了DATA（没有GAP）。第二个生成式DATA指出：所有的数据包中有94%是好的数据包，另外余下的6%是坏的数据包。PACKET生成式实现了DSL包的产生；如果生成式参数是1，那么会通过损坏一个有效的DSL包的crc来产生一个坏包。最后，GAP生成式通过在1到20之间等待一个随机的周期数目来实现发送间隔。

Group

12.16 随机序列产生 — randsequence

链接
12.16 随机序列产生 — randsequence


第十三章 进程间的同步与通信

链接
主题
SystemVerilog 3.1a语言参考手册
第十三章 进程间的同步与通信
主题
主题
主题
描述
13.1 简介（一般信息）
对于用来对一个复杂系统或高度灵活的测试平台进行建模的动态进程来说，高层次并且易于使用的同步和通信机制对于控制它们之间的通信是非常必要的。Verilog提供了基本的同步机制（也就是->和@），但它们仅限于静态对象，虽然这对于硬件级的同步来说是足够的，然而它们却不能满足高度动态、灵活的测试平台的需要。在系统级，Verilog的一个本质上的限制就是它缺乏创建动态事件和通信通道的能力，而这些对于创建动态进程却是必需的。

SystemVerilog加入了强大而又易于使用的同步和通信机制的集合，所有这些都可以动态地产生和回收。SystemVerilog加入了一个内建的semaphore类，这个内建类可以用来同步以及相互排斥地共享资源。一个mailbox内建类可以用作是进程间的通信通道。SystemVerilog还增强了Verilog的命名事件数据类型以便满足许多系统级的同步需求。

semaphore和mailboxe是内建类型，尽管如此，它们仍然是类，并且可以用作基类以便衍生额外的更高层次的类。这些内建的类驻留在内建的std包中（参见7.10.1节），因此它们可以在任何其它范围内被用户代码重新定义。
13.2 semaphore
从概念上讲，一个semaphore是一个桶。当为semaphore分配内存的时候，会产生一个包含固定数目键值的桶。使用semaphore的进程在继续执行之前必须首先从桶中获得一个键值。如果一个特定的进程要求一个键值，那么只能同时出现固定数目的进程。所有其它进程必须等待直到足够数目的键值返回到桶中。典型情况下semaphore被用来控制对共享资源的互斥访问，以及用来实现基本的同步。

产生一个semaphore的例子如下：
13.3 mailbox
maibox是一种通信机制，它使得消息能够在进程间通信。被一个进程发送到一个mailbox的数据可以被另外一个进程重新获得。

从概念上讲，mailbox的行为就像一个真实的邮箱一样。当一封信被分发并且放入到邮箱的时候，一个人可以重新获得这封信（以及存储在其中的任何数据）。然而，如果当这个人检查邮箱的时候这封信还没有被分发，那么这个人必须做出选择：它要么等待这封信被分发，要么在下一次检查邮箱的时候重新获得这封信。与此类似，SystemVerilog的mailbox以一个可控的方式来传输和接收数据。在产生mailbox的时候，它可以具有有界的队列尺寸也可以具有无边界的尺寸。当一个有界mailbox包含了其边界数目的消息的时候，mailbox会变满。一个试图向已经满了的mailbox放置消息的进程应该被挂起，直到在mailbox队列中具有足够的空间。在一个发送操作中，无边界mailbox永远也不会挂起一个线程。

产生一个mailbox的例子如下：
13.4 参数化的mailbox
缺省的mailbox是无类型的，也就是说，单个mailbox可以发送和接收任何类型的数据。这是一个非常强大的机制，然而不幸的是，它也会因为一个消息与用来重新获得消息的变量间的类型不匹配而导致运行时错误。一个mailbox经常被用来传输一个特定的消息类型，在这种情况下，如果能够在编译时发现类型不匹配，那会是很有用的。

参数化的mailbox与参数化类（参见11.23节）、模块和接口使用相同的机制。
13.5 事件
在Verilog中，命名的事件是静态对象，它可以通过->操作符触发，并且通过@操作符进程可以等待一个事件被触发。SystemVerilog事件支持相同的基本操作，但它从几个方面增强了Verilog事件。最为显著的增强是：Verilog命名事件的触发状态没有持续时间，而在SystemVerilog中，这个触发状态在事件被触发的整个时间步值内持续。而且，SystemVerilog事件作为同步队列的句柄使用，因此，它们可以作为参数传递给任务，并且它们可以赋值到另外一个事件或者与另外一个事件进行比较。

现存的Verilog事件操作（@和->）是后向兼容的，当使用在静态Verilog上下文中的时候可以继续以相同的方式工作。下面所描述的其它功能可以在静态上下文或动态上下文中作用于所有的事件。

SystemVerilog事件为一个底层的同步对象提供了一个句柄。当进程等待一个事件被触发的时候，进程被放入到一个在同步对象内部维护的队列当中。进程可以或者通过@操作符，或者通过使用wait()结构检查它们的触发状态来等待一个SystemVerilog事件被触发。事件通过使用->或->>操作符来触发。
13.6 事件排序：wait_order()
wait_order结构会挂起调用进程直到所有指定的事件以指定的顺序（从左到右）被触发，或者任何为触发的事件被乱序触发，并因此会导致操作失败。

wait_order结构的语法如下：
13.7 事件变量
一个事件是一个唯一具有几个重要特性的数据类型。与Verilog不同，SystemVerilog事件可以被赋值到另外一个事件。当一个事件赋值到另外一个事件的时候，源事件的同步队列被源事件和目标事件所共享。从这个意义上讲，事件是一个全功能的变量而不仅仅是标签。
链接
主题


13.1 简介（一般信息）

链接
第十三章 进程间的同步与通信
SystemVerilog 3.1a语言参考手册
13.1 简介（一般信息）
第十三章 进程间的同步与通信

对于用来对一个复杂系统或高度灵活的测试平台进行建模的动态进程来说，高层次并且易于使用的同步和通信机制对于控制它们之间的通信是非常必要的。Verilog提供了基本的同步机制（也就是->和@），但它们仅限于静态对象，虽然这对于硬件级的同步来说是足够的，然而它们却不能满足高度动态、灵活的测试平台的需要。在系统级，Verilog的一个本质上的限制就是它缺乏创建动态事件和通信通道的能力，而这些对于创建动态进程却是必需的。

SystemVerilog加入了强大而又易于使用的同步和通信机制的集合，所有这些都可以动态地产生和回收。SystemVerilog加入了一个内建的semaphore类，这个内建类可以用来同步以及相互排斥地共享资源。一个mailbox内建类可以用作是进程间的通信通道。SystemVerilog还增强了Verilog的命名事件数据类型以便满足许多系统级的同步需求。

semaphore和mailboxe是内建类型，尽管如此，它们仍然是类，并且可以用作基类以便衍生额外的更高层次的类。这些内建的类驻留在内建的std包中（参见7.10.1节），因此它们可以在任何其它范围内被用户代码重新定义。

Group

第十三章 进程间的同步与通信

链接
第十三章 进程间的同步与通信


13.2 semaphore

链接
第十三章 进程间的同步与通信, 主题
SystemVerilog 3.1a语言参考手册
13.2 semaphore
第十三章 进程间的同步与通信 | 主题

从概念上讲，一个semaphore是一个桶。当为semaphore分配内存的时候，会产生一个包含固定数目键值的桶。使用semaphore的进程在继续执行之前必须首先从桶中获得一个键值。如果一个特定的进程要求一个键值，那么只能同时出现固定数目的进程。所有其它进程必须等待直到足够数目的键值返回到桶中。典型情况下semaphore被用来控制对共享资源的互斥访问，以及用来实现基本的同步。

产生一个semaphore的例子如下：

Copy Code
semaphore smTx;

semaphore是一个内建的类，它提供了下列方法：

  • 产生一个具有指定数目键值的semaphore：new()
  • 从桶中获取一个或多个键值：get()
  • 向桶中返回一个或多个键值：put()
  • 尝试无阻塞地获取一个或多个键值：try_get()
Group

第十三章 进程间的同步与通信

主题
主题
描述
13.2.1 new()
semaphore使用new()方法产生。

semaphore new()方法的原型如下：
13.2.2 put()
semaphore put()方法被用来将键值返回到一个semaphore中。

put()方法的原型如下：
13.2.3 get()
semaphore get()方法被用来从一个semaphore中获得指定数目的键值。

get()方法的原型如下：
13.2.4 try_get()
semaphore try_get()方法被用来无阻塞地从一个semaphore中获得指定数目的键值。

try_get()方法的原型如下：
链接
第十三章 进程间的同步与通信, 主题


13.2.1 new()

链接
13.2 semaphore
SystemVerilog 3.1a语言参考手册
13.2.1 new()
13.2 semaphore

semaphore使用new()方法产生。

semaphore new()方法的原型如下：

Copy Code
function new(int keyCount = 0);

KeyCount指定了最初被分配到semaphore桶中的键值的数目。当进入桶中的键值比移出桶中的键值的数目多的时候，桶中键值的数目可以超过KeyCount。KeyCount的缺省值为0。

new()函数返回semaphore的句柄，如果没有产生semaphore则返回null。

Group

13.2 semaphore

链接
13.2 semaphore


13.2.2 put()

链接
13.2 semaphore
SystemVerilog 3.1a语言参考手册
13.2.2 put()
13.2 semaphore

semaphore put()方法被用来将键值返回到一个semaphore中。

put()方法的原型如下：

Copy Code
task put(int keyCount = 1);

keyCount指定了返回到semaphore中的键值的数目，它的缺省值为1。

当调用semaphore.put()任务的时候，指定数目的键值被返回到semaphore中。如果一个进程已经被挂起来等待一个键值的话，当返回了足够的键值后这个进程应该继续执行。

Group

13.2 semaphore

链接
13.2 semaphore


13.2.3 get()

链接
13.2 semaphore
SystemVerilog 3.1a语言参考手册
13.2.3 get()
13.2 semaphore

semaphore get()方法被用来从一个semaphore中获得指定数目的键值。

get()方法的原型如下：

Copy Code
task get(int keyCount = 1);

keyCount指定了需要从semaphore中获得的键值的数目，它的缺省值为1。

如果指定的键值数目有效，那么方法返回并且进程会继续执行；如果指定的键值数目无效，进程会阻塞直到键值变成有效。

semaphore等待队列是先进先出（FIFO）。这种方式不能保证进程到达队列的顺序，semaphore仅仅能够保持进程到达的顺序。

Group

13.2 semaphore

链接
13.2 semaphore


13.2.4 try_get()

链接
13.2 semaphore
SystemVerilog 3.1a语言参考手册
13.2.4 try_get()
13.2 semaphore

semaphore try_get()方法被用来无阻塞地从一个semaphore中获得指定数目的键值。

try_get()方法的原型如下：

Copy Code
function int try_get(int keyCount = 1);

keyCount指定了需要从semaphore中获得的键值的数目，它的缺省值为1。

如果指定的键值数目有效，那么try_get()方法返回1并且进程会继续执行；如果指定的键值数目无效，那么try_get()方法返回0。

Group

13.2 semaphore

链接
13.2 semaphore


13.3 mailbox

链接
第十三章 进程间的同步与通信, 主题
SystemVerilog 3.1a语言参考手册
13.3 mailbox
第十三章 进程间的同步与通信 | 主题

maibox是一种通信机制，它使得消息能够在进程间通信。被一个进程发送到一个mailbox的数据可以被另外一个进程重新获得。

从概念上讲，mailbox的行为就像一个真实的邮箱一样。当一封信被分发并且放入到邮箱的时候，一个人可以重新获得这封信（以及存储在其中的任何数据）。然而，如果当这个人检查邮箱的时候这封信还没有被分发，那么这个人必须做出选择：它要么等待这封信被分发，要么在下一次检查邮箱的时候重新获得这封信。与此类似，SystemVerilog的mailbox以一个可控的方式来传输和接收数据。在产生mailbox的时候，它可以具有有界的队列尺寸也可以具有无边界的尺寸。当一个有界mailbox包含了其边界数目的消息的时候，mailbox会变满。一个试图向已经满了的mailbox放置消息的进程应该被挂起，直到在mailbox队列中具有足够的空间。在一个发送操作中，无边界mailbox永远也不会挂起一个线程。

产生一个mailbox的例子如下：

Copy Code
mailbox mbxRcv;

mailbox是一个内建的类，它提供了下列方法：

  • 产生一个mailbox：new()
  • 将一个消息放置到一个mailbox中：put()
  • 尝试将一个消息无阻塞地放置到一个mailbox中：try_put()
  • 从一个mailbox中重新获得一个消息：get()或者peek()
  • 尝试无阻塞地从一个mailbox中重新获得一个消息：try_get()或try_peek()
  • 重新获得mailbox中消息的数目：num()
Group

第十三章 进程间的同步与通信

主题
主题
描述
13.3.1 new()
new()方法用来产生mailbox。

mailbox new()方法的原型如下：
13.3.2 num()
一个mailbox中消息的数目可以通过num()方法获得。

num()方法的原型如下：
13.3.3 put()
put()方法将一个消息放入到一个mailbox中。

put()方法的原型如下：
13.3.4 try_put()
try_put()方法尝试将一个消息放置在一个mailbox中。

try_put()方法的原型如下：
13.3.5 get()
get()方法从一个mailbox中重新获得一个消息。

get()方法的原型如下：
13.3.6 try_get()
try_get()方法尝试无阻塞地从一个mailbox中重新获得一个消息。

try_get()方法的原型如下：
13.3.7 peek()
peek()方法从一个mailbox中拷贝一个消息但不会将其从队列中删除。

peek()方法的原型如下：
13.3.8 try_peek()
try_peek()方法尝试从一个mailbox中无阻塞地拷贝一个消息。

try_peek()方法的原型如下：
链接
第十三章 进程间的同步与通信, 主题


13.3.1 new()

链接
13.3 mailbox
SystemVerilog 3.1a语言参考手册
13.3.1 new()
13.3 mailbox

new()方法用来产生mailbox。

mailbox new()方法的原型如下：

Copy Code
function new(int bound = 0);

new()函数返回mailbox句柄，如果不能产生mailbox则返回null。如果bound参数为0，那么mailbox是无边界的（缺省情况），此时一个put()操作应该永远不会阻塞；如果bound为非0，那么它表示mailbox队列的尺寸。

bound必须是正的。负的边界是非法的并会导致不确定的行为，但实现时可以发布一条警告信息。

Group

13.3 mailbox

链接
13.3 mailbox


13.3.2 num()

链接
13.3 mailbox
SystemVerilog 3.1a语言参考手册
13.3.2 num()
13.3 mailbox

一个mailbox中消息的数目可以通过num()方法获得。

num()方法的原型如下：

Copy Code
function int num();

num()方法返回mailbox中当前消息的数目。

在使用返回值的时候需要特别注意，因为它只有等到get()或put()在mailbox上执行后才有效。这些mailbox方法可以来自不同的进程，而不仅仅是执行num()方法的那个进程。因此，返回值的有效性应该依赖于其它方法启动和结束的时间。

Group

13.3 mailbox

链接
13.3 mailbox


13.3.3 put()

链接
13.3 mailbox
SystemVerilog 3.1a语言参考手册
13.3.3 put()
13.3 mailbox

put()方法将一个消息放入到一个mailbox中。

put()方法的原型如下：

Copy Code
task put(singular message);

消息是任意单一表达式，包括对象句柄。

put()方法严格按FIFO的顺序将一个消息存储在mailbox中。如果mailbox使用一个有界的队列产生，那么进程应该被挂起直到队列中有足够的空间。

Group

13.3 mailbox

链接
13.3 mailbox


13.3.4 try_put()

链接
13.3 mailbox
SystemVerilog 3.1a语言参考手册
13.3.4 try_put()
13.3 mailbox

try_put()方法尝试将一个消息放置在一个mailbox中。

try_put()方法的原型如下：

Copy Code
function int try_put(singular message);

消息是任意单一表达式，包括对象句柄。

try_put()方法严格按FIFO的顺序将一个消息存储在mailbox中。这个方法仅仅对有界mailbox才有意义。如果mailbox没有满，那么指定的消息被放置在mailbox当中并且函数返回1。如果mailbox满了，那么函数返回0。

Group

13.3 mailbox

链接
13.3 mailbox


13.3.5 get()

链接
13.3 mailbox
SystemVerilog 3.1a语言参考手册
13.3.5 get()
13.3 mailbox

get()方法从一个mailbox中重新获得一个消息。

get()方法的原型如下：

Copy Code
task get(ref singular message);

消息可以是任意单一表达式，并且它必须是一个有效的左侧表达式。

get()方法从mailbox中重新获得一个消息，也就是说从mailbox队列中删除一个消息。如果mailbox是空的，那么当前的进程阻塞直到一个消息被放置到mailbox中。如果在消息变量和mailbox中的消息间存在类型不匹配，那么会产生一个运行时错误。

非参数化的mailbox是无类型的，也就是说，单个mailbox可以发送和接收不同的数据类型。因此，除了正在被发送的数据（也就是消息队列）外，一个mailbox的实现必须维护通过put()方法放置的消息数据类型。为了使能运行时类型检查，这种机制是必需的。

mailbox等待队列是FIFO。这种方式不能保证进程到达队列的顺序，它仅仅能够保持进程到达的顺序。

Group

13.3 mailbox

链接
13.3 mailbox


13.3.6 try_get()

链接
13.3 mailbox
SystemVerilog 3.1a语言参考手册
13.3.6 try_get()
13.3 mailbox

try_get()方法尝试无阻塞地从一个mailbox中重新获得一个消息。

try_get()方法的原型如下：

Copy Code
function int try_get(ref singular message);

消息可以是任意单一表达式，并且它必须是一个有效的左侧表达式。

try_get()方法试图从mailbox中重新获得一个消息。如果mailbox是空的，那么try_get()方法返回0。如果在消息变量和mailbox中的消息间存在类型不匹配，那么try_get()方法返回-1。如果一个消息是有效的，并且消息类型与消息变量的类型匹配，那么消息被重新获得并且try_get()方法返回1。

Group

13.3 mailbox

链接
13.3 mailbox


13.3.7 peek()

链接
13.3 mailbox
SystemVerilog 3.1a语言参考手册
13.3.7 peek()
13.3 mailbox

peek()方法从一个mailbox中拷贝一个消息但不会将其从队列中删除。

peek()方法的原型如下：

Copy Code
task peek(ref singular message);

消息可以是任意单一表达式，并且它必须是一个有效的左侧表达式。

peek()方法从一个mailbox中拷贝一个消息但不会将其从队列中删除。如果mailbox是空的，那么当前的进程会阻塞直到一个消息被放置到mailbox中。如果在消息变量和mailbox中的消息间存在类型不匹配，那么会产生一个运行时错误。

注意，peek()方法能够引起一个消息为多于一个的进程解除阻塞。只要一个消息保留在mailbox队列中，那么在peek()或get()操作中阻塞的任何进程都应该被解除阻塞。

Group

13.3 mailbox

链接
13.3 mailbox


13.3.8 try_peek()

链接
13.3 mailbox
SystemVerilog 3.1a语言参考手册
13.3.8 try_peek()
13.3 mailbox

try_peek()方法尝试从一个mailbox中无阻塞地拷贝一个消息。

try_peek()方法的原型如下：

Copy Code
function int try_peek(ref singular message);

消息可以是任意单一表达式，并且它必须是一个有效的左侧表达式。

try_peek()方法尝试从一个mailbox中拷贝一个消息但不会将其从队列中删除。如果mailbox是空的，那么try_peek()方法返回0。如果在消息变量和mailbox中的消息间存在类型不匹配，那么try_peek()方法返回-1。如果一个消息是有效的，并且消息类型与消息变量的类型匹配，那么消息被拷贝并且try_peek()方法返回1。

Group

13.3 mailbox

链接
13.3 mailbox


13.4 参数化的mailbox

链接
第十三章 进程间的同步与通信
SystemVerilog 3.1a语言参考手册
13.4 参数化的mailbox
第十三章 进程间的同步与通信

缺省的mailbox是无类型的，也就是说，单个mailbox可以发送和接收任何类型的数据。这是一个非常强大的机制，然而不幸的是，它也会因为一个消息与用来重新获得消息的变量间的类型不匹配而导致运行时错误。一个mailbox经常被用来传输一个特定的消息类型，在这种情况下，如果能够在编译时发现类型不匹配，那会是很有用的。

参数化的mailbox与参数化类（参见11.23节）、模块和接口使用相同的机制。

Copy Code
mailbox #(type = dynamic_type)

其中dynamic_type代表一个特殊的类型，它能够执行运行时的类型检查（缺省情况）。

一个特定类型的参数化的mailbox通过指定类型来声明：

Copy Code
typedef mailbox #(string) s_mbox;
s_mbox sm = new;
string s;
sm.put("hello");
...
sm.get(s);  // s <- "hello"

参数化的mailbox提供了所有与动态mailbox相同的标准方法：num()、new()、get()、peek()、put()、try_get()、try_peek()、try_put()。

一个通用（动态的）mailbox与一个参数化mailbox之间唯一的不同之处是：对于一个参数化的mailbox，编译器能够确保put()、try_put()、peek()、try_peek()、get()和try_get()与mailbox类型兼容，从而所有的类型不匹配都可以被编译器捕获而不是在运行时捕获。

Group

第十三章 进程间的同步与通信

链接
第十三章 进程间的同步与通信


13.5 事件

链接
第十三章 进程间的同步与通信, 主题
SystemVerilog 3.1a语言参考手册
13.5 事件
第十三章 进程间的同步与通信 | 主题

在Verilog中，命名的事件是静态对象，它可以通过->操作符触发，并且通过@操作符进程可以等待一个事件被触发。SystemVerilog事件支持相同的基本操作，但它从几个方面增强了Verilog事件。最为显著的增强是：Verilog命名事件的触发状态没有持续时间，而在SystemVerilog中，这个触发状态在事件被触发的整个时间步值内持续。而且，SystemVerilog事件作为同步队列的句柄使用，因此，它们可以作为参数传递给任务，并且它们可以赋值到另外一个事件或者与另外一个事件进行比较。

现存的Verilog事件操作（@和->）是后向兼容的，当使用在静态Verilog上下文中的时候可以继续以相同的方式工作。下面所描述的其它功能可以在静态上下文或动态上下文中作用于所有的事件。

SystemVerilog事件为一个底层的同步对象提供了一个句柄。当进程等待一个事件被触发的时候，进程被放入到一个在同步对象内部维护的队列当中。进程可以或者通过@操作符，或者通过使用wait()结构检查它们的触发状态来等待一个SystemVerilog事件被触发。事件通过使用->或->>操作符来触发。

Copy Code
event_trigger ::=            // 引用自附录A.6.5
    -> hierarchical_event_identifier;
  | ->> [delay_or_event_control] hierarchical_event_identifier;

语法 13-1 — 事件触发语法（摘录自附录A）

声明命名事件的语法在3.8节中讨论。

Group

第十三章 进程间的同步与通信

主题
主题 | 描述
13.5.1 触发一个事件 | 命名事件可以通过->操作符触发。 触发一个事件可以为当前等待这个事件的所有进程解除阻塞。当被触发以后，命名事件的行为就好像一个热点，也就是说，触发状态本身是不可观测的，我们仅仅能够观测到它的效果。这种方式类似于一个沿能够触发一个触发器，但沿的状态却不能被确定一样，也就是说，if (posedge clock)是非法的。
13.5.2 无阻塞的事件触发 | 无阻塞事件使用->>操作符触发。 ->>操作符的效果是语句会无阻塞地执行，并且在延时控制过期或事件控制发生的时候会产生一个无阻塞的赋值更新事件。这个更新事件的效果应该是在仿真周期的无阻塞赋值区域触发被引用的事件。
13.5.3 等待一个事件 | 等待一个事件被触发的基本机制是通过事件控制操作符，@。
13.5.4 稳固的触发：触发特性 | SystemVerilog能够从在整个时间步值期间持续（也就是直到仿真时间继续）的事件触发状态中辨别事件触发器本身（瞬时的）。触发的事件特性允许用户检查这个状态。 触发的特性使用一个类似于方法的语法来调用：
链接
第十三章 进程间的同步与通信, 主题


13.5.1 触发一个事件

链接
13.5 事件
SystemVerilog 3.1a语言参考手册
13.5.1 触发一个事件
13.5 事件

命名事件可以通过->操作符触发。

触发一个事件可以为当前等待这个事件的所有进程解除阻塞。当被触发以后，命名事件的行为就好像一个热点，也就是说，触发状态本身是不可观测的，我们仅仅能够观测到它的效果。这种方式类似于一个沿能够触发一个触发器，但沿的状态却不能被确定一样，也就是说，if (posedge clock)是非法的。

Group

13.5 事件

链接
13.5 事件


13.5.2 无阻塞的事件触发

链接
13.5 事件
SystemVerilog 3.1a语言参考手册
13.5.2 无阻塞的事件触发
13.5 事件

无阻塞事件使用->>操作符触发。

->>操作符的效果是语句会无阻塞地执行，并且在延时控制过期或事件控制发生的时候会产生一个无阻塞的赋值更新事件。这个更新事件的效果应该是在仿真周期的无阻塞赋值区域触发被引用的事件。

Group

13.5 事件

链接
13.5 事件


13.5.3 等待一个事件

链接
13.5 事件
SystemVerilog 3.1a语言参考手册
13.5.3 等待一个事件
13.5 事件

等待一个事件被触发的基本机制是通过事件控制操作符，@。

Copy Code
@hierarchical_event_identifier;

@操作符阻塞调用进程直到指定的事件被触发。

对于用来为一个等待一个事件的进程解除阻塞的触发器，等待进程在触发进程执行触发操作符->之前必须执行@语句。如果触发器首先执行，那么等待进程会保持在阻塞状态。

Group

13.5 事件

链接
13.5 事件


13.5.4 稳固的触发：触发特性

链接
13.5 事件
SystemVerilog 3.1a语言参考手册
13.5.4 稳固的触发：触发特性
13.5 事件

SystemVerilog能够从在整个时间步值期间持续（也就是直到仿真时间继续）的事件触发状态中辨别事件触发器本身（瞬时的）。触发的事件特性允许用户检查这个状态。

触发的特性使用一个类似于方法的语法来调用：

Copy Code
hierarchical_event_identifier.triggered

如果指定的事件在当前的时间步值中已经被触发那么触发的事件特性计算成真，否则计算成假。如果事件标识符为null，那么触发的事件特性计算成假。

触发的事件特性在一个wait结构的关联文中最为有用：

Copy Code
wait (hierarchical_event_identifier.triggered)

使用这种机制，一个事件触发器应该为等待进程解除阻塞，无论它在触发操作之前执行还是在与触发操作相同的仿真时间上执行。因此，当触发和等待同时发生的时候，触发的事件特性能够消除一个普通的竞争条件。根据等待和触发进程的执行顺序，一个阻塞一个事件的进程既可以也能够不解除阻塞。然而，无论等待和触发操作的顺序如何，一个等待触发状态的进程总是解除阻塞。

例子：

Copy Code
event done, blast;     // 声明两个新的事件
event done_too = done; // 将done_too声明成done的别名

task trigger(event ev);
    -> ev;
endtask

...

fork
    @ done_too;       // 通过done_too等待done
    #1 trigger(done); // 通过任务trigger触发done
join

fork
    -> blast;
    wait (blast.triggered);
join

上面例子中的第一条分支语句显示了两个事件标识符（done和done_too）如何引用相同的同步对象，它还显示了一个事件怎样被传递到一个通用的触发这个事件的任务。在这个例子中，一个进程通过done_too等待事件，而真实的触发通过将done作为一个参数传递的trigger任务完成的。

在第二条分支语句中，一个进程可以在另外一个进程（如果fork...jion中的进程以源顺序执行）有机会执行并等待这个事件之前触发事件。尽管如此，第二个进程会解除阻塞并且fork会中止。这是因为进程等待事件的触发状态，它在时间步值的持续期内保持它的触发状态。

Group

13.5 事件

链接
13.5 事件


13.6 事件排序：wait_order()

链接
第十三章 进程间的同步与通信
SystemVerilog 3.1a语言参考手册
13.6 事件排序：wait_order()
第十三章 进程间的同步与通信

wait_order结构会挂起调用进程直到所有指定的事件以指定的顺序（从左到右）被触发，或者任何为触发的事件被乱序触发，并因此会导致操作失败。

wait_order结构的语法如下：

Copy Code
wait_statement ::=         // 引用自附录A.6.5
    ...
  | wait_order (hierarchical_identifier[, hierarchical_identifier]) action_block

action_block ::=
    statement_or_null
  | [statement] else statement

语法13-2 — wait_order事件排序语法（摘录自附录A）

为了使wait_order成功，在序列的任何点上，后续的事件—在这一点上它必须是未触发的，或者序列已经失败—必须以规定的顺序被触发。以前的事件并没有被限制成只发生一次。也就是说，一旦一个事件以规定的顺序发生，那么它可以被再次触发而不会引起结构失败。

只有列表中的第一个事件能够等待稳固的触发特性。

结构失败是采取的动作依赖于是否指定了可选的else语句（失败语句）。如果指定了失败语句，那么一旦结构失败就会执行指定的语句。如果没有指定失败语句，那么失败会产生一个运行时错误。

例如：

Copy Code
wait_order(a, b, c);

上面的例子会挂起当前的进程直到事件a、b和c以a –> b –> c的顺序触发。如果事件被乱序触发，那么会产生一个运行时错误。

例子：

Copy Code
wait_order(a, b, c) else $display("Error: events out of order");

在这个例子中，失败语句指出：一旦结构失败应该显示一条用户消息，但不会产生一个错误。

例子：

Copy Code
bit success;
wait_order(a, b, c)
    success = 1;
else
    success = 0;

在这个例子中，完成状态被存储在变量success中，并且不会产生一个错误。

Group

第十三章 进程间的同步与通信

链接
第十三章 进程间的同步与通信


13.7 事件变量

链接
第十三章 进程间的同步与通信, 主题
SystemVerilog 3.1a语言参考手册
13.7 事件变量
第十三章 进程间的同步与通信 | 主题

一个事件是一个唯一具有几个重要特性的数据类型。与Verilog不同，SystemVerilog事件可以被赋值到另外一个事件。当一个事件赋值到另外一个事件的时候，源事件的同步队列被源事件和目标事件所共享。从这个意义上讲，事件是一个全功能的变量而不仅仅是标签。

Group

第十三章 进程间的同步与通信

主题
主题
描述
13.7.1 合并事件
当一个事件被赋值到另外一个事件的时候，这两个事件被合并。因此，在其中一个变量上执行->会影响等待任意一个事件变量的进程。

例如：
13.7.2 回收事件
当一个事件变量被赋值为特殊的null值的时候，事件变量和底层同步队列之间的关联被打断。当没有事件变量与一个底层同步队列相关联的时候，队列本身的资源变成能够被重新使用的（资源被释放？<FPGA技术网疑问？>）。

触发一个空事件不会有任何效果。等待一个空事件的结果是未定义的，并且在实现时可以发布一个运行时警告。

例如：
13.7.3 事件比较
事件变量可以与其它事件变量或特殊值null比较。对于事件变量的比较，仅仅允许下列的操作符：

  • 与另外一个事件或与null进行相同操作（==）；
  • 与另外一个事件或与null进行不等操作（!=）；
  • 与另外一个事件或与null进行条件相等操作（===，与==具有相同的语义）；
  • 与另外一个事件或与null进行条件不等操作（!==，与!=具有相同的语义）；
  • 检测一个布尔值，在事件为null的时候它为0，否则为1。

例子：

链接
第十三章 进程间的同步与通信, 主题


13.7.1 合并事件

链接
13.7 事件变量
SystemVerilog 3.1a语言参考手册
13.7.1 合并事件
13.7 事件变量

当一个事件被赋值到另外一个事件的时候，这两个事件被合并。因此，在其中一个变量上执行->会影响等待任意一个事件变量的进程。

例如：

Copy Code
event a, b, c;

a = b;
-> c;
-> a; // 也会触发b
-> b; // 也会触发a

a = c;
b = a;
-> a; // 也会触发b和c
-> b; // 也会触发a和c
-> c; // 也会触发a和b

当事件被合并的时候，赋值仅仅影响后续事件控制或等待操作的执行。如果当另外一个事件被赋值到event1的时候如果一个进程被阻塞以等待event1，那么当前的等待进程永远也不会解除阻塞。例如：

Copy Code
fork
    T1: while(1) @E2;
    T2: while(1) @E1;
    T3: begin
        E2 = E1;
        while(1) -> E2;
    end
join

这个例子为三个并发进程产生分支。每一个进程都从相同的时间开始。因此，在进程T1和T2被阻塞的同时，进程T3将事件E1赋值到E2。这意味着进程T1永远也不会解除阻塞，因为事件E2现在是E1。为了解除T1和T2的阻塞，E1和E1的合并必须发生在分支之前。

Group

13.7 事件变量

链接
13.7 事件变量


13.7.2 回收事件

链接
13.7 事件变量
SystemVerilog 3.1a语言参考手册
13.7.2 回收事件
13.7 事件变量

当一个事件变量被赋值为特殊的null值的时候，事件变量和底层同步队列之间的关联被打断。当没有事件变量与一个底层同步队列相关联的时候，队列本身的资源变成能够被重新使用的（资源被释放？<FPGA技术网疑问？>）。

触发一个空事件不会有任何效果。等待一个空事件的结果是未定义的，并且在实现时可以发布一个运行时警告。

例如：

Copy Code
event E1 = null;
@E1;                  // 未定义的：可能永远阻塞或者根本不阻塞
wait(E1.triggered);   // 未定义的
-> E1;                // 没有效果
Group

13.7 事件变量

链接
13.7 事件变量


13.7.3 事件比较

链接
13.7 事件变量
SystemVerilog 3.1a语言参考手册
13.7.3 事件比较
13.7 事件变量

事件变量可以与其它事件变量或特殊值null比较。对于事件变量的比较，仅仅允许下列的操作符：

  • 与另外一个事件或与null进行相同操作（==）；
  • 与另外一个事件或与null进行不等操作（!=）；
  • 与另外一个事件或与null进行条件相等操作（===，与==具有相同的语义）；
  • 与另外一个事件或与null进行条件不等操作（!==，与!=具有相同的语义）；
  • 检测一个布尔值，在事件为null的时候它为0，否则为1。

例子：

Copy Code
event E1, E2;

if (E1) // 与if (E1 != null)相同
    E1 = E2;

if (E1 == E2)
    $display("E1 and E2 are the same event");
Group

13.7 事件变量

链接
13.7 事件变量


第十四章 调度语义

链接
主题
SystemVerilog 3.1a语言参考手册
第十四章 调度语义
主题
主题
主题
描述
14.1 硬件模型的执行及其验证环境
本参考手册各个章节的目标是描述各个语言元素的行为。本章给出了这些元素间相互作用的概述，特别是有关事件调度和执行的内容。尽管SystemVerilog并不仅仅限制在仿真中使用，然而语言的语义是为事件导向的仿真而定义，并且硬件描述语言的其它使用都是从这个基本的定义抽象而出。
14.2 事件仿真
SystemVerilog语言根据一个分布式事件执行模型定义。本章详细描述了分布式事件仿真以便提供一个语境来描述SystemVerilog结构的含义和有效解释。这些最终的定义为仿真提供了标准的SystemVerilog参考算法，所有遵从这个标准的仿真器都应该实现这些算法。注意，这些定义具有许多选择，并且不同的仿真器之间的某些执行细节也有些差别。另外，除了本章描述的算法外，SystemVerilog仿真器可以自由地使用不同的算法，只要用户可见的效果与这些参考算法保持一致。

一个SystemVerilog描述包含了连接的执行线程或进程。进程是可以计算的对象，它们可以具有状态，并且可以响应输入上的变化以产生输出。进程是并发调度的元素，例如initial块。进程的例子包括但不限于原语、initial、always、always_comb、always_latch以及always_ff过程块、连续赋值、异步任务、以及过程赋值语句。

在被仿真的系统描述中，一个线网或变量的每一个变化都被认为是一个更新事件。

进程敏感于更新事件。当一个更新事件被执行的时候，敏感于这个事件的所有进程都会以任意顺序计算。一个进程的计算也是一个事件，这个事件被称为计算事件。

计算事件还包含PLI回调，这些PLI回调是执行模型中的一些点，其中用户定义的外部例程能够从仿真核中被调用。

除了事件之外，仿真器的另外一个关键方面是时间。术语仿真时间被用来指代由仿真器维护的时间值，它用来建模正在仿真的系统描述所花费的时间。在本章中，术语时间可以与仿真时间互换使用。

为了支持清晰并且可预测的交互作用，单个时隙被划分成多个区域，在这些区域中规定了特定执行类型排序的事件被调度。这就使得当被测设计处于一个稳定状态的时候特性和检查器能够采样数据。特性表达式可以被安全地计算，并且测试平台能够与特性和检查器以零延时相互作用，而这些都是以一个可预测的方式进行。这种机制还允许设计、时钟传输具有非零的延时，和/或激励和响应被自由地混合并与周期精确的描述相一致。
14.3 分层的事件调度器
一个符合规定的SystemVerilog仿真器必须维护某种形式的数据结构，随着仿真时间的继续，这个数据结构允许事件被动态地调度、执行和删除。这个数据结构通常被实现成一组时间排序的链表，它们一个定义明确的方式被划分和细分。

第一个分割根据时间进行。每一个事件都具有唯一的一个执行时间，在仿真期间的人以给定时间点上它可以是当前时间或某个未来的时间。在一个特定时间上的所有被调度的事件定义了一个时隙。通过在移动到下一个非空时隙之前执行和删除当前仿真时隙中的所有事件，仿真能够按时间顺序执行。这个过程保证了仿真器在时间上永远不会回退。

一个时隙被划分成一组有序的区域：

  1. Preponed
  2. Pre-active
  3. Active
  4. Inactive
  5. Pre-NBA
  6. NBA
  7. Post-NBA
  8. Observed
  9. Post-observed
  10. Reactive
  11. Postponed

将一个时隙划分成这些有序区域的目的是提供设计和测试平台代码间的可预测的交互作用。

除了Observed和Reactive区域以及Post-observed PLI区域外，这些区域本质上包含了Verilog 1364-2001标准仿真参考模型，并具有完全相同的确定层次。这就意味着合法的Verilog代码能够在新的机制下无需修改就可以正确地运行。Postponed区域是监视信号和其它类似事件的区域。一旦到达Postponded区域后，在这个时隙中不允许有新的值变化。

在SystemVerilog 3.1标准中，Observed和Reactive区域是新的区域，并且只有来自新的语言结构的事件才能被调度进这些新的区域。

当特性表达式被触发的时候，Observed区域用来计算这些特性表达式。这个确定性的一个标准就是特性计算在任意时钟触发时隙中只能发生一次。在特性计算期间，通过/失败代码应该在当前时隙的Reactive区域被调度。

特性表达式被采样数据的采样时间在时钟控制块中控制。新的#1step采样延时提供了在进入当前时隙之前立即采样数据的能力，并且相对于其它等价结构来说它是一个首选的结构，因为它使得1step的时间延时能够被参数化。这个#1step结构是一个卓有成效的机制，它提供了一个方法来定义采样发生的时间，并且不要求一个事件在前一个时隙中被产生。从概念上讲，这个#1step采样与在当前时隙的Preponed区域发生的数据采样相同。

在程序块、以及来自特性表达式通过/失败代码中说明的代码在Reactive区域被调度。

Pre-active、Pre-NBA和Post-NBA在SystemVerilog 3.1中是新的区域，但它们支持现存的PLI回调。Post-observed区域在SystemVerilog 3.1中是新的区域并且已经为支持PLI而加入。

Pre-active区域专用于一个PLI回调控制点，它使得用户代码能够在Active区域中的事件被计算（参见14.4节）之前读取和写入值以及产生事件。

Pre-NBA区域专用于一个PLI回调控制点，它使得用户代码能够在NBA区域中的事件被计算（参见14.4节）之前读取和写入值以及产生事件。

Post-NBA区域专用于一个PLI回调控制点，它使得用户代码能够在NBA区域中的事件被计算（参见14.4节）后读取和写入值以及产生事件。

Post-observed区域专用于一个PLI回调控制点，它使得用户代码能够在特性被计算（在Observed或较早的区域）后读取值。

事件区域的执行流程在图14-1中描述。

图14-1 — 时隙和事件区域的SystemVerilog流程

Active、Inactive、Pre-NBA、NBA、Post-NBA、Observed、Postobserved和Reactive区域被称为迭代区域。

Preponed区域专用于一个PLI回调控制点上，它使得用户代码在任何线网或变量改变状态之前访问当前时隙上的数据。

Active区域保留当前被计算的事件并且可以以任意顺序处理。

Inactive区域保留将要在所有激活事件被处理后被计算的事件。

一个显式的#0延时要求进程被挂起并且将一个事件调度到当前时隙的Inactive... more

14.4 PLI回调控制点
SystemVerilog中具有两种类型的PLI回调，一种类型的PLI回调当某种特定的行为发生时立即被执行，另外一种PLI回调被显式地注册成一个单次的计算事件。

我们有可能在任何区域显式地调度一个PLI回调事件。因此，一个显式的PLI回调注册能够被一个tuple (time, region)所识别。

下面的列表提供了来自不同的当前PLI回调的映射。

表格14-3：PLI回调

链接
主题


14.1 硬件模型的执行及其验证环境

链接
第十四章 调度语义
SystemVerilog 3.1a语言参考手册
14.1 硬件模型的执行及其验证环境
第十四章 调度语义

本参考手册各个章节的目标是描述各个语言元素的行为。本章给出了这些元素间相互作用的概述，特别是有关事件调度和执行的内容。尽管SystemVerilog并不仅仅限制在仿真中使用，然而语言的语义是为事件导向的仿真而定义，并且硬件描述语言的其它使用都是从这个基本的定义抽象而出。

Group

第十四章 调度语义

链接
第十四章 调度语义


14.2 事件仿真

链接
第十四章 调度语义
SystemVerilog 3.1a语言参考手册
14.2 事件仿真
第十四章 调度语义

SystemVerilog语言根据一个分布式事件执行模型定义。本章详细描述了分布式事件仿真以便提供一个语境来描述SystemVerilog结构的含义和有效解释。这些最终的定义为仿真提供了标准的SystemVerilog参考算法，所有遵从这个标准的仿真器都应该实现这些算法。注意，这些定义具有许多选择，并且不同的仿真器之间的某些执行细节也有些差别。另外，除了本章描述的算法外，SystemVerilog仿真器可以自由地使用不同的算法，只要用户可见的效果与这些参考算法保持一致。

一个SystemVerilog描述包含了连接的执行线程或进程。进程是可以计算的对象，它们可以具有状态，并且可以响应输入上的变化以产生输出。进程是并发调度的元素，例如initial块。进程的例子包括但不限于原语、initial、always、always_comb、always_latch以及always_ff过程块、连续赋值、异步任务、以及过程赋值语句。

在被仿真的系统描述中，一个线网或变量的每一个变化都被认为是一个更新事件。

进程敏感于更新事件。当一个更新事件被执行的时候，敏感于这个事件的所有进程都会以任意顺序计算。一个进程的计算也是一个事件，这个事件被称为计算事件。

计算事件还包含PLI回调，这些PLI回调是执行模型中的一些点，其中用户定义的外部例程能够从仿真核中被调用。

除了事件之外，仿真器的另外一个关键方面是时间。术语仿真时间被用来指代由仿真器维护的时间值，它用来建模正在仿真的系统描述所花费的时间。在本章中，术语时间可以与仿真时间互换使用。

为了支持清晰并且可预测的交互作用，单个时隙被划分成多个区域，在这些区域中规定了特定执行类型排序的事件被调度。这就使得当被测设计处于一个稳定状态的时候特性和检查器能够采样数据。特性表达式可以被安全地计算，并且测试平台能够与特性和检查器以零延时相互作用，而这些都是以一个可预测的方式进行。这种机制还允许设计、时钟传输具有非零的延时，和/或激励和响应被自由地混合并与周期精确的描述相一致。

Group

第十四章 调度语义

链接
第十四章 调度语义


14.3 分层的事件调度器

链接
第十四章 调度语义, 主题
SystemVerilog 3.1a语言参考手册
14.3 分层的事件调度器
第十四章 调度语义 | 主题

一个符合规定的SystemVerilog仿真器必须维护某种形式的数据结构，随着仿真时间的继续，这个数据结构允许事件被动态地调度、执行和删除。这个数据结构通常被实现成一组时间排序的链表，它们一个定义明确的方式被划分和细分。

第一个分割根据时间进行。每一个事件都具有唯一的一个执行时间，在仿真期间的人以给定时间点上它可以是当前时间或某个未来的时间。在一个特定时间上的所有被调度的事件定义了一个时隙。通过在移动到下一个非空时隙之前执行和删除当前仿真时隙中的所有事件，仿真能够按时间顺序执行。这个过程保证了仿真器在时间上永远不会回退。

一个时隙被划分成一组有序的区域：

  1. Preponed
  2. Pre-active
  3. Active
  4. Inactive
  5. Pre-NBA
  6. NBA
  7. Post-NBA
  8. Observed
  9. Post-observed
  10. Reactive
  11. Postponed

将一个时隙划分成这些有序区域的目的是提供设计和测试平台代码间的可预测的交互作用。

除了Observed和Reactive区域以及Post-observed PLI区域外，这些区域本质上包含了Verilog 1364-2001标准仿真参考模型，并具有完全相同的确定层次。这就意味着合法的Verilog代码能够在新的机制下无需修改就可以正确地运行。Postponed区域是监视信号和其它类似事件的区域。一旦到达Postponded区域后，在这个时隙中不允许有新的值变化。

在SystemVerilog 3.1标准中，Observed和Reactive区域是新的区域，并且只有来自新的语言结构的事件才能被调度进这些新的区域。

当特性表达式被触发的时候，Observed区域用来计算这些特性表达式。这个确定性的一个标准就是特性计算在任意时钟触发时隙中只能发生一次。在特性计算期间，通过/失败代码应该在当前时隙的Reactive区域被调度。

特性表达式被采样数据的采样时间在时钟控制块中控制。新的#1step采样延时提供了在进入当前时隙之前立即采样数据的能力，并且相对于其它等价结构来说它是一个首选的结构，因为它使得1step的时间延时能够被参数化。这个#1step结构是一个卓有成效的机制，它提供了一个方法来定义采样发生的时间，并且不要求一个事件在前一个时隙中被产生。从概念上讲，这个#1step采样与在当前时隙的Preponed区域发生的数据采样相同。

在程序块、以及来自特性表达式通过/失败代码中说明的代码在Reactive区域被调度。

Pre-active、Pre-NBA和Post-NBA在SystemVerilog 3.1中是新的区域，但它们支持现存的PLI回调。Post-observed区域在SystemVerilog 3.1中是新的区域并且已经为支持PLI而加入。

Pre-active区域专用于一个PLI回调控制点，它使得用户代码能够在Active区域中的事件被计算（参见14.4节）之前读取和写入值以及产生事件。

Pre-NBA区域专用于一个PLI回调控制点，它使得用户代码能够在NBA区域中的事件被计算（参见14.4节）之前读取和写入值以及产生事件。

Post-NBA区域专用于一个PLI回调控制点，它使得用户代码能够在NBA区域中的事件被计算（参见14.4节）后读取和写入值以及产生事件。

Post-observed区域专用于一个PLI回调控制点，它使得用户代码能够在特性被计算（在Observed或较早的区域）后读取值。

事件区域的执行流程在图14-1中描述。

图14-1 — 时隙和事件区域的SystemVerilog流程

Active、Inactive、Pre-NBA、NBA、Post-NBA、Observed、Postobserved和Reactive区域被称为迭代区域。

Preponed区域专用于一个PLI回调控制点上，它使得用户代码在任何线网或变量改变状态之前访问当前时隙上的数据。

Active区域保留当前被计算的事件并且可以以任意顺序处理。

Inactive区域保留将要在所有激活事件被处理后被计算的事件。

一个显式的#0延时要求进程被挂起并且将一个事件调度到当前时隙的Inactive区域，这样这个进程能够在下一个inactive到active的迭代中继续。

一个无阻塞赋值在NBA区域中产生一个事件，这个事件在当前或一个较迟的仿真时间中被调度。

Postponed区域专用于一个PLI回调控制点，它使得用户代码被挂起直到所有的Active、Inactive和NBA区域完成。在这个区域中，向任何线网或变量写入值，或者在当前时隙中任何以前的区域中调度一个事件都是非法的。

Group

第十四章 调度语义

主题
主题 | 描述
14.3.1 SystemVerilog仿真参考算法 |
链接
第十四章 调度语义, 主题


14.3.1 SystemVerilog仿真参考算法

链接
14.3 分层的事件调度器
SystemVerilog 3.1a语言参考手册
14.3.1 SystemVerilog仿真参考算法
14.3 分层的事件调度器
Copy Code
execute_simulation {
    T = 0;
    initialize the values of all nets and variables;
    schedule all initialization events into time 0 slot;
    while (some time slot is non-empty) {
        move to the next future non-empty time slot and set T;
        execute_time_slot (T);
    }
}

execute_time_slot {
    execute_region (preponed);
    while (some iterative region is non-empty) {
        execute_region (active);
        scan iterative regions in order {
            if (region is non-empty) {
                move events in region to the active region;
                break from scan loop;
            }
        }
    }
    execute_region (postponed);
}

execute_region {
    while (region is non-empty) {
        E = any event from region;
        remove E from the region;
        if (E is an update event) {
            update the modified object;
            evaluate processes sensitive to the object and possibly schedule
            further events for execution;
        } else { /* E is an evaluation event */
            evaluate the process associated with the event and possibly
            schedule further events for execution;
        }
    }
}

迭代区域以及它们的顺序为：Active、Inactive、Pre-NBA、NBA、Post-NBA、Observed、Postobserved和Reactive。

Group

14.3 分层的事件调度器

链接
14.3 分层的事件调度器


14.4 PLI回调控制点

链接
第十四章 调度语义
SystemVerilog 3.1a语言参考手册
14.4 PLI回调控制点
第十四章 调度语义

SystemVerilog中具有两种类型的PLI回调，一种类型的PLI回调当某种特定的行为发生时立即被执行，另外一种PLI回调被显式地注册成一个单次的计算事件。

我们有可能在任何区域显式地调度一个PLI回调事件。因此，一个显式的PLI回调注册能够被一个tuple (time, region)所识别。

下面的列表提供了来自不同的当前PLI回调的映射。

表格14-3：PLI回调

回调 | 识别
tf_synchronize | (time, Pre-NBA)
tf_isynchronize | (time, Pre-NBA)
tf_rosynchronize | (time, Postponed)
tf_irosynchronize | (time, Postponed)
cbReadWriteSynch | (time, Post-NBA)
cbAtStartOfSimTime | (time, Pre-active)
cbReadOnlySynch | (time, Postponed)
cbNBASynch | (time, Pre-NBA)
cbAtEndOfSimTime | (time, Postponed)
cbNextSimTime | (time, Pre-active)
cbAfterDelay | (time, Pre-active)
Group

第十四章 调度语义

链接
第十四章 调度语义


第十五章 时钟控制块

链接
主题
SystemVerilog 3.1a语言参考手册
第十五章 时钟控制块
主题
主题
主题
描述
15.1 简介（一般信息）
在Verilog中，块与块之间的通信通过模块端口来指定。SystemVerilog加入了接口（interface）这一概念，接口是一个关键的结构，它能够封装块与块之间的通信，因此，用户能够方便地改变模块间通信的建模抽象层次。

一个接口指定了一个测试平台用来与被测设计进行通信的信号或线网。然而，一个接口并没有任何显式的时序规程、同步要求、或时钟控制范例。

SystemVerilog加入了时钟控制块，它能够识别时钟信号，并能够捕获被建模块的时序和同步要求。一个时钟控制块集合了同步于一个特定时钟的信号，并且使得它们的时序成为显式的。在一个基于周期的方法中，时钟控制块是一个关键的元素，它使得用户能够在一个更高的抽象层次上编写测试平台。除了关注于信号以及时间上的转变外，测试还可以根据周期和事务定义。根据环境的不同，一个测试平台可以包含一个或多个时钟控制块，每一个都可以包含它自己的时钟加上任意数目的信号。

时钟控制块将时序和同步细节与一个测试平台中的结构、功能和过程元素分割开来。因此，采样和驱动时钟控制块信号的时序成为隐式的并且相对于时钟控制块的时钟。这使得我们能够以一个非常简洁的方式编写一组关键的操作，而无需显式地使用时钟或指定时序。这些操作是：

  • 同步的事件
  • 输入采样
  • 同步的驱动

15.2 时钟控制块声明
时钟控制块的声明语法如下：
15.3 输入时滞与输出时滞
输入或双向信号在指定的时钟事件上采样。如果指定了一个输入时滞，那么信号在时钟事件之前的时滞时间单位上采样。类似地，输出或双向信号在相应的时钟事件之后的时滞仿真时间单位上被驱动。图15-1为一个上升沿时钟显示了基本的采样/驱动时序。

图15-1 — 包含相对于时钟上升沿的时滞的采样和驱动时间

一个时滞必须是一个常量表达式，并且可以被说明成一个参数。如果没有指定时滞的时间单位，那么会使用当前的时间单位。如果使用了一个数字的话，那么时滞会使用当前作用范围的时间比例来解释。

15.4 层次化的表达式
一个时钟控制块中的任何信号都可以与一个任意的层次化表达式相关联。正像15.2节所描述的那样，层次化的表达式通过在层次化表达式前面附加一个等号（=）来引入：
15.5 多时钟控制块中的信号
相同的信号（时钟、输入、输入输出、或输出）可以在一个时钟控制块中出现多次。使用相同时钟（或时钟表达式）的时钟控制块应该共享相同的同步事件，这种方式就像几个锁存器可以被一个相同的时钟控制一样。输入语义在15.12节中描述，输出语义在15.14节中描述。
15.6 时钟控制块的作用范围和生命周期
一个时钟控制块既是一个声明也是这个声明的一个实例。单独的实例化步骤不是必要的。相反，会为包含声明的块的每一个实例产生一个拷贝（就像一个always块一样）。一旦声明了一个时钟控制块，定时信号就可以通过时钟控制块的名字和一个点（.）操作符来引用：
15.7 多时钟控制块的例子
在这个例子中，一个简单的测试程序包含了两个时钟控制块。在本例中使用的程序结构将在第十六章中讨论。
15.8 接口与时钟控制块
一个时钟控制块封装了一组共享一个基本时钟的信号，因此使用一个SystemVerilog接口说明一个时钟控制块能够显著地减少连接测试平台所需代码的数目。此外，由于测试平台内时钟控制块中信号方向是有关测试平台而不是被测设计的，一个modport声明可以恰当地描述这两个方向。一个测试平台程序可以包含在一个程序当中，并且它的端口可以是接口，这个接口对应于每个时钟控制块中声明的信号。从测试平台这一侧（也就是modport test）看接口中的连线应该与时钟控制块中声明的方向相同，而从被测设计来看则具有相反的方向（也就是modport dut）。

例如，前面的例子可以使用接口按如下的方式重新编写：
15.9 时钟控制块事件
一个时钟控制块的时钟控制事件可以直接使用时钟控制块的名字来引用，而不用理会用来声明时钟控制块的真实时钟控制事件。

例如：
15.10 周期延时：##
##操作符可以被用来将执行延时一个指定数目的时钟控制事件，或者时钟周期。

周期延时语句的语法如下：
15.11 缺省时钟控制
一个时钟控制可以被说明成缺省的，这样它可以作用于一个指定模块、接口、或程序内的所有周期延时操作。

缺省周期说明语句的语法如下：
15.12 输入采样
所有的时钟控制块输入（input或inout）都在对应的时钟控制事件上采样。如果输入时滞不是一个显式的#0，那么采样的值对应于先于时钟控制事件的时间布值时滞时间单位的Postponed区域中的信号值（参见15.3节中的图15-1）。如果输入时滞是一个显式的#0，那么采样的值对应于Observed区域的采样值。

采样会立即发生（调用进程不会阻塞）。当一个信号出现在一个表达式中的时候，它会被信号的采样值替代，也就是在最后一个采样点上采样的值。

当同一个信号是多个始终控制块输入的时候，它的语义是很直接的；每一个时钟控制块使用自己的时钟控制事件采样对应的信号。
15.13 同步的事件
显式的同步通过事件控制操作符@来实现，它允许一个进程来等待一个特定的信号值变化或者一个时钟控制事件（参见15.9节）。

同步操作符的语法在第8.10节给出。

与事件控制一起使用的表达式可以指示时钟控制块的输入（input或inout）或者一个分片。分片可以包含动态索引，它会在@表达式执行的时候进行一次计算。

下面是一些同步语句的例子：

  • 等待时钟控制块ram_bus中ack_1信号的下一次变化

15.14 同步的驱动
时钟控制块的输出（output或inout）被用来在一个指定的时间上将值驱动到它们对应的信号。换句话说，对应的信号在指定的时钟控制事件上通过输出时滞来修改它的值。

说明一个同步驱动的语法类似于一个赋值：
链接
主题


15.1 简介（一般信息）

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.1 简介（一般信息）
第十五章 时钟控制块

在Verilog中，块与块之间的通信通过模块端口来指定。SystemVerilog加入了接口（interface）这一概念，接口是一个关键的结构，它能够封装块与块之间的通信，因此，用户能够方便地改变模块间通信的建模抽象层次。

一个接口指定了一个测试平台用来与被测设计进行通信的信号或线网。然而，一个接口并没有任何显式的时序规程、同步要求、或时钟控制范例。

SystemVerilog加入了时钟控制块，它能够识别时钟信号，并能够捕获被建模块的时序和同步要求。一个时钟控制块集合了同步于一个特定时钟的信号，并且使得它们的时序成为显式的。在一个基于周期的方法中，时钟控制块是一个关键的元素，它使得用户能够在一个更高的抽象层次上编写测试平台。除了关注于信号以及时间上的转变外，测试还可以根据周期和事务定义。根据环境的不同，一个测试平台可以包含一个或多个时钟控制块，每一个都可以包含它自己的时钟加上任意数目的信号。

时钟控制块将时序和同步细节与一个测试平台中的结构、功能和过程元素分割开来。因此，采样和驱动时钟控制块信号的时序成为隐式的并且相对于时钟控制块的时钟。这使得我们能够以一个非常简洁的方式编写一组关键的操作，而无需显式地使用时钟或指定时序。这些操作是：

  • 同步的事件
  • 输入采样
  • 同步的驱动
Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.2 时钟控制块声明

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.2 时钟控制块声明
第十五章 时钟控制块

时钟控制块的声明语法如下：

Copy Code
clocking_declaration ::=              // 引用自附录A.6.11
    [default] clocking [clocking_identifier] clocking_event;
        {clocking_item}
    endclocking [: clocking_identifier]

clocking_event ::=
    @ identifier
  | @ (event_expression)

clocking_item :=
    default default_skew;
  | clocking_direction list_of_clocking_decl_assign;
  | {attribute_instance} concurrent_assertion_item_declaration

default_skew ::=
    input clocking_skew
  | output clocking_skew
  | input clocking_skew output clocking_skew

clocking_direction ::=
    input [clocking_skew]
  | output [clocking_skew]
  | input [clocking_skew] output [clocking_skew]
  | inout

list_of_clocking_decl_assign ::= clocking_decl_assign {, clocking_decl_assign}

clocking_decl_assign ::= signal_identifier [= hierarchical_identifier]

clocking_skew ::=
    edge_identifier [delay_control]
  | delay_control

edge_identifier ::= posedge | negedge                // 引用自附录A.7.4

delay_control ::=                                    // 引用自附录A.6.5
    # delay_value
  | # (mintypmax_expression)

语法 15-1—时钟控制块语法（摘录自附录A）

delay_control必须是一个时间文本或者一个可以计算成一个正的整数值的常量表达式。

clocking_identifier了指定所声明的时钟控制块的名字。

signal_identfier标识一个位于包围时钟控制块声明的作用范围内的信号，并且声明了时钟控制块中一个信号的名字。除非使用了一个hierarchical_expression，无论是这个信号还是clocking_item的名字都应该是相同的。

clocking_event指定了一个特定的、作用于时钟控制块时钟的事件。典型情况下，这个表达式是一个时钟信号的上升沿或下降沿。在一个指定的时钟控制块中说明的所有其它信号的时序都由这个时钟事件控制。时钟控制块中所有的输入或双向信号都在对应的时钟事件发生的时候被采样。同样，时钟控制块中所有输出或双向信号都在对应的时钟事件发生的时候被驱动。双向信号（inout）即被驱动也被采样。

clocking_skew确定一个信号离开时钟事件多少个时间单位被采样或驱动。输入时滞隐含是负的，也就是说，它们总是指向时钟之前的一个时间，而输出时滞则总是指向时钟之后的一个时间（参见15.3节）。当时钟时间指定了一个简单的沿而不是一个数值的时候，时滞可以被说明成信号的特定的沿。通过使用一个缺省的时钟控制条目，我们可以为整个块指定单个时滞。

Copy Code
clocking ck1 @(posedge clk);
    default input #1step output negedge; // 合法的
    // 输出在clk的下降沿被驱动
    input ...;
    output ...;
endclocking

clocking ck2 @(clk); // 没有指定沿
    default input #1step output negedge; // 合法的
    input ...;
    output ...;
endclocking

hierarchical_identifier说明与时钟控制块关联的信号由它的层次化名字指定（跨模块引用），而不是一个本地端口。

例子：

Copy Code
clocking bus @(posedge clock1);
    default input #10ns output #2ns;
    input data, ready, enable = top.mem1.enable;
    output negedge ack;
    input #1step addr;
endclocking

在上面的例子中，第一行代码声明了一个称为bus的时钟控制块，它以信号clock1的上升沿进行时钟控制。第二行代码通过default指出：时钟控制块中的所有信号都应该使用一个10ns的输入时滞和一个2ns的输出时滞。下一行代码为时钟控制块加入了三个输入信号：data、ready和enable；最后一个信号指向层次化的信号top.mem1.enable。第四行代码为时钟控制块加入了一个ack信号并过载了缺省的输出时滞从而使ack信号在时钟的下降沿被驱动。最后一行代码加入了addr信号并过载了缺省的输入时滞从而使addr在时钟上升沿之前的一个步值时被采样。

除非另有说明，缺省的输入时滞是1step，缺省的输出时滞是0。一个步值是一个特殊的时间单位，它的值在18.10节中定义。一个1step的输入时滞使得输入信号在时钟信号之前的时间步值中采样它们的稳定值（也就是在前一个Postponed区域）。与其它代表物理单位的时间单位不同，一个step不能被用来设置或修改时间精度或时间单位。

Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.3 输入时滞与输出时滞

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.3 输入时滞与输出时滞
第十五章 时钟控制块

输入或双向信号在指定的时钟事件上采样。如果指定了一个输入时滞，那么信号在时钟事件之前的时滞时间单位上采样。类似地，输出或双向信号在相应的时钟事件之后的时滞仿真时间单位上被驱动。图15-1为一个上升沿时钟显示了基本的采样/驱动时序。

图15-1 — 包含相对于时钟上升沿的时滞的采样和驱动时间

一个时滞必须是一个常量表达式，并且可以被说明成一个参数。如果没有指定时滞的时间单位，那么会使用当前的时间单位。如果使用了一个数字的话，那么时滞会使用当前作用范围的时间比例来解释。

Copy Code
clocking dram @(clk);
    input #1ps address;
    input #5 output #6 data;
endclocking

一个1step的输入时滞指示信号将在前一个时间步值的结束处采样。也就是说，采样的值总是对应时钟沿之前的最后一个信号值。

具有显式的#0时滞的输入在对应时钟事件的同一时间采样，但为了避免竞争，它们在Observed区域被采样。同样，没有时滞（显式的#0时滞）的时钟控制块输出在对应时钟事件的同一时间被驱动，就像无阻塞赋值一样（在NBA区域）。

时滞是说明性的结构，因此它们与语法上类似的过程化延时语句在语义上非常不同。特别地，一个显式的#0时滞不会挂起任何进程，也不会在Inactive区域执行或采样值。

Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.4 层次化的表达式

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.4 层次化的表达式
第十五章 时钟控制块

一个时钟控制块中的任何信号都可以与一个任意的层次化表达式相关联。正像15.2节所描述的那样，层次化的表达式通过在层次化表达式前面附加一个等号（=）来引入：

Copy Code
clocking cd1 @(posedge phi1);
    input #1step state = top.cpu.state;
endclocking

然而，层次化的表达式并没有被限制成其它范围内的简单名字或信号。它们可以被用来声明在其它范围或在当前范围内的信号的分片和串联（或组合）。

Copy Code
clocking mem @(clock);
    input instruction = {opcode, regA, regB[3:1]};
endclocking
Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.5 多时钟控制块中的信号

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.5 多时钟控制块中的信号
第十五章 时钟控制块

相同的信号（时钟、输入、输入输出、或输出）可以在一个时钟控制块中出现多次。使用相同时钟（或时钟表达式）的时钟控制块应该共享相同的同步事件，这种方式就像几个锁存器可以被一个相同的时钟控制一样。输入语义在15.12节中描述，输出语义在15.14节中描述。

Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.6 时钟控制块的作用范围和生命周期

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.6 时钟控制块的作用范围和生命周期
第十五章 时钟控制块

一个时钟控制块既是一个声明也是这个声明的一个实例。单独的实例化步骤不是必要的。相反，会为包含声明的块的每一个实例产生一个拷贝（就像一个always块一样）。一旦声明了一个时钟控制块，定时信号就可以通过时钟控制块的名字和一个点（.）操作符来引用：

Copy Code
dom.sig   // 时钟控制dom中的sig信号

时钟控制块不能被嵌套。它们不能再函数、任务、包的内部或一个编译单元中所有声明的外部声明。时钟控制块只能在一个模块、接口或程序（参见第16章）中声明。

时钟控制块具有静态的生命周期以及相对于模块、接口或程序是本地的作用范围。

Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.7 多时钟控制块的例子

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.7 多时钟控制块的例子
第十五章 时钟控制块

在这个例子中，一个简单的测试程序包含了两个时钟控制块。在本例中使用的程序结构将在第十六章中讨论。

Copy Code
program test( input phi1, input [15:0] data, output logic write,
              input phi2, inout [8:1] cmd, input enable
            );

reg [8:1] cmd_reg;

clocking cd1 @(posedge phi1);
    input data;
    output write;
    input state = top.cpu.state;
endclocking

clocking cd2 @(posedge phi2);
    input #2 output #4ps cmd;
    input enable;
endclocking

initial begin
    // 程序从这里开始
    ...
    // 用户可以访问access cd1.data , cd2.cmd , etc…
end

assign cmd = enable ? cmd_reg: 'x;

endprogram

这个测试程序可以被实例化并连接到一个被测设计（cpu和mem）。

Copy Code
module top;
    logic phi1, phi2;
    wire [8:1] cmd;   // 不能是logic（两个双向的驱动器）
    logic [15:0] data;
    test main(phi1, data, write, phi2, cmd, enable);
    cpu cpu1(phi1, data, write);
    mem mem1(phi2, cmd, enable);
endmodule
Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.8 接口与时钟控制块

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.8 接口与时钟控制块
第十五章 时钟控制块

一个时钟控制块封装了一组共享一个基本时钟的信号，因此使用一个SystemVerilog接口说明一个时钟控制块能够显著地减少连接测试平台所需代码的数目。此外，由于测试平台内时钟控制块中信号方向是有关测试平台而不是被测设计的，一个modport声明可以恰当地描述这两个方向。一个测试平台程序可以包含在一个程序当中，并且它的端口可以是接口，这个接口对应于每个时钟控制块中声明的信号。从测试平台这一侧（也就是modport test）看接口中的连线应该与时钟控制块中声明的方向相同，而从被测设计来看则具有相反的方向（也就是modport dut）。

例如，前面的例子可以使用接口按如下的方式重新编写：

Copy Code
interface bus_A (input clk);
    logic [15:0] data;
    logic write;
    modport test (input data, output write);
    modport dut (output data, input write);
endinterface

interface bus_B (input clk);
    logic [8:1] cmd;
    logic enable;
    modport test (input enable);
    modport dut (output enable);
endinterface

program test(bus_A.test a, bus_B.test b);
    clocking cd1 @(posedge a.clk);
        input a.data;
        output a.write;
        inout state = top.cpu.state;
    endclocking

    clocking cd2 @(posedge b.clk);
        input #2 output #4ps b.cmd;
        input b.enable;
    endclocking

    initial begin
        // 程序从这里开始
        ...
        // 用户可以访问cd1.a.data，cd2.b.cmd等等
    end
endprogram

test模块可以被实例化并按如下方式连接：

Copy Code
module top;
    logic phi1, phi2;
    bus_A a(phi1);
    bus_B b(phi2);
    test main(a, b);
    cpu cpu1(a);
    mem mem1(b);
endmodule

作为选择，在上面的test程序中，时钟控制块可以使用接口和层次化表达式按如下方式编写：

Copy Code
clocking cd1 @(posedge a.clk);
    input data = a.data;
    output write = a.write;
    inout state = top.cpu.state;
endclocking

clocking cd2 @(posedge b.clk);
    input #2 output #4ps cmd = b.cmd;
    input enable = b.enable;
endclocking

这就使得我们能够使用较短的名字（cd1.data, cd2.cmd, …）来替代较长的接口语法（cd1.a.data, cd2.b.cmd,…）。

Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.9 时钟控制块事件

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.9 时钟控制块事件
第十五章 时钟控制块

一个时钟控制块的时钟控制事件可以直接使用时钟控制块的名字来引用，而不用理会用来声明时钟控制块的真实时钟控制事件。

例如：

Copy Code
clocking dram @(posedge phi1);
    inout data;
    output negedge #1 address;
endclocking

时钟控制块dram的时钟控制事件可以用来等待那个特定的事件：

Copy Code
@(dram);

上述语句等价于@(posedge phi1)。

Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.10 周期延时：##

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.10 周期延时：##
第十五章 时钟控制块

##操作符可以被用来将执行延时一个指定数目的时钟控制事件，或者时钟周期。

周期延时语句的语法如下：

Copy Code
procedural_timing_control_statement ::=         // 引用自附录A.6.5
    procedural_timing_control statement_or_null

procedural_timing_control ::=
    ...
  | cycle_delay

cycle_delay ::=              // 引用自附录A.6.11
    ## integral_number
  | ## identifier
  | ## (expression)

语法15-2 — 周期延时语法（摘录自附录A）

expression可以是任何能够计算成一个正的整数值的SystemVerilog表达式。

由什么组成一个周期是通过有效的缺省时钟控制确定的（参见15.11节）。如果当前的模块、接口或程序没有指定缺省的时钟控制的话，编译器应该发布一条错误。

例子：

Copy Code
## 5;       // 使用缺省时钟控制等待5个周期（时钟控制事件）
## (j+1);   // 使用缺省时钟控制等待j+1个周期（时钟控制事件）
Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.11 缺省时钟控制

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.11 缺省时钟控制
第十五章 时钟控制块

一个时钟控制可以被说明成缺省的，这样它可以作用于一个指定模块、接口、或程序内的所有周期延时操作。

缺省周期说明语句的语法如下：

Copy Code
module_or_generate_item_declaration ::=       // 引用自附录A.1.5
    ...
  | default clocking clocking_identifier;

clocking_declaration ::=         // 引用自附录A.6.11
    [default] clocking [clocking_identifier] clocking_event;
        {clocking_item}
    endclocking [: clocking_identifier]

语法 15-3 — 缺省时钟控制语法（摘录自附录A）

clocking_identifier必须是时钟控制块的名字。

在一个程序、模块或接口中只能指定一个缺省时钟控制。在相同的程序或模块中多次指定一个缺省时钟控制应该导致一个编译器错误。

一个缺省时钟控制仅在包含缺省时钟控制说明的范围内有效。这个范围包括包含了声明的模块、接口或程序以及任何嵌套的模块或接口。它不包括被实例化的模块或接口。

例子1：将一个时钟控制声明成缺省的。

Copy Code
program test(input bit clk, input reg [15:0] data);
    default clocking bus @(posedge clk);
        inout data;
    endclocking

    initial begin
        ## 5;
        if (bus.data == 10)
            ## 1;
        else
            ...
    end
endprogram

例子2：将一个现存的时钟控制指定成缺省的。

Copy Code
module processor ...
    clocking busA @(posedge clk1);
        ...
    endclocking

    clocking busB @(negedge clk2);
        ...
    endclocking

    module cpu (interface y);
        default clocking busA;

        initial begin
            ## 5; // 使用busA => (posedge clk1)
            ...
        end
    endmodule
endmodule
Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.12 输入采样

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.12 输入采样
第十五章 时钟控制块

所有的时钟控制块输入（input或inout）都在对应的时钟控制事件上采样。如果输入时滞不是一个显式的#0，那么采样的值对应于先于时钟控制事件的时间布值时滞时间单位的Postponed区域中的信号值（参见15.3节中的图15-1）。如果输入时滞是一个显式的#0，那么采样的值对应于Observed区域的采样值。

采样会立即发生（调用进程不会阻塞）。当一个信号出现在一个表达式中的时候，它会被信号的采样值替代，也就是在最后一个采样点上采样的值。

当同一个信号是多个始终控制块输入的时候，它的语义是很直接的；每一个时钟控制块使用自己的时钟控制事件采样对应的信号。

Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.13 同步的事件

链接
第十五章 时钟控制块
SystemVerilog 3.1a语言参考手册
15.13 同步的事件
第十五章 时钟控制块

显式的同步通过事件控制操作符@来实现，它允许一个进程来等待一个特定的信号值变化或者一个时钟控制事件（参见15.9节）。

同步操作符的语法在第8.10节给出。

与事件控制一起使用的表达式可以指示时钟控制块的输入（input或inout）或者一个分片。分片可以包含动态索引，它会在@表达式执行的时候进行一次计算。

下面是一些同步语句的例子：

  • 等待时钟控制块ram_bus中ack_1信号的下一次变化
Copy Code
@(ram_bus.ack_l);
  • 等待时钟控制块ram_bus中的下一个时钟控制事件
Copy Code
@(ram_bus);
  • 等待ram_bus.enable信号的上升沿
Copy Code
@(posedge ram_bus.enable);
  • 等待指定的一位分片dom.sign[a]的下降沿。注意，索引a在运行时计算。
Copy Code
@(negedge dom.sign[a]);
  • 等待dom.sig1的下一个上升沿或dom.sig2的下一次变化，无论哪一个最先发生。
Copy Code
@(posedge dom.sig1 or dom.sig2);
  • 等待dom.sig1的下降沿或dom.sig2的上升沿，无论哪一个最先发生。
Copy Code
@(negedge dom.sig1 or posedge dom.sig2);

同步事件控制所使用的值是同步的值，也就是在对应的时钟控制事件上采样的值。

Group

第十五章 时钟控制块

链接
第十五章 时钟控制块


15.14 同步的驱动

链接
第十五章 时钟控制块, 主题
SystemVerilog 3.1a语言参考手册
15.14 同步的驱动
第十五章 时钟控制块 | 主题

时钟控制块的输出（output或inout）被用来在一个指定的时间上将值驱动到它们对应的信号。换句话说，对应的信号在指定的时钟控制事件上通过输出时滞来修改它的值。

说明一个同步驱动的语法类似于一个赋值：

Copy Code
statement ::= [block_identifier :] {attribute_instance} statement_item
                                                              // 引用自附录A.6.4

statement_item ::=
    ...
    | clocking_drive;

clocking_drive ::=                 // 引用自附录A.6.11
    clockvar_expression <= [cycle_delay] expression
  | cycle_delay clockvar_expression <= expression

cycle_delay ::= ## expression

clockvar ::= hierarchical_identifier

clockvar_expression ::= clockvar select

语法15-4 — 同步的驱动语法（摘录自附录A）

clockvar_expression或者是一个位选择、分片、或者是对应的信号被驱动的整个时钟控制块的输出（不允许使用串联）：

Copy Code
dom.sig       // 整个clockvar
dom.sig[2]    // 位选择
dom.sig[8:2]  // 分片

clocking_drive生成式中的表达式可以是与对应信号类型赋值兼容的任何有效的表达式。

event_count在cycle_delay生成式中的##之后引用expression，并且是一个integral表达式，它可选地说明了在语句执行之前必须经过的时钟控制事件的数目（也就是周期）。指定一个非零的event_count会阻塞当前的进程直到经过指定数目的时钟控制事件，否则语句在当前的时间执行。event_count使用类似于周期延时操作符（参见15.10节）的语法，然而，同步的驱动使用正在被驱动的信号的时钟控制块，并且不是缺省的时钟控制。

第二种形式的同步驱动使用内部赋值语法。一个内部赋值event_count说明也会延迟赋值的执行。在这种情况下，进程不会阻塞并且在语句执行的时候计算右侧表达式。

例子：

Copy Code
bus.data[3:0] <= 4'h5; // 在当前周期的NBA区域驱动data
##1 bus.data <= 8'hz;  // 等待一个bus周期然后驱动data
##2; bus.data <= 2;    // 等待两个缺省时钟控制周期然后驱动data
bus.data <= ##2 r;     // 记下r的值然后再两个bus周期之后驱动data

不管驱动语句何时执行（由于event_count延时），被驱动的值仅在输出时滞指定的时间上被赋值到对应的信号。

Group

第十五章 时钟控制块

主题
主题 | 描述
15.14.1 驱动和无阻塞赋值 | 同步信号驱动按照无阻塞赋值处理。 inout时钟控制块变量和同步驱动的一个关键特性是一个驱动不会改变时钟控制块输入。这是因为读取输入总是产生最后一个被采样的值，而不是被驱动的值。
15.14.2 驱动值解析 | 当多于一个同步驱动在相同的仿真时间被应用到相同的时钟控制块输出（或inout）的时候，SystemVerilog会检查被驱动值的冲突。当检测到冲突驱动的时候会发布一个运行时错误，并且每一个发生冲突的位都被驱动成X（对一个两态端口会被驱动成0）。 例如：
链接
第十五章 时钟控制块, 主题


15.14.1 驱动和无阻塞赋值

链接
15.14 同步的驱动
SystemVerilog 3.1a语言参考手册
15.14.1 驱动和无阻塞赋值
15.14 同步的驱动

同步信号驱动按照无阻塞赋值处理。

inout时钟控制块变量和同步驱动的一个关键特性是一个驱动不会改变时钟控制块输入。这是因为读取输入总是产生最后一个被采样的值，而不是被驱动的值。

Group

15.14 同步的驱动

链接
15.14 同步的驱动


15.14.2 驱动值解析

链接
15.14 同步的驱动
SystemVerilog 3.1a语言参考手册
15.14.2 驱动值解析
15.14 同步的驱动

当多于一个同步驱动在相同的仿真时间被应用到相同的时钟控制块输出（或inout）的时候，SystemVerilog会检查被驱动值的冲突。当检测到冲突驱动的时候会发布一个运行时错误，并且每一个发生冲突的位都被驱动成X（对一个两态端口会被驱动成0）。

例如：

Copy Code
clocking pe @(posedge clk);
    output nibble; // 四位输出
endclocking

pe.nibble <= 4'b0101;
pe.nibble <= 4'b0011;

无论nibble使一个reg还是一个wire，被驱动的值都是4'b0xx1。

当相同的变量是来自多个时钟控制块的输出的时候，最后一个驱动确定变量的值。这就使得一个单一模块能够通过使用一个不同的时钟控制块来建模每一个活跃沿来对多速率器件（例如一个DDR存储器）建模。例如：

Copy Code
reg j;

clocking pe @(posedge clk);
    output j;
endclocking

clocking ne @(negedge clk);
    output j;
endclocking

变量j是使用不同的时钟控制事件（posedge和negedge）的时钟控制块的输出。当被驱动的时候，变量j的取值应该是被这两个时钟控制块赋值的最近的值。

驱动一个线网（也就是通过不同的端口）的时钟控制块会引起线网被驱动成它的被解析的信号值。当一个时钟控制块输出对应于一个线网的时候，会产生一个线网的驱动器，它在更新的时候就好像被一个来自时钟控制块内部的寄存器连续无阻塞赋值一样。

Group

15.14 同步的驱动

链接
15.14 同步的驱动


第十六章 程序块

链接
主题
SystemVerilog 3.1a语言参考手册
第十六章 程序块
主题
主题
主题
描述
16.1 简介（一般信息）
模块是基本的Verilog构造块。模块可以包含其它模块的实例、线网、任务和函数声明、以及always块和initial块中的过程语句。这种结构非常适合于硬件的描述。然而，对测试平台来讲，其重点不是硬件级的细节（例如线网、结构化层次、以及互连），而是建模设计验证的完整环境。为了获得被正确初始化和同步的环境、避免设计与测试平台间的竞争、自动化输入激励的产生、以及复用现存的模型和其它构架，我们需要耗费很大的努力。

程序块能够实现三个基本的目标：

  1. 它提供了测试平台执行的入口点。
  2. 它产生了一个封装程序级数据的范围。
  3. 它提供了一个语境来说明Reactive区域中的调度。

程序结构在设计和测试平台间建立了一个清晰的分割，并且更为重要的是，它为程序中声明的所有元素在Reactive区域中说明了特定的执行语义。与时钟控制块一起，程序为设计和测试平台间提供了无竞争的交互，并形成了周期和事务级的抽象。

SystemVerilog的抽象和建模结构简化了测试平台的产生和维护。实例化以及单独连接每一个程序实例的能力使得它们能够作为通用模块使用。

16.2 程序结构
一个典型的程序包含类型和数据声明、子例程、设计的连接、以及一个或多个过程化的代码流。设计和测试平台间的连接使用与SystemVerilog说明端口连接（包括接口）相同的互连机制。程序块的语法如下：
16.3 多个程序
SystemVerilog允许具有任意数目的程序定义或实例。程序可以是完全独立（没有程序间的通信）的，也可以是协同操作的。通过使用嵌套的块、包、或层次化引用来共享数据，或者在对应的程序块内部声明数据（使其成为私有的），通信的程度是可以控制的。
16.4 消除测试平台的竞争
在Verilog中具有两个主要的不确定性源。第一个是激活的事件以一个任意的顺序处理。第二个是行为块中没有时间控制结构的语句不会作为一个事件执行。然而，从测试平台的角度看，这些影响都是并不重要的细节问题。测试平台的主要任务是为被测设计产生有效的输入激励，并验证被测设计是否能够正确地操作。此外，对于使用周期抽象的测试平台而言，无论是检查当前的输出还是为下一个周期计算激励，它仅与系统的稳态相关。形式工具也已这种方式工作。

在敏感于设计信号（在模块内声明而不是程序块）变化（例如更新事件）的程序块中的语句在Reactive区域被调度。考虑一个包含@(clk)语句的程序块，其中clk是某个模块中的一个设计信号。clk信号的每一个跃变都会引起语句S1被调度到Reactive区域。同样，程序块中的initial块也在Reactive区域被调度；相反，模块中的initial块则在Active区域被调度。另外，从程序内驱动的设计信号必须使用无阻塞赋值进行赋值并且在NBA区域被更新。因此，即使无延时驱动的信号也会作为一个事件被传递到设计。使用这个行为，正确的周期语义可以无竞争地被建模；因此使得基于程序的测试平台能够与周期控制的断言和形式工具相兼容。

由于程序在Reactive区域调度事件，因此时钟控制块结构对于自动地采样前一个时间步值或时钟周期的稳态值非常有用。专门通过具有#0输入时滞的时钟控制模块读取设计值的程序对于读-写竞争是不敏感的。值得注意的是：简单地采样输入信号（或者在时钟控制块输入上设置非零时滞）不会消除潜在的竞争。正确的输入采样仅仅解决了单个的时钟控制块。对于多个时钟，交叠或同时的时钟以任意顺序处理仍然是一个潜在的竞争源。通过在所有的设计事件被处理了之后（包括被无阻塞赋值驱动的时钟），在Reactive区域调度其执行，程序结构解决了这方面的问题。
16.5 阻塞周期/事件模式下的任务
在设计模块内部调用程序任务或函数是非法的并且会导致一个错误。这是因为设计不必敏感于测试平台。SystemVerilog允许程序调用位于其它程序或位于设计模块内部的任务和函数。设计模块内部的函数可以从一个程序中被调用，并且不要求特殊的处理。然而，从一个程序中调用的位于设计模块内部的阻塞任务（一个没有在0仿真时间执行的任务）在从任务返回时却要求显式的同步。也就是说，当阻塞任务返回到程序代码的时候，程序块的执行被自动挂起直到Reacive区域。参数的拷贝发生在任务返回的时候。

在从程序内部调用设计模块中的阻塞任务时需要特别小心。在第一个时序控制上阻塞之前被任务计算的表达式应该使用它们已经被无阻塞赋值更新后的值。相反，如果在时间步值的起始处（在无阻塞赋值被处理之前）从一个模块中调用任务的话，那么那些相同的表达式应该使用它们被无阻塞赋值更新之前的值。
16.6 程序控制任务
除了通常的仿真控制任务（$stop和$finish）外，一个程序可以使用$exit控制任务。
链接
主题


16.1 简介（一般信息）

链接
第十六章 程序块
SystemVerilog 3.1a语言参考手册
16.1 简介（一般信息）
第十六章 程序块

模块是基本的Verilog构造块。模块可以包含其它模块的实例、线网、任务和函数声明、以及always块和initial块中的过程语句。这种结构非常适合于硬件的描述。然而，对测试平台来讲，其重点不是硬件级的细节（例如线网、结构化层次、以及互连），而是建模设计验证的完整环境。为了获得被正确初始化和同步的环境、避免设计与测试平台间的竞争、自动化输入激励的产生、以及复用现存的模型和其它构架，我们需要耗费很大的努力。

程序块能够实现三个基本的目标：

  1. 它提供了测试平台执行的入口点。
  2. 它产生了一个封装程序级数据的范围。
  3. 它提供了一个语境来说明Reactive区域中的调度。

程序结构在设计和测试平台间建立了一个清晰的分割，并且更为重要的是，它为程序中声明的所有元素在Reactive区域中说明了特定的执行语义。与时钟控制块一起，程序为设计和测试平台间提供了无竞争的交互，并形成了周期和事务级的抽象。

SystemVerilog的抽象和建模结构简化了测试平台的产生和维护。实例化以及单独连接每一个程序实例的能力使得它们能够作为通用模块使用。

Group

第十六章 程序块

链接
第十六章 程序块


16.2 程序结构

链接
第十六章 程序块
SystemVerilog 3.1a语言参考手册
16.2 程序结构
第十六章 程序块

一个典型的程序包含类型和数据声明、子例程、设计的连接、以及一个或多个过程化的代码流。设计和测试平台间的连接使用与SystemVerilog说明端口连接（包括接口）相同的互连机制。程序块的语法如下：

Copy Code
program_nonansi_header ::=            // 引用自附录A.1.3
    {attribute_instance} program [lifetime] program_identifier
        [parameter_port_list] list_of_ports;

program_ansi_header ::=
    {attribute_instance} program [lifetime] program_identifier
        [parameter_port_list] [list_of_port_declarations];

program_declaration ::=
    program_nonansi_header [timeunits_declaration] {program_item}
        endprogram [: program_identifier]
  | program_ansi_header [timeunits_declaration] {non_port_program_item}
        endprogram [: program_identifier]
  | {attribute_instance} program program_identifier(.*);
        [timeunits_declaration] {program_item}
    endprogram [: program_identifier]
  | extern program_nonansi_header
  | extern program_ansi_header

program_item ::=               // 引用自附录A.1.7
    port_declaration;
  | non_port_program_item

non_port_program_item ::=
    {attribute_instance} continuous_assign
  | {attribute_instance} module_or_generate_item_declaration
  | {attribute_instance} specparam_declaration
  | {attribute_instance} initial_construct
  | {attribute_instance} concurrent_assertion_item
  | {attribute_instance} timeunits_declaration18

lifetime ::= static | automatic    // 引用自附录A.2.1.3

语法16-1 — 程序声明语法（摘录自附录A）

例如：

Copy Code
program test (input clk, input [16:1] addr, inout [7:0] data);
    initial ...
endprogram

或者

Copy Code
program test (interface device_ifc);
    initial ...
endprogram

一个更完整的例子包含在15.7节和15.8节中。

尽管程序结构是SystemVerilog的新结构，然而包含程序却是一个自然的扩展。程序结构可以被看作是一个具有特殊执行语义的叶子模块。一旦被声明，一个程序块可以在需要的层次位置（典型情况位于顶层）中被实例化，并且它的端口可以以任意其它模块相同的方式被连接。

程序块可以在模块或接口内部嵌套。这就使得多个协同操作的程序能够共享作用范围内的本地变量。没有端口的嵌套程序或者没有被显式实例化的顶层程序被隐含地实例化一次。被隐含地实例化的程序具有相同的实例和声明名字。例如：

Copy Code
module test(...)
    int shared; // 被程序p1和p2共享的变量

    program p1;
        ...
    endprogram

    program p2;
        ...
    endprogram // 在模块test中，p1和p2被隐含地实例化一次
endmodule

一个程序块可以包含一个或多个initial块，但不能包含always块、UDP、模块、接口或其它程序。

程序内的类型和数据声明对于程序作用范围来讲是本地的并具有静态的生命周期。非程序变量只能使用无阻塞赋值进行赋值。对程序变量使用无阻塞赋值或对设计变量（非程序变量）使用阻塞赋值都应该是一个错误。从程序块外部引用程序变量也是错误的。

Group

第十六章 程序块

链接
第十六章 程序块


16.3 多个程序

链接
第十六章 程序块
SystemVerilog 3.1a语言参考手册
16.3 多个程序
第十六章 程序块

SystemVerilog允许具有任意数目的程序定义或实例。程序可以是完全独立（没有程序间的通信）的，也可以是协同操作的。通过使用嵌套的块、包、或层次化引用来共享数据，或者在对应的程序块内部声明数据（使其成为私有的），通信的程度是可以控制的。

Group

第十六章 程序块

链接
第十六章 程序块


16.4 消除测试平台的竞争

链接
第十六章 程序块, 主题
SystemVerilog 3.1a语言参考手册
16.4 消除测试平台的竞争
第十六章 程序块 | 主题

在Verilog中具有两个主要的不确定性源。第一个是激活的事件以一个任意的顺序处理。第二个是行为块中没有时间控制结构的语句不会作为一个事件执行。然而，从测试平台的角度看，这些影响都是并不重要的细节问题。测试平台的主要任务是为被测设计产生有效的输入激励，并验证被测设计是否能够正确地操作。此外，对于使用周期抽象的测试平台而言，无论是检查当前的输出还是为下一个周期计算激励，它仅与系统的稳态相关。形式工具也已这种方式工作。

在敏感于设计信号（在模块内声明而不是程序块）变化（例如更新事件）的程序块中的语句在Reactive区域被调度。考虑一个包含@(clk)语句的程序块，其中clk是某个模块中的一个设计信号。clk信号的每一个跃变都会引起语句S1被调度到Reactive区域。同样，程序块中的initial块也在Reactive区域被调度；相反，模块中的initial块则在Active区域被调度。另外，从程序内驱动的设计信号必须使用无阻塞赋值进行赋值并且在NBA区域被更新。因此，即使无延时驱动的信号也会作为一个事件被传递到设计。使用这个行为，正确的周期语义可以无竞争地被建模；因此使得基于程序的测试平台能够与周期控制的断言和形式工具相兼容。

由于程序在Reactive区域调度事件，因此时钟控制块结构对于自动地采样前一个时间步值或时钟周期的稳态值非常有用。专门通过具有#0输入时滞的时钟控制模块读取设计值的程序对于读-写竞争是不敏感的。值得注意的是：简单地采样输入信号（或者在时钟控制块输入上设置非零时滞）不会消除潜在的竞争。正确的输入采样仅仅解决了单个的时钟控制块。对于多个时钟，交叠或同时的时钟以任意顺序处理仍然是一个潜在的竞争源。通过在所有的设计事件被处理了之后（包括被无阻塞赋值驱动的时钟），在Reactive区域调度其执行，程序结构解决了这方面的问题。

Group

第十六章 程序块

主题
主题 | 描述
16.4.1 零时滞时钟控制块竞争 | 当一个时钟控制块将输入和输出时滞都设置成#0（参见15.3节）的时候，它的输入在其输出被驱动（在NBA区域）的同一时刻被采样（在observed区域）。这种类型的显式的#0延时处理是一个能够导致竞争的基本的非确定性源。然而，即使是在这种情况下，程序通过两种机制最小化了出现竞争的可能性。首先，在所有的#0延时转换已经通过设计传播并且系统已经达到了准稳态之后约束程序语句在Reactive区域被调度。其次，通过要求设计变量或线网址能够通过非阻塞修改。这两种机制降低了竞争的可能性；尽管如此，当时滞被显式地设置成#0的时候，一个竞争仍然有可能发生。
链接
第十六章 程序块, 主题


16.4.1 零时滞时钟控制块竞争

链接
16.4 消除测试平台的竞争
SystemVerilog 3.1a语言参考手册
16.4.1 零时滞时钟控制块竞争
16.4 消除测试平台的竞争

当一个时钟控制块将输入和输出时滞都设置成#0（参见15.3节）的时候，它的输入在其输出被驱动（在NBA区域）的同一时刻被采样（在observed区域）。这种类型的显式的#0延时处理是一个能够导致竞争的基本的非确定性源。然而，即使是在这种情况下，程序通过两种机制最小化了出现竞争的可能性。首先，在所有的#0延时转换已经通过设计传播并且系统已经达到了准稳态之后约束程序语句在Reactive区域被调度。其次，通过要求设计变量或线网址能够通过非阻塞修改。这两种机制降低了竞争的可能性；尽管如此，当时滞被显式地设置成#0的时候，一个竞争仍然有可能发生。

Group

16.4 消除测试平台的竞争

链接
16.4 消除测试平台的竞争


16.5 阻塞周期/事件模式下的任务

链接
第十六章 程序块
SystemVerilog 3.1a语言参考手册
16.5 阻塞周期/事件模式下的任务
第十六章 程序块

在设计模块内部调用程序任务或函数是非法的并且会导致一个错误。这是因为设计不必敏感于测试平台。SystemVerilog允许程序调用位于其它程序或位于设计模块内部的任务和函数。设计模块内部的函数可以从一个程序中被调用，并且不要求特殊的处理。然而，从一个程序中调用的位于设计模块内部的阻塞任务（一个没有在0仿真时间执行的任务）在从任务返回时却要求显式的同步。也就是说，当阻塞任务返回到程序代码的时候，程序块的执行被自动挂起直到Reacive区域。参数的拷贝发生在任务返回的时候。

在从程序内部调用设计模块中的阻塞任务时需要特别小心。在第一个时序控制上阻塞之前被任务计算的表达式应该使用它们已经被无阻塞赋值更新后的值。相反，如果在时间步值的起始处（在无阻塞赋值被处理之前）从一个模块中调用任务的话，那么那些相同的表达式应该使用它们被无阻塞赋值更新之前的值。

Copy Code
module ...
    task T;
        S1: a = b;     // 可能在Observe区域之前或之后执行
        #5;
        S2: b <= 1'b1; // 总是在Observe区域之前执行
    endtask
endmodule

如果在一个模块中调用上面的任务T，那么语句S1可以在Active区域被处理的时候立即执行，并发生在变量b被一个无阻塞赋值更新之前。如果在一个程序内部调用相同的任务，那么语句S1应该在Reactive区域被处理的时候执行，并在变量b可以已经被无阻塞赋值更新之后。语句S2总是在延时过期之后立即执行；它不会等待Reactive区域，即使它最初从程序块中被调用。

Group

第十六章 程序块

链接
第十六章 程序块


16.6 程序控制任务

链接
第十六章 程序块, 主题
SystemVerilog 3.1a语言参考手册
16.6 程序控制任务
第十六章 程序块 | 主题

除了通常的仿真控制任务（$stop和$finish）外，一个程序可以使用$exit控制任务。

Group

第十六章 程序块

主题
主题 | 描述
16.6.1 $exit() | 每一个程序都可以通过调用$exit系统任务显式地退出。当所有的程序退出（隐式或显式）的时候，仿真会结束并且会隐式地调用$finish。 $exit系统任务的语法如下：
链接
第十六章 程序块, 主题


16.6.1 $exit()

链接
16.6 程序控制任务
SystemVerilog 3.1a语言参考手册
16.6.1 $exit()
16.6 程序控制任务

每一个程序都可以通过调用$exit系统任务显式地退出。当所有的程序退出（隐式或显式）的时候，仿真会结束并且会隐式地调用$finish。

$exit系统任务的语法如下：

Copy Code
task $exit();

当程序中所有的initial块结束的时候（也就是它们执行最后一条语句的时候），程序会隐含地调用$exit。调用$exit会导致当前程序产生的所有进程都被中止。

Group

16.6 程序控制任务

链接
16.6 程序控制任务


第十七章 断言

链接
主题
SystemVerilog 3.1a语言参考手册
第十七章 断言
主题
主题
主题
描述
17.1 简介（一般信息）
SystemVerilog加入了为一个系统指定断言的功能。断言说明了系统的一个行为。断言主要用来验证一个设计的行为。另外，断言可以被用来提供功能覆盖以及产生验证的输入激励。

SystemVerilog具有两种类型的断言：并发断言和即时断言。

  • 即时断言的执行遵从仿真事件语义并且像一个过程块中的一条语句一样执行。即时断言的主要目的是与仿真一起使用。
  • 并发断言基于时钟语义并使用变量的采样值。SystemVerilog断言的目标之一就是为断言提供一个公共的语义，这样它们可以被用来驱动不同的设计和验证工具。许多工具，例如形式验证工具，使用基于周期的语义来评估电路描述，典型情况下这种方法依赖于一个时钟信号或者信号组来驱动电路的评估。在时钟沿之间的任何时序或事件行为都会被忽略。并发断言结合了这些时钟语义。虽然这种方法通常简化了一个电路描述的评估，然而却存在一些情况，在这些情况下基于周期的评估提供了与标准的SystemVerilog基于事件的计算不同的行为。

本章表述了这两种类型的断言。

17.2 即时断言
即时断言语句是一个表达式的测试，当语句在程序代码中执行的时候完成。表达式是非时间的，并且按一个过程化if语句的条件中的表达式相同的方式解释。也就是说，如果表达式计算成X、Z或0，那么它被解释成假并且认为断言失败。否则，表达式被解释成真，并且认为断言通过。

即时断言语句是一个statement_item，并且可以在一个过程化语句被说明的任意地方说明。
17.3 并发断言概述
并发断言描述了贯穿时间的行为。与即时断言基于时钟的计算模型不同，并发断言仅在一个时钟标记出现的时候被计算。在计算中使用的变量值是采样的值。通过这种方式，我们可以获得一个可预测的结果，而不管仿真器内部的对事件进行排序和计算的机制如何。这种模型也对应于从RTL描述获得的硬件解释的综合模型。

断言中使用的变量值在一个时隙的Preponed区域被采样，并且断言在Observe区域被计算。这一点在第十四章 调度语义中解释。

一个并发断言规范采用的时序模型基于时钟标记并使用一个通用的时钟周期概念。一个时钟的定义由用户明确地说明并且在表达式之间可以存在不同。

一个时钟标记是时间上的一个原子瞬间，它本身并不具有在时间上的持续期。在任意仿真时间，一个时钟应该只标记一次，并且在这个仿真时间上采样的值被用于当前断言的计算。在一个断言中，采样值是一个时钟标记上变量唯一有效的值。图17-1显示了随着时钟的推进一个变量的值。在时钟标记1和2，req信号的值是低。在时钟标记3，采样的值为高并保持为高直到时钟标记6。变量req在时钟标记6处的采样值为低并保持为低直到时钟标记10。注意，仿真值跃变到高发生在时钟标记9。然而，时钟标记9处的采样值仍为低。

图17-1 — 在仿真标记上采样一个变量

在一个表达式中使用的表达式总是被绑定到一个时钟定义。采样值被用来计算值变化表达式或者用来确定一个序列匹配的布尔子表达式。

注意：

  • 一个重要的一点是要确保定义的时钟行为是没有毛刺的。否则会采样到错误的值。
  • 如果一个出现在时钟表达式中变量也出现在一个断言表达式中，那么这个变量的值在两个使用中可以是不同的。变量的当前值被用在时钟表达式中，而变量的采样值则用于断言。

控制序列计算的时钟表达式可以比仅仅是单一的信号名更加复杂。诸如(clk && gating_signal)和(clk iff gating_signal)之类的表达式可以被用来代表一个门时钟。其它更加复杂的表达式也是可能的。然而，为了确保正确的系统行为并尽可能真正地符合基于周期的语义，一个时钟表达式中的信号必须是无毛刺的，并且在任何仿真时间只能跃变一次。

并发断言的一个例子如下：

17.4 布尔表达式
在序列中使用的表达式针对表达式中出现的变量的采样值进行计算。一个表达式计算的结果是布尔值，并且与一个过程化if语句中条件表达式的解释方式相同。也就是说，如果表达式计算成X、Z、或0，那么它被解释成“假”。否则解释成“真”。

出现在并发断言中的表达式存在某些限制。对操作数类型、变量和操作符的限制在后续的章节中描述。

表达式可以包含函数调用，但存在某些语义限制。

  • 出现在表达式中的函数不能包含输出或ref参数（允许使用const ref）。
  • 函数应该是自动的（或者不保留状态信息）并且没有边带效应。

17.5 序列
17.6 声明序列
一个序列可以在下列单元中声明：

  • 一个模块
  • 一个接口
  • 一个程序
  • 一个时钟控制块
  • 一个包
  • 一个编译单元的作用范围

序列使用下列的语法进行声明：

17.7 序列操作
17.8 处理一个序列中的数据
使用一个SystemVerilog静态变量意味着仅存在它的一份拷贝。如果需要在流水线设计中检查数据值，那么对于每一个进入流水线的数据量值，我们可以使用一个单独的变量来存储预期的流水线输出，以便在真正退出管线的时候比较结果。这个存储空间可以通过使用一个变量数组来构建，并且为了最小化通过流水线的传播这个数组可以安排在一个移位寄存器中。然而，在一些更为复杂的情况下，例如管线的潜伏期是可变的并且是乱序的，那么这种结构可能就变得非常复杂并且容易出错。因此，我们需要一些局部变量，这些变量在一个特定的、能够跨越任意时间间隔的事务检查中使用，并且能够与其它事务检查重叠。所以，这样的一个变量必须能够在需要的时候在一个序列实例中动态地产生并能在序列结束的时候移除。

一个变量的动态产生极其赋值是通过在一个序列或特性声明中使用局部变量声明并在序列中赋值来实现的。
17.9 在一个序列匹配时调用子程序
任务、任务方法、void函数、void函数方法以及系统任务可以在一个序列成功匹配的结束处调用。子程序调用，例如局部变量赋值，出现在紧跟着序列的以逗号分割的列表中。子程序调用被称为附加到序列。序列以及之后的列表以括号包围。
17.10 系统函数
断言一般被用来计算一个设计实现的某些特定属性，例如一个特定的信号是否为“热点（one-hot）”。SystemVerilog中包含下列系统函数来促进这些基本的断言功能：

  • $onehot(<expression>) ：如果表达式中只有一位为高，那么返回“真”。
  • $onehot0(<expression>) ：如果表达式中至少有一位为高，那么返回“真”。
  • $isunknown(<expression>) ：如果表达式任何一位为X或Z，那么返回“真”，等价于：^<expression> === 'bx。

所有上述的系统函数都具有一个bit类型的返回值。1'b1的返回值指示“真”，1'b0的返回值指示“假”。

为布尔表达式提供的另外一个有用的函数是$countones，它可以计算一个位向量表达式中1的数目。

17.11 声明特性
一个特性定义了设计的一个行为。一个特性可以作为一个假设、一个检查器或者一个覆盖率规范被用于验证。为了将这种行为用于验证，必须使用一个断言、假设或者覆盖语句。一个特性声明本身不会产生任何结果。

一个特性可以在下列结构中声明：

  • 一个模块
  • 一个接口
  • 一个程序
  • 一个时钟控制块
  • 一个包
  • 一个编译单元作用域

为了声明一个特性，我们可以使用如下所示的property结构：

17.12 多时钟的支持
多时钟序列和特性可以使用下列的语法说明。
17.13 并发断言
A property on its own is never evaluated for checking an expression. It must be used within a verification statement for this to occur. A verification statement states the verification function to be performed on the property. The statement can be one of the following:

  • assert to specify the property as a checker to ensure that the property holds for the design
  • assume to specify the property as an assumption for the environment
  • cover to monitor the property evaluation for coverage

A concurrent assertion statement can be specified in:

  • an always block or initial block as a statement, wherever these... more
17.14 时钟解析
SystemVerilog具有多种方法为一个特性指定时钟。

— 具有一个时钟的序列实例，例如：
17.15 将特性绑定到作用域或实例
To facilitate verification separate from the design, it is possible to specify properties and bind them to specific modules or instances. The following are the goals of providing this feature:
  • It allows verification engineers to verify with minimum changes to the design code/files.
  • It allows a convenient mechanism to attach verification IP to a module or an instance.
  • No semantic changes to the assertions are introduced due to this feature. It is equivalent to writing properties external to a module, using hierarchical path names.
With this feature, a user can bind a module, interface, or program instance to a module... more
17.16 expect语句
The expect statement is a procedural blocking statement that allows waiting on a property evaluation. The syntax of the expect statement accepts a named property or a property declaration, and is given below.
链接
主题


17.1 简介（一般信息）

链接
第十七章 断言
SystemVerilog 3.1a语言参考手册
17.1 简介（一般信息）
第十七章 断言

SystemVerilog加入了为一个系统指定断言的功能。断言说明了系统的一个行为。断言主要用来验证一个设计的行为。另外，断言可以被用来提供功能覆盖以及产生验证的输入激励。

SystemVerilog具有两种类型的断言：并发断言和即时断言。

  • 即时断言的执行遵从仿真事件语义并且像一个过程块中的一条语句一样执行。即时断言的主要目的是与仿真一起使用。
  • 并发断言基于时钟语义并使用变量的采样值。SystemVerilog断言的目标之一就是为断言提供一个公共的语义，这样它们可以被用来驱动不同的设计和验证工具。许多工具，例如形式验证工具，使用基于周期的语义来评估电路描述，典型情况下这种方法依赖于一个时钟信号或者信号组来驱动电路的评估。在时钟沿之间的任何时序或事件行为都会被忽略。并发断言结合了这些时钟语义。虽然这种方法通常简化了一个电路描述的评估，然而却存在一些情况，在这些情况下基于周期的评估提供了与标准的SystemVerilog基于事件的计算不同的行为。

本章表述了这两种类型的断言。

Group

第十七章 断言

链接
第十七章 断言


17.2 即时断言

链接
第十七章 断言
SystemVerilog 3.1a语言参考手册
17.2 即时断言
第十七章 断言

即时断言语句是一个表达式的测试，当语句在程序代码中执行的时候完成。表达式是非时间的，并且按一个过程化if语句的条件中的表达式相同的方式解释。也就是说，如果表达式计算成X、Z或0，那么它被解释成假并且认为断言失败。否则，表达式被解释成真，并且认为断言通过。

即时断言语句是一个statement_item，并且可以在一个过程化语句被说明的任意地方说明。

Copy Code
procedural_assertion_statement ::=        // 引用自附录A.6.10
    ...
  | immediate_assert_statement

immediate_assert_statement ::=
    assert (expression) action_block

action_block ::=            // 引用自附录A.6.3
    statement_or_null
  | [statement] else statement

语法17-1 — 即时断言语法（摘录自附录A）

action_block说明了在断言成功或失败时作出什么样的动作。与断言语句成功相关联的语句是第一条语句。它被称为合格语句并且在表达式被计算成真的时候执行。例如，合格语句可以为一个覆盖率日志记录成功的数目，但合格语句也可以被完全忽略。如果合格语句被忽略，那么当断言表达式为真的时候不会作出用户指定的动作。与else相关联的语句被称为失败语句，并且当表达式被计算成假的时候执行。else语句也可以被忽略。动作块在断言表达式被计算后立即执行。

可选的语句标签（标识符和冒号）产生了一个命名的块，它包围了断言语句（或任意其它的SystemVerilog语句）并且能够使用%m的格式说明来显示。

Copy Code
assert_foo : assert(foo) $display("%m passed"); else $display("%m failed");

注意：断言控制系统任务在第23.9节中描述。

由于断言是一条有时必须为真的语句，所以断言的失败应该具有一个与其相关联的严重程度。缺省情况下，一个断言失败的严重程度是error。其它的严重程度可以通过在失败语句中包含下列严重性系统任务重的一个来指定：

  • $fatal是一个运行时的致命性错误。
  • $error是一个运行时错误。
  • $warning是一个运行时警告，它可以以一个工具专用的方式来取消。
  • $info指示不带有任何严重程度的断言失败。
这些系统任务的语法在23.8节中展示。

如果一个断言失败并且没有指定else子句，那么除非使用一个工具专用的选项（例如命令行选项）来取消失败，否则工具应该缺省调用$call。

所有这些严重性系统任务都应该打印一条工具专用的信息，它能够指示失败的严重程度以及有关特定失败的特定信息，包括：

  • 断言语句的文件名和行号。
  • 如果指定了层次化名字标签，那么应该提供断言的层次化名字；否则应该提供断言的作用范围。

对于仿真工具，这些任务还应该包含验证程度系统任务被调用的仿真运行时间。

每一个系统任务还可以使用与Verilog $display相同的格式包含额外的用户专用信息。

如果else子句包含了多个系统任务，那么每一个系统任务都应该按指定的方式执行。

如果严重性系统任务在不是断言失败的时候执行，那么断言真实的失败时间可以被记录，并被有计划地显示。例如：

Copy Code
time t;

always @(posedge clk)
    if (state == REQ)
        assert (req1 || req2)
    else begin
        t = $time;

    #5 $error("assert failed at time %0t",t);
end

如果断言在时间10处失败，那么错误消息应该时间15处打印，但用户定义的打印字符串应该为“assert failed at time 10”。

警告和信息类型的消息可以通过一个工具专用的选项（例如一个命令行选项）来控制其显示。

由于失败语句与通过语句一样可以是任何合法的SystemVerilog过程化语句，所以它还可以被用来将失败通知到测试平台的另外一个部分。

Copy Code
assert (myfunc(a,b)) count1 = count + 1; else -> event1;
assert (y == 0) else flag = 1;
Group

第十七章 断言

链接
第十七章 断言


17.3 并发断言概述

链接
第十七章 断言
SystemVerilog 3.1a语言参考手册
17.3 并发断言概述
第十七章 断言

并发断言描述了贯穿时间的行为。与即时断言基于时钟的计算模型不同，并发断言仅在一个时钟标记出现的时候被计算。在计算中使用的变量值是采样的值。通过这种方式，我们可以获得一个可预测的结果，而不管仿真器内部的对事件进行排序和计算的机制如何。这种模型也对应于从RTL描述获得的硬件解释的综合模型。

断言中使用的变量值在一个时隙的Preponed区域被采样，并且断言在Observe区域被计算。这一点在第十四章 调度语义中解释。

一个并发断言规范采用的时序模型基于时钟标记并使用一个通用的时钟周期概念。一个时钟的定义由用户明确地说明并且在表达式之间可以存在不同。

一个时钟标记是时间上的一个原子瞬间，它本身并不具有在时间上的持续期。在任意仿真时间，一个时钟应该只标记一次，并且在这个仿真时间上采样的值被用于当前断言的计算。在一个断言中，采样值是一个时钟标记上变量唯一有效的值。图17-1显示了随着时钟的推进一个变量的值。在时钟标记1和2，req信号的值是低。在时钟标记3，采样的值为高并保持为高直到时钟标记6。变量req在时钟标记6处的采样值为低并保持为低直到时钟标记10。注意，仿真值跃变到高发生在时钟标记9。然而，时钟标记9处的采样值仍为低。

图17-1 — 在仿真标记上采样一个变量

在一个表达式中使用的表达式总是被绑定到一个时钟定义。采样值被用来计算值变化表达式或者用来确定一个序列匹配的布尔子表达式。

注意：

  • 一个重要的一点是要确保定义的时钟行为是没有毛刺的。否则会采样到错误的值。
  • 如果一个出现在时钟表达式中变量也出现在一个断言表达式中，那么这个变量的值在两个使用中可以是不同的。变量的当前值被用在时钟表达式中，而变量的采样值则用于断言。
控制序列计算的时钟表达式可以比仅仅是单一的信号名更加复杂。诸如(clk && gating_signal)和(clk iff gating_signal)之类的表达式可以被用来代表一个门时钟。其它更加复杂的表达式也是可能的。然而，为了确保正确的系统行为并尽可能真正地符合基于周期的语义，一个时钟表达式中的信号必须是无毛刺的，并且在任何仿真时间只能跃变一次。

并发断言的一个例子如下：

Copy Code
base_rule1: assert property (cont_prop(rst,in1,in2)) pass_stat else fail_stat;

关键字property将一个并发断言与一个即时断言区分开来。并发断言的语法在17.13节中描述。

Group

第十七章 断言

链接
第十七章 断言


17.4 布尔表达式

链接
第十七章 断言, 主题
SystemVerilog 3.1a语言参考手册
17.4 布尔表达式
第十七章 断言 | 主题

在序列中使用的表达式针对表达式中出现的变量的采样值进行计算。一个表达式计算的结果是布尔值，并且与一个过程化if语句中条件表达式的解释方式相同。也就是说，如果表达式计算成X、Z、或0，那么它被解释成“假”。否则解释成“真”。

出现在并发断言中的表达式存在某些限制。对操作数类型、变量和操作符的限制在后续的章节中描述。

表达式可以包含函数调用，但存在某些语义限制。

  • 出现在表达式中的函数不能包含输出或ref参数（允许使用const ref）。
  • 函数应该是自动的（或者不保留状态信息）并且没有边带效应。

Group

第十七章 断言

主题
主题
描述
17.4.1 操作数类型
下列类型是不被允许的：
  • 非整数类型（shortreal、real、realtime）
  • 字符串
  • 事件
  • chandle
  • 类
  • 联合数组
  • 动态数组
固定尺寸数组（压缩的以及非压缩的）都可以当作一个整体、部分选择和被索引的位使用。片断可以是常量、参数或变量。

下面的例子显示了一些可能的结构体和联合体成员比较的格式：
17.4.2 变量
可以出现在表达式中的变量必须是静态设计变量或者是返回17.4.1节中描述的类型值的函数调用。在程序、接口或时钟控制块中声明的静态变量也可以被访问。如果引用一个任务中声明的静态变量，那么变量独立于任务调用被采样成任意其它变量。
17.4.3 操作符
针对17.4.1节中描述的类型有效的所有操作符都是允许的，除了赋值操作符以及递增和递减操作符。SystemVerilog包含C语言赋值操作符，例如+=，以及C语言递增和递减操作符（++和--）。这些表达式不能在出现在断言中的表达式中使用。这个限制阻止了边带效应。
链接
第十七章 断言, 主题


17.4.1 操作数类型

链接
17.4 布尔表达式
SystemVerilog 3.1a语言参考手册
17.4.1 操作数类型
17.4 布尔表达式

下列类型是不被允许的：

  • 非整数类型（shortreal、real、realtime）
  • 字符串
  • 事件
  • chandle
  • 类
  • 联合数组
  • 动态数组
固定尺寸数组（压缩的以及非压缩的）都可以当作一个整体、部分选择和被索引的位使用。片断可以是常量、参数或变量。

下面的例子显示了一些可能的结构体和联合体成员比较的格式：

Copy Code
typedef int [4] array;
typedef struct {int a, b, c, d} record;
union {record r; array a;} p, q;

下列的比较在表达式中是合法的：

Copy Code
p.a == q.a

以及

Copy Code
p.r == q.r

下面的例子提供了表达式中数组使用的进一步的演示。

Copy Code
logic [7:0] arrayA [0:15], arrayB[0:15];

下列的比较是合法的：

Copy Code
arrayA == arrayB;
arrayA != arrayB;
arrayA[i] >= arrayB[j];
arrayB[i][j+:2] == arrayA[k][m-:2];
(arrayA[i] & (~arrayB[j])) == 0;
Group

17.4 布尔表达式

链接
17.4 布尔表达式


17.4.2 变量

链接
17.4 布尔表达式
SystemVerilog 3.1a语言参考手册
17.4.2 变量
17.4 布尔表达式

可以出现在表达式中的变量必须是静态设计变量或者是返回17.4.1节中描述的类型值的函数调用。在程序、接口或时钟控制块中声明的静态变量也可以被访问。如果引用一个任务中声明的静态变量，那么变量独立于任务调用被采样成任意其它变量。

Group

17.4 布尔表达式

链接
17.4 布尔表达式


17.4.3 操作符

链接
17.4 布尔表达式
SystemVerilog 3.1a语言参考手册
17.4.3 操作符
17.4 布尔表达式

针对17.4.1节中描述的类型有效的所有操作符都是允许的，除了赋值操作符以及递增和递减操作符。SystemVerilog包含C语言赋值操作符，例如+=，以及C语言递增和递减操作符（++和--）。这些表达式不能在出现在断言中的表达式中使用。这个限制阻止了边带效应。

Group

17.4 布尔表达式

链接
17.4 布尔表达式


17.5 序列

链接
第十七章 断言
SystemVerilog 3.1a语言参考手册
17.5 序列
第十七章 断言
Copy Code
sequence_expr ::=          // 引用自附录A.2.10
    cycle_delay_range sequence_expr {cycle_delay_range sequence_expr}
  | sequence_expr cycle_delay_range sequence_expr {cycle_delay_range sequence_expr}
  | expression_or_dist [boolean_abbrev]
  | (expression_or_dist {, sequence_match_item}) [boolean_abbrev]
  | sequence_instance [sequence_abbrev]
  | (sequence_expr {, sequence_match_item}) [sequence_abbrev]
  | sequence_expr and sequence_expr
  | sequence_expr intersect sequence_expr
  | sequence_expr or sequence_expr
  | first_match(sequence_expr {, sequence_match_item})
  | expression_or_dist throughout sequence_expr
  | sequence_expr within sequence_expr
  | clocking_event sequence_expr

cycle_delay_range ::=
    ## integral_number
  | ## identifier
  | ## (constant_expression)
  | ## [cycle_delay_const_range_expression]

sequence_match_item ::=
    operator_assignment
  | inc_or_dec_expression
  | subroutine_call

sequence_instance ::=
    ps_sequence_identifier [([actual_arg_list])]

actual_arg_list ::=
    actual_arg_expr {, actual_arg_expr}
  | .formal_identifier(actual_arg_expr) {, .formal_identifier(actual_arg_expr)}

actual_arg_expr ::=
    event_expression
  | $

boolean_abbrev ::=
    consecutive_repetition
  | non_consecutive_repetition
  | goto_repetition

sequence_abbrev ::= consecutive_repetition

consecutive_repetition ::= [* const_or_range_expression]

non_consecutive_repetition ::= [= const_or_range_expression]

goto_repetition ::= [-> const_or_range_expression]

const_or_range_expression ::=
    constant_expression
  | cycle_delay_const_range_expression

cycle_delay_const_range_expression ::=
    constant_expression : constant_expression
  | constant_expression : $
expression_or_dist ::= expression[dist{dist_list}]

语法17-2 — 序列语法（摘录自附录A）

特性经常由有序的行为构建。sequence功能提供了一种能力来构建和处理有序的行为。最简单的有序行为是线性的。一个线性序列是SystemVerilog布尔表达式的一个有限列表，这些表达式以一个线性增加的时间顺序排列。如果第一个布尔表达式在第一个时钟标记处被计算成“真”，第二个布尔表达式在第二个时钟标记处被计算成“真”，依此类推，直到并包括最后一个布尔表达式在最后一个时钟标记被计算成“真”，那么这个线性序列被说成在一个连续时钟标记的有限间隔上匹配。单个布尔表达式是一个简单线性序列的一个例子，并且它在单个时钟标记处匹配，只要在这个时钟标记处该布尔表达式被计算成“真”。

更为复杂的有序行为通过SystemVerilog序列来描述。一个序列是一个基于SystemVerilog布尔表达式的正则表达式，它简明地说明了一组零个、有限多或无限多的线性序列。如果这个集合中的线性序列中至少有一个匹配于一个连续时钟标记的有限间隔，那么序列就被认为在这个间隔上匹配。

一个特性可能包含一个或多个开始于不同时间的有序行为的检查。一个序列的计算是一次搜索起始始于一个特定时钟标记的序列匹配的过程。为了确定是否存在一个这样的匹配，在特定的时钟标记处开始计算合适的布尔表达式并在后续的时钟标记上持续直到找到一个匹配或者由于不存在匹配而中止。

类似于链表的串联，序列可以由串联组成。串联使用##指定了一个从第一个序列的结尾直到第二个序列的开始的延时。

下述为序列串联的语法：

Copy Code
sequence_expr ::=          // 引用自附录A.2.10
    cycle_delay_range sequence_expr {cycle_delay_range sequence_expr}
  | sequence_expr cycle_delay_range sequence_expr {cycle_delay_range sequence_expr}
  ...

cycle_delay_range ::=
    ## integral_number
  | ## identifier
  | ## (constant_expression)
  | ## [cycle_delay_const_range_expression]

cycle_delay_const_range_expression ::=
    constant_expression : constant_expression
  | constant_expression : $

语法17-3 — 序列串联语法（摘录自附录A）

在此语法中：

  • constant_expression在编译时计算并且必须产生一个整数值。
  • constant_expression只能是0或者更大。
  • $标记被用来指示仿真的结束。对于形式验证工具，$被用来指示一个有限的、 无边界的范围。
  • 当一个范围使用两个表达式说明的时候，第二个表达式必须大于或等于第一个表达式。

一个序列出现的语境决定了序列何时被计算。序列中的第一个表达式在触发序列计算的表达式的第一个时钟标记处被检查。序列中的每一个后续的元素（如果有的话）在后续的时钟被检查。

一个紧跟着一个数字或范围的##说明了从当前时钟标记到下一个序列开始的延时。延时##1指示后续序列在当前时钟标记之后的一个时钟标记开始。延时##0指示下一个序列开始于与当前时钟标记相同的时钟标记。

当作为两个序列的串联使用的时候，这个延时指的是从第一个序列的结尾到第二个序列的开始之间的延时。延时##1指示第二个序列的开始在第一个序列结束后的一个时钟标记。延时##0指示第二个序列的开始于第一个序列的结尾处于同一个时钟标记。

下面是几个延时表达式的例子，`true是一个布尔表达式，它总是被计算成“真”，这样它具有很好的直观性。它可以按如下方式定义：

Copy Code
`define true 1
##0 a     // means a
##1 a     // means ‘true ##1 a
##2 a     // means ‘true ##1 ‘true ##1 a
##[0:3]a  // means (a) or (`true ##1 a) or (`true ##1 `true ##1 a) or
          // (‘true ##1 ‘true ##1 ‘true ##1 a)
a ##2 b   // means a ##1 ‘true ##1 b

对于下面的序列：

Copy Code
req ##1 gnt ##1 !req

这个序列指出req在当前的时钟标记为真，gnt应该在第一个后续的时钟标记处为真，并且req应该在此之后的下一个时钟标记处为假。##1操作符说明了一个时钟标记的间隔。多于一个时钟标记的延时可以按下列方式说明：

Copy Code
req ##2 gnt

上面的例子指出，req应该在当前的时钟标记处为真，并且gnt应该在后续的第二个时钟标记处为真，如图17-2所示。

图17-2 — 序列的串联

下面的例子说明信号b应该在信号a之后的第N个时钟标记处为真：

Copy Code
a ##N b // 在第N个采样上检查b

为了说明一个交叠序列的串联（其中一个序列的结束点与下一个序列的起始点冲突），需要使用一个为0的值，如下例所示：

Copy Code
a ##1 b ##1 c // 第一个序列seq1
d ##1 e ##1 f // 第二个序列seq2
(a ##1 b ##1 c) ##0 (d ##1 e ##1 f) // 交叠的串联

在上面的例子中，c必须在序列seq1的结束点上为“真”，并且d必须在序列seq2的起始处为“真”。当使用0时钟标记延时串联的时候，c和d必须在同一时刻为“真”，因此产生了一个等价于下面例子的串联的序列：

Copy Code
a ##1 b ##1 c&&d ##1 e ##1 f

同时需要注意的是：在序列之间没有其它形式的交叠能够使用串联操作进行表达。

在延时可以是一个范围内任意值的情况下，一个时间窗口可以使用下列形式指定：

Copy Code
req ##[4:32] gnt

在上面的例子中，信号req必须在当前的时钟标记为真，并且信号gnt必须在当前时钟标记之后的第4个和第32个时钟标记之间的某个时钟标记处为“真”。

通过使用$，这个时间窗口可以被扩展到一个有限的、但无边界的范围，如下面的例子所示。

Copy Code
req ##[4:$] gnt

通过与`true串联，一个序列可以被无条件地扩展。

Copy Code
a ##1 b ##1 c ##3 ‘true

当满足了信号c之后，序列长度被扩展了3个时钟标记。当通过较简单的序列来构建复杂序列的时候可以要求这样的在序列长度上的调整。

Group

第十七章 断言

链接
第十七章 断言


17.6 声明序列

链接
第十七章 断言
SystemVerilog 3.1a语言参考手册
17.6 声明序列
第十七章 断言

一个序列可以在下列单元中声明：

  • 一个模块
  • 一个接口
  • 一个程序
  • 一个时钟控制块
  • 一个包
  • 一个编译单元的作用范围
序列使用下列的语法进行声明：

Copy Code
concurrent_assertion_item_declaration ::=       // 引用自附录A.2.10
    ...
  | sequence_declaration

sequence_declaration ::=
    sequence sequence_identifier[([list_of_formals])];
        {assertion_variable_declaration}
        sequence_expr;
    endsequence [: sequence_identifier]

sequence_instance ::=
    ps_sequence_identifier [([actual_arg_list])]

actual_arg_list ::=
    actual_arg_expr {, actual_arg_expr}
  | .formal_identifier(actual_arg_expr){, .formal_identifier(actual_arg_expr)}

actual_arg_expr ::=
    event_expression
  | $

assertion_variable_declaration ::=
    data_type list_of_variable_identifiers;

语法17-4 — 序列声明语法（摘录自附录A）

clocking_event为序列指定了时钟。

一个序列声明可以带有可选的形式参数。当一个序列被实例化的时候，可以将实型参数传递到序列。通过使用实型参数替代形式参数，序列被展开。SystemVerilog会执行语义检查以确保使用真实参数展开的序列是合法的。

一个实型参数可以替代一个：

  • 标识符
  • 表达式
  • 事件控制表达式
  • 标记成$的上限范围
注意，在一个序列中使用，但不是序列形式参数的变量从序列被声明的作用域中根据作用域规则被求解。

Copy Code
sequence s1;
    @(posedge clk) a ##1 b ##1 c;
endsequence

sequence s2;
    @(posedge clk) d ##1 e ##1 f;
endsequence

sequence s3;
    @(negedge clk) g ##1 h ##1 i;
endsequence

在这个例子中，序列s1和s2在连续的clk上升沿事件上被计算。序列s3在连续的clk下降沿事件上被计算。

下面是序列声明的另外的一个例子，它包含了参数：

Copy Code
sequence s20_1(data, en);
    (!frame && (data == data_bus)) ##1 (c_be[0:3] == en);
endsequence

序列s20_1没有指定一个时钟。在这个例子中，一个时钟会从某个外部源（例如一个特性或一个断言语句）继承而来。一个序列可以通过它的名字引用。与SystemVerilig命名约定相一致，我们可以使用一个层次化的名字。一个序列可以在一个特性、一条断言语句或者一条覆盖语句中被引用。

为了将一个命名序列当作另外一个序列的子序列使用，我们只需简单地引用它的名字。对于引用一个命名序列的序列的计算来讲，它在执行的时候就好像这个命名序列被包含成引用序列的词法组成部分一样，这个命名序列的形式参数被实形参数所替代并且这个命名序列中剩余的变量根据命名序列声明的作用域来解析。一个例子如下所示：

Copy Code
sequence s;
    a ##1 b ##1 c;
endsequence

sequence rule;
    @(posedge sysclk)
        trans ##1 start_trans ##1 s ##1 end_trans;
endsequence

前一个例子中的序列规则等价于：

Copy Code
sequence rule;
    @(posedge sysclk)
        trans ##1 start_trans ##1 a ##1 b ##1 c ##1 end_trans;
endsequence

序列名字的任何形式的循环依赖都是不允许的。下面的例子演示了一个s1对s2以及s2对s1的非法的依赖性，因为这个例子产生了一个循环依赖。

Copy Code
sequence s1;
    @(posedge sysclk) (x ##1 s2);
endsequence

sequence s2;
    @(posedge sysclk) (y ##1 s1);
endsequence
Group

第十七章 断言

链接
第十七章 断言


17.7 序列操作

链接
第十七章 断言, 主题
SystemVerilog 3.1a语言参考手册
17.7 序列操作
第十七章 断言 | 主题
Group

第十七章 断言

主题
主题 | 描述
17.7.1 操作符优先级 | 操作符优先级和关联性在下面的表17-1中列出。最高的优先级被最先列出。 表17-1: 操作符优先级和关联性
17.7.2 序列中的复制 | 下面是序列复制的语法：
17.7.3 采样值函数 | 本节描述了用来访问一个表达式采样值的有效的系统函数。这些函数能够访问当前的采样值、访问过去的采样值、或者检测一个表达式采样值的变化。一个表达式的采样在17.3节中解释。SystemVerilog提供了下列的函数。
17.7.4 与操作 | 当我们希望两个操作数都能够匹配，但操作数序列的结束时间可以不同的时候，我们可以使用二元操作符and。
17.7.5 交集（具有长度限制的与操作） | 当我们希望两个操作数能够匹配，并且操作数序列的结束时间必须相同的时候，我们可以使用intersect二元操作符。
17.7.6 或操作 | 当希望两个操作数序列中至少有一个匹配的时候，我们可以使用or操作符。
17.7.7 first_match操作 | 对于操作数序列的一次计算尝试的多个可能的匹配，first_match操作符仅仅匹配其中的第一个。这就使得所有后续的匹配都不会被考虑。特别地，当一个序列是一个更大的序列的子序列的时候，first_match操作符对于封闭序列的计算具有明显的效果。
17.7.8 序列上的条件 | 序列经常发生在某种假设的条件下以获得正确的行为。一个逻辑条件必须保持为“真”，例如在处理一个事物的时候。而且，在处理一个事务的时候，是禁止出现某些值的 。这样的情形可以直接使用下面的结构来表达：
17.7.9 包含在另外一个序列中的序列 | 在一个序列中容纳另外一个序列可以按如下方式表示：
17.7.10 一个序列结束点的检测和使用 | SystemVerilog中提供了两种方法将一个复杂序列分解成较为简单的子序列。 一种方法是通过引用名字来实例化一个命名序列。这样一个引用的计算要求命名序列从包围序列的计算期间引用被到达的时钟标记上开始匹配。例如：
链接
第十七章 断言, 主题


17.7.1 操作符优先级

链接
17.7 序列操作
SystemVerilog 3.1a语言参考手册
17.7.1 操作符优先级
17.7 序列操作

操作符优先级和关联性在下面的表17-1中列出。最高的优先级被最先列出。

表17-1: 操作符优先级和关联性

SystemVerilog表达式操作符 | 关联性
[* ] [= ] [-> ] | ----
## | 左
throughout | 右
within | 左
intersect | 左
and | 左
or | 左
Group

17.7 序列操作

链接
17.7 序列操作


17.7.2 序列中的复制

链接
17.7 序列操作
SystemVerilog 3.1a语言参考手册
17.7.2 序列中的复制
17.7 序列操作

下面是序列复制的语法：

Copy Code
sequence_expr ::=           // 引用自附录A.2.10
    ...
  | expression_or_dist [boolean_abbrev]
  | (expression_or_dist{, sequence_match_item}) [boolean_abbrev]
  | sequence_instance [sequence_abbrev]
  | (sequence_expr{, sequence_match_item}) [sequence_abbrev]
    ...

boolean_abbrev ::=
    consecutive_repetition
  | non_consecutive_repetition
  | goto_repetition

sequence_abbrev ::= consecutive_repetition

consecutive_repetition ::= [* const_or_range_expression]

non_consecutive_repetition ::= [= const_or_range_expression]

goto_repetition ::= [-> const_or_range_expression]

const_or_range_expression ::=
    constant_expression
  | cycle_delay_const_range_expression

cycle_delay_const_range_expression ::=
    constant_expression : constant_expression
  | constant_expression : $

语法17-5 — 序列复制语法（摘录自附录A）

一个复制需要迭代的数目既可以通过一个准确的数值来指定，也可以被要求位于一个有限的范围之内。如果指定了一个准确的数值，那么迭代的数目通过一个非负的整数常量表达式来定义。如果它被要求位于一个有限的范围之内，那么迭代的最小数目通过一个非负的整数常量表达式来定义，迭代的最大数目既可以是一个非负的整数常量表达式也可以是$（它指示一个有限的但无边界的最大值）。

如果迭代的最小数目和最大数目都通过非负的整数常量表达式来定义，那么迭代的最小数目必须小于或等于其最大数目。

SystemVerilog提供了三种类型的复制：

  • 连续复制（[*）：连续复制说明了操作数序列的有限多的迭代匹配，它在一个匹配的结束到下一个匹配的开始之间具有一个时钟标记的延时。整个复制序列在操作数的最后一个迭代匹配的结束处匹配。
  • 跳转复制（ [->）：跳转复制指定了操作数布尔表达式的有限多的迭代匹配，在操作数的一次匹配到后续匹配之间具有一个或多个时钟标记的延时并且之间没有操作数的严格匹配。整个复制序列在操作数的最后一次迭代匹配处匹配。
  • 非连续复制（[=）：非连续复制制定了操作数布尔表达式的有限多的迭代匹配，它在操作数的一次匹配到后续匹配之间具有一个或多个时钟标记的延时，并且之间没有操作数的严格匹配。整个复制序列在操作数最后一次迭代匹配的时候或之后但在操作数的任何后来匹配之前匹配。

一个序列内的一个子序列的连续复制的效果可以通过显式地迭代子序列来获得，例如：

Copy Code
a ##1 b ##1 b ##1 b ##1 c

通过使用连续复制操作符[*3]，它指示了3次迭代，这个有序的行为能够以更加简洁的方式说明：

Copy Code
a ##1 b [*3] ##1 c

一个连续复制指出操作数序列必须匹配指定数目的次数。连续复制操作符[*N]指出操作数序列必须连续地匹配N次。例如：

Copy Code
a [*3]

意味着

Copy Code
a ##1 a ##1 a

使用0作为复制数目会产生一个空的序列，例如：

Copy Code
a [*0]

一个空的序列是一个不会在任何正数时钟上匹配的序列。下面的规则适用于序列与空序列串联的情况。一个空序列被表示成empty，并且一个序列被表示成seq。

  • (empty ##0 seq) 不会产生一个匹配
  • (seq ##0 empty)不会产生一个匹配
  • (empty ##n seq)，其中n大于0，它等价于(##(n-1) seq)
  • (seq ##n empty)，其中n大于0，它等价于(seq ##(n-1) 'true)

例如：

Copy Code
b ##1 (a[*0] ##0 c)

不会产生序列的匹配。

Copy Code
b ##1 a[*0:1] ##2 c

等价于

Copy Code
(b ##2 c) or (b ##1 a ##2 c)

语法允许在同一个序列中组合一个延时和复制。下列的例子都是被允许的：

Copy Code
‘true ##3 (a [*3]) // 意味着`true ##1 `true ##1 `true ##1 a ##1 a ##1 a
(‘true ##2 a) [*3] // 意味着(‘true ##2 a) ##1 (‘true ##2 a) ##1
                   // (‘true ##2 a)，进一步意味着‘true ##1 ‘true ##1
                   // a ##1 ‘true ##1 ‘true ##1 a ##1 ‘true ##1 ‘true ##1 a

一个序列可以按如下方式重复：

Copy Code
(a ##2 b) [*5]

上面的例子与下面的例子相同：

Copy Code
(a ##2 b ##1 a ##2 b ##1 a ##2 b ##1 a ##2 b ##1 a ##2 b)

一个具有最小和最大迭代数目的重复可以使用连续重复操作符[* min:max]来表达。

例如：

Copy Code
(a ##2 b)[*1:5]

等价于：

Copy Code
(a ##2 b)
or (a ##2 b ##1 a ##2 b)
or (a ##2 b ##1 a ##2 b ##1 a ##2 b)
or (a ##2 b ##1 a ##2 b ##1 a ##2 b ##1 a ##2 b)
or (a ##2 b ##1 a ##2 b ##1 a ##2 b ##1 a ##2 b ##1 a ##2 b)

类似地：

Copy Code
(a[*0:3] ##1 b ##1 c)

等价于：

Copy Code
(b ##1 c)
or (a ##1 b ##1 c)
or (a ##1 a ##1 b ##1 c)
or (a ##1 a ##1 a ##1 b ##1 c)

为了指定一个有限的但无边界数目的迭代，我们可以使用一个$符号。例如，下面的复制：

Copy Code
a ##1 b [*1:$] ##1 c

在上面的例子中，如果a在第一个时钟标记处为“真”，c在最后一个时钟标记处为“真”，并且b在第一个和最后一个时钟标记之间的每一个时钟标记都为“真”，那么这个序列在三个或更多个时钟标记的间隔上匹配。

通过准确数目来指定一个复制迭代的数目等价于指定一个最小复制数目等于最大复制数目的范围。换句话说， seq[*n]等价于seq[*n:n]。

跳转复制（非连续准确的复制）将一个布尔表达式而不是一个序列作为操作数。它指定了在没必要连续并且在最后一个迭代匹配上结束的时钟标记上的布尔表达式的迭代匹配。例如：

Copy Code
a ##1 b [->2:10] ##1 c

在上面的例子中，如果a在第一个时钟标记处为“真”，c在最后一个时钟标记上为“真”，b在倒数第二个时钟标记处为“真”，并且在第一个和最后一个b为“真”之间不一定为连续的时钟标记上具有至少2个（包括倒数第二个时钟标记）、最多10个b为“真”，那么例子中的序列在连续的时钟标记的间隔上匹配。它等价于下面的例子：

Copy Code
a ##1 ((!b[*0:$] ##1 b) [*2:10]) ##1 c

除了一个匹配不必在操作数布尔表达式的最后一个迭代匹配结束之外，非连续复制类似于跳转复制。如果布尔表达式在所有的时钟标记上为“假”，那么使用非连续复制而不是跳转复制使得匹配被扩展了任意多的时钟标记。例如：

Copy Code
a ##1 b [=2:10] ##1 c

如果a在第一个时钟标记处为“真”，c在最后一个时钟标记处为“真”，并且在b为“真”的第一个和最后一个匹配之间至少两个至多10个不必连续的时钟标记上匹配，那么这个序列匹配。这个序列等价于：

Copy Code
a ##1 ((!b [*0:$] ##1 b) [*2:10]) ##1 !b[*0:$] ##1 c
Group

17.7 序列操作

链接
17.7 序列操作


17.7.3 采样值函数

链接
17.7 序列操作
SystemVerilog 3.1a语言参考手册
17.7.3 采样值函数
17.7 序列操作

本节描述了用来访问一个表达式采样值的有效的系统函数。这些函数能够访问当前的采样值、访问过去的采样值、或者检测一个表达式采样值的变化。一个表达式的采样在17.3节中解释。SystemVerilog提供了下列的函数。

Copy Code
$sampled(expression [, clocking_event])
$rose(expression [, clocking_event])
$fell(expression [, clocking_event])
$stable(expression [, clocking_event])
$past(expression1 [, number_of_ticks] [, expression2] [, clocking_event])

这些函数的使用并没有被限制到断言功能；它们也可以被用作过程化代码中的表达式。时钟控制事件尽管作为函数的一个显式的参数是可选的，但在语义上它是需要的。

时钟控制事件必须被显式地指定成一个参数，或者从它使用的代码中被推断出来。下列规则被用来推断时钟控制事件：

  • 如果使用在一个断言当中，那么使用来自断言的合适的时钟控制事件。
  • 如果使用在一个单一定时断言的动作块中，那么使用断言的时钟。
  • 如果使用在一个过程化块中，那么使用过程化代码的推断时钟（参见17.13.5节）。
否则，会使用缺省时钟控制（参见15.11节）。

当这些函数被使用在一个断言中的时候，函数的时钟控制事件参数（如果指定了的话）应该与断言中表达式的时钟控制事件相同。在多时钟断言的情况下，其中函数被使用的表达式的合适的时钟控制事件被应用到这个函数。

函数$sampled返回与时钟控制事件最后一次发生有关的表达式的采样值。当$sampled在第一个时钟控制事件发生之前被调用的时候，函数会返回X。尽管在断言中使用$sampled函数是被允许的，但它确实多余的，因为函数的结果与在断言中使用的表达式本身的采样值是相同的。

SystemVerilog提供了三个函数来检测采样值的变化：$rose、$fell和$stable。

一个值改变函数检测一个表达式在采样值上的改变。时钟控制事件被用来在当前仿真时间单位之前的一个时钟标记上获取参数表达式的采样值。在这里，当前仿真时间单位指的是函数被计算的仿真时间单位。这个采样值与当前仿真时间单位的prepone时间上决定的表达式的值进行比较。一个值改变表达式的结果是“真”或“假”，并且可以在一个布尔表达式中使用。

如果表达式的最低有效位变为1，那么$rose返回“真”；否则返回“假”。

如果表达式的最低有效位变为0，那么$fell返回“真”；否则返回“假”。

如果表达式的值没有发生变化，那么$stable返回“真”；否则返回“假”。

当这些函数在时钟控制事件的第一个时钟标记上或之前被调用的话，那么通过将表达式当前的采样值与X进行比较来计算结果。

图17-3演示了值改变的两个例子：

  • 值改变表达式e1被定义成$rose(req)
  • 值改变表达式e2被定义成$fell(ack)

图17-3 — 值改变表达式

用来采样变量的时钟标记由特性的时钟衍生而来，它不同于仿真标记。现在，我们假设这个时钟在其它地方定义。因为req的值在时钟标记2处为低而在时钟标记3处为高，所以e1在时钟标记3处出现。类似地，因为ack的值在时钟标记5处采样为高而在时钟标记6处采样为低，因此e2发生在时钟标记6处。

下面的例子演示了$rose在断言之外的SystemVerilog代码中的使用。

Copy Code
always @(posedge clk)
    reg1 <= a & $rose(b);

在这个例子中，时钟控制事件(posedge clk)被应用到$rose。只要b的采样值从时钟控制事件前一个标记上的值改变到1，那么$rose的结果即为“真”。

除了访问值改变外，以前的值可以通过$past函数访问。SystemVerilog为$past函数提供了下面的三个可选的参数：

expression2被用作是时钟控制事件的门表达式；

number_of_ticks指定了过去发生的时钟标记的数目；

clocking_event为expression1指定了时钟控制事件；

expression1和expression2可以是断言中允许使用的任何表达式。

number_of_ticks必须大于或等于1。如果没有指定number_of_ticks，。那么它的缺省值为1。$past函数返回在$past被计算之前的number_of_ticks个时钟标记处表达式的采样值。一个时钟标记基于clocking_event。如果指定的过去的时钟标记在仿真开始之前，那么$past函数的返回值为X。

可选参数clocking_event指定了函数的时钟。clocking_event的使用规则与值改变函数中描述的规则相同。

当不需要两个参数中间的可选参数的时候，必须为每一个被忽略的参数放置一个逗号。例如：

Copy Code
$past(in1, , enable);

在这里指定了一个逗号来忽略number_of_ticks。对于空的number_of_ticks参数，会使用缺省值1。注意，如果想要忽略clocking_event，就不需要放置一个逗号，因为它没有位于指定的参数之间。

$past函数可以用于任何SystemVerilog表达式中，下面的代码就展示了一个这样的例子。

Copy Code
always @(posedge clk)
    reg1 <= a & $past(b);

在这个例子中，时钟控制事件(posedge clk)被应用到$past函数。$past在(posedge clk) 当前发生的时候被计算，并返回(posedge clk)前一次发生时候的采样值。

当指定了expression2的时候，expression1的采样基于expression2的门控时钟。例如，

Copy Code
always @(posedge clk)
    if (enable) q <= d;

always @(posedge clk)
    assert (done |=> (out == $past(q, 2, enable));

在这个例子中，计算$past时q的采样基于下面的时钟控制表达式：

Copy Code
posedge clk iff enable
Group

17.7 序列操作

链接
17.7 序列操作


17.7.4 与操作

链接
17.7 序列操作
SystemVerilog 3.1a语言参考手册
17.7.4 与操作
17.7 序列操作

当我们希望两个操作数都能够匹配，但操作数序列的结束时间可以不同的时候，我们可以使用二元操作符and。

Copy Code
sequence_expr ::=         // 引用自附录A.2.10
    ...
  | sequence_expr and sequence_expr

语法17-6 — and操作符语法（摘录自附录A）

and的两个操作数为序列。and操作的匹配要求两个操作数必须匹配。操作数序列起始于相同的时间。当其中的一个操作数匹配的时候，它等待另外一个操作数匹配。复合序列的结束时间是匹配后一个操作数的结束时间。

如果te1和te2是序列，那么对于复合序列：

Copy Code
te1 and te2

  • 在te1和te2匹配的时候匹配。
  • 结束时间是te1和te2中最后一个匹配的时间。
下面的例子是一个具有and操作符的序列，其中的两个操作数都是序列。

Copy Code
(te1 ##2 te2) and (te3 ##2 te4 ##2 te5)

图17-4 — 两个序列的与操作

图17-4中演示的操作展示了在时钟标记8处的计算尝试。在这里，两个操作数序列为(te1 ##2 te2)和(te3 ##2 te4 ##2 te5)。第一个操作数序列要求te1首先被计算为真，然后te2在两个时钟标记之后被计算为真。第二个序列要求te3首先被计算为“真”，然后te4在两个时钟标记之后被计算为“真”，最后te5在两个时钟标记之后被计算为“真”。

因为两个操作数序列都是匹配的，所以这个计算尝试会产生一个匹配。单个序列匹配的结束时间是时钟标记10和时钟标记12。复合序列的结束时间是两个结束时间较晚的一个，复合序列在时钟标记12处识别了一个匹配。

在下面的例子中，第一个操作数序列具有一个串联操作符，范围为1到5：

Copy Code
(te1 ##[1:5] te2) and (te3 ##2 te4 ##2 te5)

第一个操作数序列要求te1被计算成“真”，并且te2在1、2、3、4或5个时钟标记之后被计算成“真”。第二个操作数序列与前一个例子相同。为了考虑复合序列匹配的所有的可能性，我们采用下列的步骤：

  1. 为与第一个序列操作数相关的五个可能的线性序列启动五个执行线程。
  2. 第二个操作数序列只有一个相关联的线性序列，所以只为它启动一个执行线程。
  3. 图17-5显示了开始于时钟标记8处的计算尝试。正像一个时间窗口中显示的那样，第一个操作数序列的所有五个线性序列都是匹配的，所以有五个第一个操作数序列的匹配，它们分别在时钟标记9、10、11、12和13处结束。第二个操作数序列在时钟标记12处结束。
  4. 第一个操作数的每一次匹配都与第二个操作数序列的单次匹配相结合，与操作的规则决定了复合序列最终匹配的结束时间。

这个计算的结果是复合序列的五个匹配，其中的四个在时钟标记12处结束，第五个在时钟标记13处结束。图17-5显示了复合序列在时钟标记12和13处结束的匹配。

图17-5 — 两个序列的与操作 ，包括一个时间范围

如果te1和te2是被采样的表达式（不是序列），那么在te1和te2在都被计算成“真”的时候序列（te1和te2）会匹配。

图17-6中展示了一个这样的例子，它显示了在每一个时钟标记处的尝试结果。序列在时钟标记1、3、8和14处匹配，因为te1和te2在这些时钟标记处同时为“真”。在所有其它的时钟标记处，序列匹配是失败的，因为在这些时钟标记上，或者te1为“假”，或者te2为“假”。

图17-6 — 两个布尔表达式的与操作

Group

17.7 序列操作

链接
17.7 序列操作


17.7.5 交集（具有长度限制的与操作）

链接
17.7 序列操作
SystemVerilog 3.1a语言参考手册
17.7.5 交集（具有长度限制的与操作）
17.7 序列操作

当我们希望两个操作数能够匹配，并且操作数序列的结束时间必须相同的时候，我们可以使用intersect二元操作符。

Copy Code
sequence_expr ::=    // 引用自附录A.2.10
    ...
  | sequence_expr intersect sequence_expr

语法17-7 — 交集操作符语法（摘录自附录A）

intersect操作的两个操作数都是序列。intersect操作匹配的要求如下：

  • 两个操作数都必须匹配。
  • 操作数序列的两个匹配长度必须相同。
有关序列长度的其它要求是and操作与intersect操作的基本差别。

一个intersect序列的计算尝试会产生多个匹配。这样的一个尝试的结果可以按如下方式计算。

  • 具有相同长度的第一个和第二个操作数的匹配是成对的。每一个这样的对都会产生一个复合序列的匹配，其长度和结束点等于操作数序列成对匹配的共享长度和结束点。
  • 如果没有找到这样的对，那么复合序列不会匹配。
除了使用intersect替代and外，图17-7类似于图17-5。在这个例子中，与图17-5不同，只在时钟标记12处具有单个匹配。

图17-7 — 两个序列的交集

Group

17.7 序列操作

链接
17.7 序列操作


17.7.6 或操作

链接
17.7 序列操作
SystemVerilog 3.1a语言参考手册
17.7.6 或操作
17.7 序列操作

当希望两个操作数序列中至少有一个匹配的时候，我们可以使用or操作符。

Copy Code
sequence_expr ::=    // 引用自附录A.2.10
    ...
  | sequence_expr or sequence_expr

语法17-8 — or操作符语法（摘录自附录A）

or操作符的两个操作数均为序列。

对于下面的例子，如果操作数te1和te2为表达式，那么这个例子在te1和te2中至少有一个计算成“真”的任意时钟标记上匹配。

Copy Code
te1 or te2

图17-8演示了一个or操作的例子，其中te1和te2为表达式。符合序列在时钟标记7和13处不会匹配，因为在这些时间标记上，无论te1还是te2都为“假”。在所有其它的时钟标记上符合序列都是匹配的，因为两个操作数中至少有一个可以被计算成“真”。

图17-8 — 两个序列的或操作

当te1和te2都是序列的时候，对于下面的序列：

Copy Code
te1 or te2

如果两个操作数序列中至少有一个匹配的时候上面的序列会匹配。te1或者te2的每一次匹配都会引起复合序列的一次匹配，并且符合序列匹配的结束时间与te1或te2匹配的结束时间相同。换句话说，复合序列的匹配集合是te1匹配集合与te2匹配集合的联合。

下面的例子显示了一个具有or操作符的序列，其中的两个操作数都是序列。图17-9演示了这个例子。

Copy Code
(te1 ##2 te2) or (te3 ##2 te4 ##2 te5)

图17-9 — 两个序列的或操作（or）

在这个例子中，两个操作数序列为：(te1 ##2 te2)和(te3 ##2 te4 ##2 te5)。第一个序列要求te1首先被计算成“真”，跟着是te2在两个时钟标记之后被计算成“真”。第二个序列要求te3被计算成“真”，跟着是te4在两个时钟标记之后被计算成“真”，然后是te5在两个时钟标记之后被计算成“真”。图17-9显示了时钟标记8处的计算尝试。第一个序列在时钟标记10处匹配，第二个序列在时钟标记12处匹配。所以复合序列的匹配就被识别出来。

在下面的例子中，第一个操作数序列具有一个串联操作符，其范围从1到5。

Copy Code
(te1 ##[1:5] te2) or (te3 ##2 te4 ##2 te5)

第一个操作数序列要求te1被计算成“真”，并且te2在1、2、3、4或5个时钟标记之后被计算成真。第二个操作数序列要求te3被计算成“真”，te4在两个时钟标记之后被计算成“真”，te5在另外两个时钟周期后被计算成“真”。复合序列在两个操作数中至少一个匹配的任意时钟标记上匹配。正如图17-10所显示的，对于时钟标记8处的尝试，第一个操作数序列在时钟标记9、10、11、12和13处匹配，而第二个操作书在时钟标记12处匹配。因此，复合序列在时钟标记9、10、11、13处的每一个上具有一次匹配，并在时钟标记12处具有两次匹配。

图17-10 — 两个序列的或（or）操作，包含一个时间范围

Group

17.7 序列操作

链接
17.7 序列操作


17.7.7 first_match操作

链接
17.7 序列操作
SystemVerilog 3.1a语言参考手册
17.7.7 first_match操作
17.7 序列操作

对于操作数序列的一次计算尝试的多个可能的匹配，first_match操作符仅仅匹配其中的第一个。这就使得所有后续的匹配都不会被考虑。特别地，当一个序列是一个更大的序列的子序列的时候，first_match操作符对于封闭序列的计算具有明显的效果。

Copy Code
sequence_expr ::=      // 引用自附录A.2.10
    ...
  | first_match (sequence_expr{, sequence_match_item})

语法17-9 — first_match操作符语法（摘录自附录A）

first_match(seq)的每一次计算尝试均会产生一次起始于相同的时钟标记的针对操作数seq的计算尝试。如果seq的计算尝试没有产生匹配，那么first_match(seq)的计算尝试也不会产生匹配。否则，具有最早结束时钟标记的seq的匹配是first_match(seq)的匹配。如果seq在相同的结束时钟标记上具有多个最早的匹配，那么所有的这些匹配都是first_match(seq)的匹配。

下面的例子显示了一个可变延时的说明：

Copy Code
sequence t1;
    te1 ## [2:5] te2;
endsequence

sequence ts1;
    first_match(te1 ## [2:5] te2);
endsequence

在这个例子中，te1和te2均为表达式。序列t1的每一次计算尝试均可能产生多达四个下列序列的匹配：

Copy Code
te1 ##2 te2
te1 ##3 te2
te1 ##4 te2
te1 ##5 te2

然而，序列ts1仅能为上述四个匹配中的一个产生匹配。上述四个序列中最先结束的那一个就是序列ts1的匹配。

另外一个例子：

Copy Code
sequence t2;
    (a ##[2:3] b) or (c ##[1:2] d);
endsequence

sequence ts2;
    first_match(t2);
endsequence

序列t2的每一次计算尝试均可能产生多达四个下列序列的匹配：

Copy Code
a ##2 b
a ##3 b
c ##1 d
c ##2 d

序列ts2仅仅匹配这些序列中最早结束的匹配。如果a、b、c和d均为表达式，那么可能存在两个在同一时间结束的匹配。

Copy Code
a ##2 b
c ##2 d

如果这些序列都是匹配的，并且(c ##1 d)没有匹配，那么ts2的计算会产生这样的两个匹配。

序列匹配条目可以被附加到first_match操作符的操作数序列。序列条目被放置在与包围操作数的括号相同的括号集内。因此，例如，局部变量赋值x = e可以通过下述的方式被附加到seq的first_match操作符：

Copy Code
first_match(seq, x = e)

上面的例子等价于：

Copy Code
first_match((seq, x = e))

参见17.8节和17.9节中有关序列匹配条目的讨论。

Group

17.7 序列操作

链接
17.7 序列操作


17.7.8 序列上的条件

链接
17.7 序列操作
SystemVerilog 3.1a语言参考手册
17.7.8 序列上的条件
17.7 序列操作

序列经常发生在某种假设的条件下以获得正确的行为。一个逻辑条件必须保持为“真”，例如在处理一个事物的时候。而且，在处理一个事务的时候，是禁止出现某些值的 。这样的情形可以直接使用下面的结构来表达：

Copy Code
sequence_expr ::=       // 引用自附录A.2.10
    ...
  | expression_or_dist throughout sequence_expr

语法17-10 — throughout结构的语法（摘录自附录A）

exp throughout seq结构是下列语句的缩写：

Copy Code
(exp) [*0:$] intersect seq

对于复合序列exp throughout seq，只要seq在一个有限的连续时钟标记间隔上匹配并且exp在这个间隔的每一个时钟标记上为“真”，那么这个复合序列就在这段间隔上匹配。

图17-11演示了如下的例子。

Copy Code
sequence burst_rule1;
    @(posedge mclk)
        $fell(burst_mode) ##0
        (!burst_mode) throughout (##2 ((trdy==0)&&(irdy==0)) [*7]);
endsequence

图17-11 — throughout限制失败的匹配

图17-11演示了起始于时钟标记2处针对序列burst_rule1的计算尝试。由于信号burst_mode在时钟标记1处为高并且在时钟标记2处为低，所以$fell(burst_mode)在时钟标记2处为“真”。为了实现burst_rule1的匹配，要求burst_mode的值在起始于时钟标记2处的子序列(##2 ((trdy==0)&&(irdy==0)) [*7])的一次匹配期间内为低。这个子序列在时钟标记2到时钟标记10之间匹配。然而，在时钟标记9处burst_mode变为高，因此，根据througout的规则，序列的匹配失败。

相反，如果信号burst_mode能够至少在时钟标记10处保持为低，那么从时钟标记2到时钟标记10之间burst_rule1会有一次匹配，如图17-12所示。

图17-12 — throughout限制成功的匹配

Group

17.7 序列操作

链接
17.7 序列操作


17.7.9 包含在另外一个序列中的序列

链接
17.7 序列操作
SystemVerilog 3.1a语言参考手册
17.7.9 包含在另外一个序列中的序列
17.7 序列操作

在一个序列中容纳另外一个序列可以按如下方式表示：

Copy Code
sequence_expr ::=         // 引用自附录A.2.10
    ...
  | sequence_expr within sequence_expr

语法17-11 — within结构的语法（摘录自附录A）

seq1 within seq2结构是下述语句的缩写：

Copy Code
(1[*0:$] ##1 seq1 ##1 1[*0:$]) intersect seq2

对于复合序列seq1 within seq2，只要seq2在一个有限的连续时钟标记间隔上匹配并且seq1在这个间隔的某些子间隔上匹配，那么这个复合序列就在这段间隔上匹配。也就是说，seq1和seq2的匹配必须满足下列条件：

  • seq1匹配的起始点必须不早于seq2匹配的起始点。
  • seq1匹配的结束点必须不晚于seq2匹配的结束点。
例如，对于下面的序列：

Copy Code
!trdy[*7] within (($fell irdy) ##1 !irdy[*8])

在图17-12中所显示的路径中，上面的例子在时钟标记3到时钟标记11间匹配。

Group

17.7 序列操作

链接
17.7 序列操作


17.7.10 一个序列结束点的检测和使用

链接
17.7 序列操作
SystemVerilog 3.1a语言参考手册
17.7.10 一个序列结束点的检测和使用
17.7 序列操作

SystemVerilog中提供了两种方法将一个复杂序列分解成较为简单的子序列。

一种方法是通过引用名字来实例化一个命名序列。这样一个引用的计算要求命名序列从包围序列的计算期间引用被到达的时钟标记上开始匹配。例如：

Copy Code
sequence s;
    a ##1 b ##1 c;
endsequence

sequence rule;
    @(posedge sysclk)
        trans ##1 start_trans ##1 s ##1 end_trans;
endsequence

序列s从序列rule中的start_trans被计算的一个时钟标记之后开始计算。

使用一个序列的另外一个方法是在另外一个序列中检测它的结束点。只要一个序列匹配的结束时钟标记到达，这个序列的结束点就到达，而不管匹配的起始时钟标记如何。通过使用ended方法，任何序列中结束点的到达都可以被检测到。

ended方法的语法如下：

Copy Code
sequence_instance.ended

ended是一个作用于一个序列的方法。这个方法的操作结果或者为“真”，或者为“假”。当ended方法在一个表达式中被计算的时候，它检测其操作数序列在特定的时间点上是否到达了它的结束点。

ended的结果并不依赖于其操作书序列匹配的起始点。这样的一个例子如下所示：

Copy Code
sequence e1;
    @(posedge sysclk) $rose(ready) ##1 proc1 ##1 proc2;
endsequence

sequence rule;
    @(posedge sysclk) reset ##1 inst ##1 e1.ended ##1 branch_back;
endsequence

在这个例子中，序列e1必须在inst之后的一个时钟标记匹配。如果使用e1的一个实例来替代ended方法，e1的一个匹配必须在inst之后的一个时钟标记开始。注意：ended方法仅仅检测e1的结束点，并且对e1的起始点没有意义。ended方法可以用于具有形式参数的序列。例如下面的声明：

Copy Code
sequence e2(a,b,c);
    @(posedge sysclk) $rose(a) ##1 b ##1 c;
endsequence

sequence rule2;
    @(posedge sysclk) reset ##1 inst ##1 e2(ready,proc1,proc2).ended
        ##1 branch_back;
endsequence

rule2等价于下面的rule2a：

Copy Code
sequence e2_instantiated;
    e2(ready, proc1, proc2);
endsequence

sequence rule2a;
    @(posedge sysclk) reset ##1 inst ##1 e2_instantiated.ended ##1 branch_back;
endsequence

在将局部变量传递到一个应用了ended方法的序列实例的时候存在一些其它的限制。参见17.8节。

Group

17.7 序列操作

链接
17.7 序列操作


17.8 处理一个序列中的数据

链接
第十七章 断言
SystemVerilog 3.1a语言参考手册
17.8 处理一个序列中的数据
第十七章 断言

使用一个SystemVerilog静态变量意味着仅存在它的一份拷贝。如果需要在流水线设计中检查数据值，那么对于每一个进入流水线的数据量值，我们可以使用一个单独的变量来存储预期的流水线输出，以便在真正退出管线的时候比较结果。这个存储空间可以通过使用一个变量数组来构建，并且为了最小化通过流水线的传播这个数组可以安排在一个移位寄存器中。然而，在一些更为复杂的情况下，例如管线的潜伏期是可变的并且是乱序的，那么这种结构可能就变得非常复杂并且容易出错。因此，我们需要一些局部变量，这些变量在一个特定的、能够跨越任意时间间隔的事务检查中使用，并且能够与其它事务检查重叠。所以，这样的一个变量必须能够在需要的时候在一个序列实例中动态地产生并能在序列结束的时候移除。

一个变量的动态产生极其赋值是通过在一个序列或特性声明中使用局部变量声明并在序列中赋值来实现的。

Copy Code
sequence_expr ::=         // 引用自附录A.2.10
    ...
  | (expression_or_dist{, sequence_match_item}) [boolean_abbrev]
  | (sequence_expr{, sequence_match_item}) [sequence_abbrev]
    ...

语法 17-12 — 变量赋值语法（摘录自附录A）

变量的类型被显式地说明。通过将子序列、采样赋值放置在圆括号中并以逗号分割，变量可以在任意符合语法的子序列的结束点上被赋值。例如，如果在下面的序列中：

Copy Code
a ##1 b[->1] ##1 c[*2]

我们希望在b[->1]的匹配上作这样的赋值：x = e，那么序列可以按如下方式重写：

Copy Code
a ##1 (b[->1], x = e) ##1 c[*2]

以后，局部变量可以在序列中按如下的方式被重新赋值：

Copy Code
a ##1 (b[->1], x = e) ##1 (c[*2], x = x + 1)

对于每一次尝试，都会为序列产生变量的一个新的拷贝。变量值可以向任何其它SystemVerilog变量一样被测试。

不允许层次化地引用局部变量。

考虑一个局部变量使用的例子，假设一个流水线具有固定的5个时钟周期的潜伏期。当valid_in为“真”的时候，pipe_in携带数据进入管线，并且流水线计算的值在5个时钟周期之后出现在信号pipe_out1上。管线传输的数据通过一个函数来预测，这个函数对数据进行递增。下面的特性验证了这个行为：

Copy Code
property e;
    int x;
    (valid_in,(x = pipe_in)) |-> ##5 (pipe_out1 == (x+1));
endproperty

特性e按如下方式计算：

  1. 当valid_in为“真”的时候，x被赋值为pipe_in的值。如果5个周期之后，pipe_out1等于x+1，那么特性e为“真”。否则特性e为“假”。
  2. 当valid_in为“假”的时候，特性e计算成“真”。

变量可以在序列或特性中使用。

Copy Code
sequence data_check;
    int x;
    a ##1 !a, x = data_in ##1 !b[*0:$] ##1 b && (data_out == x);
endsequence

property data_check_p
    int x;
    a ##1 !a, x = data_in |=> !b[*0:$] ##1 b && (data_out == x);
endproperty

局部变量可以在重复的序列上写入并实现值的累加。

Copy Code
sequence rep_v;
    int x;
    `true,x = 0 ##0
    (!a [*0:$] ##1 a, x = x+data)[*4] ##1 b ##1 c && (data_out == x);
endsequence

局部变量在这个序列被实例化的序列中是不可见的。下面的例子演示了在序列seq1中对子序列sub_seq1中局部变量v1的无效访问。

Copy Code
sequence sub_seq1;
    int v1;
    a ##1 !a, v1 = data_in ##1 !b[*0:$] ##1 b && (data_out == v1);
endsequence

sequence seq1;
    c ##1 sub_seq1 ##1 (do1 == v1); // 错误的，因为v1是不可见的。
endsequence

为了访问一个子序列的局部变量，必须声明一个局部变量并通过一个自变量传递到被实例化的子序列。下面的例子演示了这样的用法。

Copy Code
sequence sub_seq2(lv);
    a ##1 !a, v1 = data_in ##1 !b[*0:$] ##1 b && (data_out == lv);
endsequence

sequence seq2;
    int v1;
    c ##1 sub_seq2(v1) ##1 (do1 == v1); // 现在v1被绑定到lv
endsequence

局部变量可以被传递到一个应用了ended的命名序列的实例，并且以相似的方式访问。例如：

Copy Code
sequence seq2a;
    int v1;
    c ##1 sub_seq2(v1).ended ##1 (do1 == v1); // 现在v1被绑定到lv
endsequence

当将局部变量可以被传递到一个应用了ended的命名序列的实例的时候存在一些限制：

  1. 局部变量只能以完整的实型参数传递，而不能作为实型参数的正确子表达式传递。
  2. 在命名序列的声明中，局部变量被绑定的形式参数不能在它被赋值之前引用。

sub_seq2符合第二条限制，因为v1 = data_in的赋值发生在data_out == lv中对lv的引用之前。

如果一个局部变量在被传递到一个应用了ended的命名序列的实例之前进行了赋值，那么上述的限制能够防止所赋的值在命名序列内部可见。这些限制是重要的，因为ended的使用意味着局部变量在命名序列外部被赋值的时间点与实例匹配的起始点没有能够得到保证的关系。

如果下面两个条件被满足，一个作为实形参数被传递到一个应用了ended的命名序列的实例的局部变量将会从ended的应用中流出到该实例：

  1. 局部变量流出命名序列实例的结尾，如序列的局部变量流规则所定义的那样。（参见下面的描述以及附录H。）
  2. 作用到该实例的ended的应用是一个最大的布尔表达式。换句话说，ended的应用上不能有非或任何其它表达式操作符。
上述的两个条件均被sub_seq2和seq2a所满足。因此，seq2a中比较表达式do1 == v1中v1的值为sub_seq2中通过赋值语句v1 = data_in赋给lv的值。 然而，对于下面的例子：

Copy Code
sequence seq2b;
    int v1;
    c ##1 !sub_seq2(v1).ended ##1 (do1 == v1); // v1 unassigned
endsequence

上面的例子违背了第二个条件，因为“非”操作被应用到了sub_seq2(v1).ended。因此，v1不会从ended的应用中流出到这个实例，并在表达式do1 == v1中对v1的引用是一个未赋值的变量。

在单个周期中，一个应用了ended的序列实例可能具有多个匹配，并且这些匹配对本地变量可能具有不同的计算结果。在语义上，多个匹配按匹配一个or操作的两个析取项相同的方式对待（参见下面的描述）。换句话说，计算应用了ended的实例的线程将会产生分支以便单独地考虑这些局部变量。

注意：当一个局部变量是一个序列声明的形式参数的时候，按如下所示的方式声明变量是非法的。

Copy Code
sequence sub_seq3(lv);
    int lv; // 因为lv是一个形式参数，所以该条声明是非法的。
    a ##1 !a, v1 = data_in ##1 !b[*0:$] ##1 b && (data_out == lv);
endsequence

当在调用分支操作符or、and以及intersect的序列中使用局部变量的时候，必须作出一些特别的考虑。从这些操作符的一个构建而来的复合序列的计算可以认为是产生两个分支线程来并行地计算操作书序列。在开始计算复合序列之前一个局部变量可能已经被赋了值。这样的一个局部变量被称为流入到每一个操作数序列。局部变量可以在一个或两个操作数序列中被赋值或解赋值。通常，我们不能保证两个线程的计算会产生一致的结果值，乃至对局部变量是否已经被赋了值具有一致的认识。因此，在复合序列的计算过程中或之前赋给局部变量的值并不总是被允许在复合序列的计算之后可见。

在某些情况下，在局部变量值上的不一致是无关紧要的，然而在有些情况下却是重要的。附录H给出了一些精确的条件来定义一些静态（也就是编译时可计算的）条件，在这些条件下能够保证局部变量的值在复合序列被计算后具有一致的视图。如果满足了这些条件，那么局部变量被称为流出了复合序列。局部变量流的一个直观描述如下：

  1. 在并行线程上赋值的变量不能在同属线程中访问。例如：

Copy Code
sequence s4;
    int x;
    (a ##1 b, (x = data) ##1 c) or (d ##1 (e==x)); // 非法的
endsequence

  2. 对于or操作的情况，当且仅当一个局部变量流出每一个操作数序列的时候，这个局部变量才流出复合序列。如果局部变量在复合序列启动之前没有被赋值并且它仅在其中的一个操作数序列被赋值，那么它不会流出复合序列。
  3. 一个匹配其操作数序列的or操作的一个操作数的每一个线程都作为一个独立的线程执行，并携带它自己的最新赋值到流出复合序列的局部变量。这些线程不必在局部变量上具有一致的计算结果。例如：

Copy Code
sequence s5;
    int x,y;
    ((a ##1 b, x = data, y = data1 ##1 c)
    or (d ##1 `true, x = data ##0 (e==x))) ##1 (y==data2);
    // 非法的，因为y没有在交集中
endsequence

sequence s6;
    int x,y;
    ((a ##1 b, x = data, y = data1 ##1 c)
    or (d ##1 `true, x = data ##0 (e==x))) ##1 (x==data2);
    // 合法的，因为x位于交集中
endsequence

  4. 对于and和intersect操作的情况，从至少一个操作数流出的局部变量应该从复合序列流出，除非它被阻塞。如果下列条件中的一个条件成立，那么一个局部变量会被阻塞：
    1. 局部变量在复合序列的每一个操作数中或者从复合序列的每一个操作数流出时被赋值。或者，
    2. 局部变量被阻塞而不能从至少一个操作数序列中流出。
流出复合序列的一个局部变量的值是最后所赋的值。在复合序列的计算结束的时候两个操作数的线程被合并成一个。

Copy Code
sequence s7;
    int x,y;
    ((a ##1 b, x = data, y = data1 ##1 c)
    and (d ##1 `true, x = data ##0 (e==x))) ##1 (x==data2);
    // 非法的，因为x对于两个线程是共用的
endsequence

sequence s8;
    int x,y;
    ((a ##1 b, x = data, y = data1 ##1 c)
    or (d ##1 `true, x = data ##0 (e==x))) ##1 (y==data2);
    // legal since y is in the difference
endsequence
Group

第十七章 断言

链接
第十七章 断言


17.9 在一个序列匹配时调用子程序

链接
第十七章 断言
SystemVerilog 3.1a语言参考手册
17.9 在一个序列匹配时调用子程序
第十七章 断言

任务、任务方法、void函数、void函数方法以及系统任务可以在一个序列成功匹配的结束处调用。子程序调用，例如局部变量赋值，出现在紧跟着序列的以逗号分割的列表中。子程序调用被称为附加到序列。序列以及之后的列表以括号包围。

Copy Code
sequence_expr ::=         // 引用自附录A.2.10
    ...
  | (expression_or_dist{, sequence_match_item }) [boolean_abbrev]
  | (sequence_expr{, sequence_match_item}) [sequence_abbrev]
    ...

sequence_match_item ::=
    operator_assignment
  | inc_or_dec_expression
  | subroutine_call

语法17-13 — 序列中子程序调用的语法（摘录自附录A）

例如：

Copy Code
sequence s1;
    logic v, w;
    (a, v = e) ##1
    (b[->1], w = f, $display("b after a with v = %h, w = %h\n", v, w));
endsequence

上面的例子定义了一个序列s1，它在一次a出现后第一次出现b的时候匹配。在匹配的时候，执行系统任务$display来写入一条消息，它声明这次匹配并显示赋给局部变量v和w的值。

所有被附加到一个序列的子程序调用均在序列的每一次成功匹配处执行。对于每一次成功的匹配，附加调用以它们在列表中出现的顺序调用。与一个动作块一样，子程序调用在Reactive区域调度。

一个附加到了一个序列的子程序调用的每一个参数必须或者作为一个输入通过值传递，或者通过引用传递（ref或const ref；参见10.4.2节）。通过值传递的实参表达式使用底层变量的采样值并且与用来计算序列匹配的变量值一致。

局部变量可以被传递到附加到了一个序列的子程序调用。任何流出序列或者在紧跟序列的列表中但在子程序调用之前进行赋值的局部变量都可以用在调用的实参表达式中。如果一个局部变量出现在了一个实参表达式中，那么参数必须通过值传递。

Group

第十七章 断言

链接
第十七章 断言


17.10 系统函数

链接
第十七章 断言
SystemVerilog 3.1a语言参考手册
17.10 系统函数
第十七章 断言

断言一般被用来计算一个设计实现的某些特定属性，例如一个特定的信号是否为“热点（one-hot）”。SystemVerilog中包含下列系统函数来促进这些基本的断言功能：

  • $onehot(<expression>) ：如果表达式中只有一位为高，那么返回“真”。
  • $onehot0(<expression>) ：如果表达式中至少有一位为高，那么返回“真”。
  • $isunknown(<expression>) ：如果表达式任何一位为X或Z，那么返回“真”，等价于：^<expression> === 'bx。
所有上述的系统函数都具有一个bit类型的返回值。1'b1的返回值指示“真”，1'b0的返回值指示“假”。

为布尔表达式提供的另外一个有用的函数是$countones，它可以计算一个位向量表达式中1的数目。

Copy Code
$countones(expression)

值为X和Z的位不会被计数到1的数目。

Group

第十七章 断言

链接
第十七章 断言


17.11 声明特性

链接
第十七章 断言, 主题
SystemVerilog 3.1a语言参考手册
17.11 声明特性
第十七章 断言 | 主题

一个特性定义了设计的一个行为。一个特性可以作为一个假设、一个检查器或者一个覆盖率规范被用于验证。为了将这种行为用于验证，必须使用一个断言、假设或者覆盖语句。一个特性声明本身不会产生任何结果。

一个特性可以在下列结构中声明：

  • 一个模块
  • 一个接口
  • 一个程序
  • 一个时钟控制块
  • 一个包
  • 一个编译单元作用域
为了声明一个特性，我们可以使用如下所示的property结构：

Copy Code
concurrent_assertion_item_declaration ::=           // 引用自附录A.2.10
    property_declaration
    ...

property_declaration ::=
    property property_identifier[([list_of_formals])];
        {assertion_variable_declaration}
        property_spec;
    endproperty [: property_identifier]

list_of_formals ::= formal_list_item{, formal_list_item}

property_spec ::=
    [clocking_event] [disable iff(expression_or_dist)] property_expr

property_expr ::=
    sequence_expr
  | (property_expr)
  | not property_expr
  | property_expr or property_expr
  | property_expr and property_expr
  | sequence_expr |-> property_expr
  | sequence_expr |=> property_expr
  | if (expression_or_dist) property_expr [else property_expr]
  | property_instance
  | clocking_event property_expr

assertion_variable_declaration ::=
    data_type list_of_variable_identifiers;

property_instance::=
    ps_property_identifier[([actual_arg_list])]

语法17-14 — property结构的语法（摘录自附录A）

与序列声明一样，一个特性在声明的时候可以带有可选的形式参数。当一个特性被实例化的时候，实参可以被传递到特性。通过使用实参替代形参，实参使得特性得到了扩展。语义检查被执行医确保使用实参扩展的特性是合法的。

特性的计算结果要么为“真”要么为“假”。SystemVerilog中具有七种类型的特性：序列、否定、析取（逻辑和）、合取（逻辑积）、if...else、蕴含、实例化。

1) 当且仅当序列没有空匹配的时候，作为序列的特性才计算成“真”。有可能具有空匹配的序列不允许作为特性使用。因为当且仅当具有第一次匹配的时候才具有一次匹配，这样的一个特性的计算与隐含地传递它的sequence_expr到first_match(sequence_expr)相同。只要能够确定sequence_expr的一次匹配，特性的计算结果就被认为是“真”，并且对于该次计算尝试不要求其它的匹配。

2) 如果一个特性具有下列的构成，那么它是一个否定。

Copy Code
not property_expr

对于该特性的每一次计算尝试，都具有一个property_expr的计算尝试。关键字not指出特性的计算返回底层的 property_expr的计算结果的“非”。因此，如果property_expr计算成“真”，那么not property_expr计算为“假”；如果property_expr计算成“”，那么property_expr计算成“真”。

3) 如果一个特性具有如下的构成，那么它就是一个析取。

Copy Code
property_expr1 or property_expr2

当且仅当property_expr1和property_expr2至少有一个被计算成“真”特性才被计算成“真”。

4) 如果一个特性具有如下的格式，那么它就是一个合取。

Copy Code
property_expr1 and property_expr2

当且仅当property_expr1和property_expr2都计算为“真”的时候该特性才被计算成“真”。

5) 如果一个特性具有或者

Copy Code
if (expression_or_dist)
    property_expr1

或者

Copy Code
if (expression_or_dist)
    property_expr1
else
    property_expr2

的构成，那么它就是一个if...else。

当且仅当或者expression_or_dist计算成“假”或者property_expr1计算成“真”的时候第一种格式的特性才被计算成“真”。对于第二种格式的特性，当且仅当expression_or_dist计算成“真”并且property_expr1计算成“真”，或者expression_or_dist计算成“假”并且property_expr2计算成“真”的时候它才被计算成“真”。

6) 如果一个特性或者具有

Copy Code
sequence_expr |-> property_expr

或者具有

Copy Code
sequence_expr |=> property_expr

的格式，那么它就是一个蕴含。

有关蕴含的含义将在17.11.1节中讨论。

7) 一个命名特性的实例可以被用作property_expr或者property_spec。通常，如果命名特性体property_spec能够被实例所替代，使用实参替代形式参数并产生一个合法的property_expr或property_spec，并忽略局部变量声明，那么这个实例就是合法的。因此，例如，如果一个命名特性的实例被用作任意特性构建操作符的一个property_expr操作数，那么这个命名特性就不需要具有一个disable iff子句。类似地，当一个命名特性在一个还调用了其它时钟事件的property_expr或property_spec中实例化的时候，这个命名特性中的时钟事件必须符合多时钟支持的规则。

下面的表格按从高优先级到低优先级的顺序列出了特性操作符，并显示了非一元操作符的关联性。

表17-2：特性操作符的优先级和关联性

SystemVerilog特性操作符 | 关联性
not | ----
and | 左
or | 左
if...else | 右
|-> |=> | 右

一条disable iff子句可以被附加到一个property_expr以便产生一个property_spec。

Copy Code
disable iff (expression_or_dist) property_expr

disable iff表达式被称为复位表达式。disable iff子句允许指定异步复位。对于property_spec的一次计算，具有一个底层property_expr的计算。如果在计算完成之前复位表达式变为“真”，那么propterty_spec的整个计算都为“真”。否则，property_spec的计算与property_expr的计算结果相同。对于property_spec的不同的计算尝试，复位表达式都被独立地检测。显式地或者通过实例中的特性实现disable iff子句的嵌套是不被允许的。

Group

第十七章 断言

主题
主题
描述
17.11.1 蕴含
蕴含结构指出一个特性检查是在一个有序前项匹配的基础上有条件地执行的。
17.11.2 特性的例子
下面的例子演示了特性的格式。
17.11.3 递归特性
SystemVerilog允许使用递归的特性。如果一个命名特性的声明调用了其本身的一个实例，那么这个命名特性是递归的。递归提供了一种灵活的框架来对特性进行编码以便作为正在进行的假设、检查器或覆盖率监视器使用。

例如：
17.11.4 有限长度与无限长度行为
The formal semantics in Annex H defines whether a given property holds on a given behavior. How the outcome of this evaluation relates to the design depends on the behavior that was analyzed. In dynamic verification, only behaviors that are finite in length are considered. In such a case, SystemVerilog defines four levels of satisfaction of a property:

Holds strongly:
  • no bad states have been seen
  • all future obligations have been met
  • the property will hold on any extension of the path
Holds (but does not hold strongly):
  • no bad states have been seen
  • all future obligations have been met... more
17.11.5 Non-degeneracy
It is possible to define sequences that can never be matched. For example:
链接
第十七章 断言, 主题


17.11.1 蕴含

链接
17.11 声明特性
SystemVerilog 3.1a语言参考手册
17.11.1 蕴含
17.11 声明特性

蕴含结构指出一个特性检查是在一个有序前项匹配的基础上有条件地执行的。

Copy Code
property_expr ::=            // 引用自附录A.2.10
    ...
  | sequence_expr |-> property_expr
  | sequence_expr |=> property_expr

语法17-15 — 蕴含语法（摘录自附录A）

上面的子句可以用于一个表达式的预处理监视，并允许将其使用在特性级。蕴含的结果要么为“真”要么为“假”。左侧操作数sequence_expr被称为前项，而右侧的操作数property_expr则被称为后项。

对于|->蕴含，我们需要注意以下几点：

  • 从一个指定的起始点开始，先项sequence_expr可以具有0个、一个、或多个成功的匹配。
  • 如果从一个指定的起始点开始没有前项sequence_expr的匹配，那么从这个起始点开始的蕴含的计算会无意义地成功并且返回“真”。
  • 对于前项sequence_expr的每一次成功匹配，后项property_expr会被单独计算。前项sequence_expr匹配的结束点是后项property_expr计算的起始点。
  • 从一个指定的起始点开始，当且仅当起始于这个起始点的前项sequence_expr匹配，并且起始于前项匹配的结束点的后项property_expr成功匹配并返回“真”的时候，蕴含的计算才会成功并返回“真”。
SystemVerilog提供了两种形式的蕴含：交迭的蕴含使用|->操作符；非交迭的蕴含使用|=>操作符。对于交迭的蕴含，如果前项sequence_expr具有一次匹配，那么该次匹配的结束点即为后项property_expr计算的起始点。对于非交迭的蕴含，后项property_expr计算的起始点位于sequence_expr匹配的结束点之后的那个时钟标记。因此：

Copy Code
sequence_expr |=> property_expr

等价于：

Copy Code
sequence_expr ##1 `true |-> property_expr

在多时钟序列和特性中使用蕴含的情况将在17.12节中详细解释。

下面的例子演示了一个总线操作，在这个例子中数据从一个主设备传输到一个从设备。当总线进入到一个数据传输阶段的时候，可能具有多个数据阶段以便传输一个数据块。对于数据传输阶段，如果在时钟信号的任一上升沿irdy有效并且trdy或stop信号有效，那么一个数据阶段结束。注意，这里的有效指的是信号的值为“低”。一个数据阶段的结束可以使用下面的方式表达：

Copy Code
property data_end;
    @(posedge mclk)
        data_phase |-> ((irdy==0) && ($fell(trdy) || $fell(stop)));
endproperty

每次当一个数据阶段为“真”的时候，我们识别出了一个data_phase的匹配。在时钟标记6处的计算尝试在图17-13中演示。图中所显示的信号值是相对于时钟的采样值。在时钟标记6处，data_end为“真”，因为stop信号变为有效同时irdy信号也是有效的。

图 17-13 — 有条件的序列匹配

在另外一个例子中，data_end_exp被用来确保frame在data_end_exp出现后的两个时钟标记内无效（值为“高”）。更进一步，它还要求在frame变为无效后的一个时钟标记上irdy无效（值为“高”）。

可以用来表达这个条件的一个特性如下所示：

Copy Code
`define data_end_exp (data_phase && ((irdy==0)&&($fell(trdy)||$fell(stop))))
property data_end_rule1;
    @(posedge mclk)
        `data_end_exp |-> ##[1:2] $rose(frame) ##1 $rose(irdy);
endproperty

特性data_end_rule1首先在每一个时钟标记上计算data_end_exp以测试它的值是否为“真”。如果它的值为“假”，那么对于data_end_rule1的计算尝试被认为是“真”。否则会计算紧随其后的序列。

Copy Code
##[1:2] $rose(frame) ##1 $rose(irdy)

上面的序列在接下来的两个时钟标记内寻找frame信号的上升沿。在frame反转为高后，irdy信号也必须在一个时钟标记之后反转为高。图17-14演示了在时钟标记6处的计算尝试。`data_end_exp在时钟标记6处被确认。接下来，frame信号在时钟标记7处反转为高。由于它满足由[1:2]所施加的约束，所以它满足这个序列并且继续进行下一步的计算。在时钟标记8处，irdy信号被计算。信号irdy在时钟标记8处跃变为高，对于开始于时钟标记6处的计算尝试，它完全满足序列规范。

图17-14 — 有条件的序列

通常，断言与一些先决条件相关联，因此所执行的检查也仅仅发生在某些特性的条件下。正像前一个例子所看到的那样，|->操作符提供了这种能力来说明在计算它们的结果特性之前序列必须满足的先决条件。下面的例子修改了前一个例子，通过删除了结果的先决条件，我们可以看到它对断言结果的影响。如图17-15所示。

Copy Code
property data_end_rule2;
    @(posedge mclk)
        ##[1:2] $rose(frame) ##1 $rose(irdy);
endproperty

图17-15 — 没有先决条件产生的结果

上述特性在每一个时钟标记处进行计算。对于时钟标记1处的计算，在时钟标记1或时钟标记2处没有出现frame信号的上升沿，所以特性在时钟标记1失败。类似的，在时钟标记2、3和4处特性也是失败的。对于起始于时钟标记5和6处的计算尝试，时钟标记7处发生的frame信号的上升沿使得特性能够得到进一步的检查。根据规范，序列在时钟标记8处结束，对于起始于5和6处的计算尝试会产生一次匹配。因为$rose(frame)没有再次发生，所以所有后续的序列匹配计算尝试都是失败的。

从图17-15中可以看出，将检查的先决条件‘data_end_exp从断言中删除会导致与验证目标不相关的失败。从确认的立场来看，确定先决条件并用其过滤掉不恰当或无关的条件是非常重要的。

蕴含操作中前项是一个序列的例子如下所示：

Copy Code
(a ##1 b ##1 c) |-> (d ##1 e)

如果序列(a ##1 b ##1 c)匹配，那么序列(d ##1 e)也必须匹配。换句话说，如果序列(a ##1 b ##1 c)没有匹配，那么结果为“真”。

蕴含的另外一个例子如下：

Copy Code
property p16;
    (write_en & data_valid) ##0
    (write_en && (retire_address[0:4]==addr)) [*2] |->
    ##[3:8] write_en && !data_valid &&(write_address[0:4]==addr);
endproperty

作为一种选择，这个特性可以被编码成一个嵌套的蕴含：

Copy Code
property p16_nested;
    (write_en & data_valid) |->
    (write_en && (retire_address[0:4]==addr)) [*2] |->
    ##[3:8] write_en && !data_valid &&(write_address[0:4]==addr);
endproperty

多时钟序列的蕴含操作将在17.12节中解释。

Group

17.11 声明特性

链接
17.11 声明特性


17.11.2 特性的例子

链接
17.11 声明特性
SystemVerilog 3.1a语言参考手册
17.11.2 特性的例子
17.11 声明特性

下面的例子演示了特性的格式。

Copy Code
property rule1;
    @(posedge clk)
        a |-> b ##1 c ##1 d;
endproperty

property rule2;
    @(clkev)
        disable iff (foo)
            a |-> not(b ##1 c ##1 d);
endproperty

特性rule2对蕴含中后项的(b ##1 c ##1 d)序列取反。clkev为特性指定了时钟。

Copy Code
property rule3;
    @(posedge clk)
        a[*2] |-> ((##[1:3] c) or (d |=> e));
endproperty

Property rule3 says that if a holds and a also held last cycle, then either c must hold at some point 1 to three cycles after the current cycle, or, if d holds in the current cycle, then e must hold one cycle later.

Copy Code
property rule4;
    @(posedge clk)
        a[*2] |-> ((##[1:3] c) and (d |=> e));
endproperty

Property rule4 says that if a holds and a also held last cycle, then c must hold at some point 1 to three cycles after the current cycle, and if d holds in the current cycle, then e must hold one cycle later.

Copy Code
property rule5;
    @(posedge clk)
        a ##1 (b || c)[->1] |->
            if (b)
                (##1 d |-> e)
            else // c
                f;
endproperty

Property rule5 has a followed by the first match of either b or c as its antecedent. The consequent uses if...else to split cases on which of b or c is matched first.

Copy Code
property rule6(x,y);
    ##1 x |-> y;
endproperty

property rule5a;
    @(posedge clk)
        a ##1 (b || c)[->1] |->
            if (b)
                rule6(d,e)
            else // c
                f;
endproperty

特性rule5a等价于rule5，但它使用rule6的一个实例作为一个特性表达式。

一个特性可以可选地为时钟指定一个事件控制。时钟派生和解析的规则将在17.14节中描述。

一个命名特性可以通过引用它的名字来实例化。与SystemVerilog命名约定一致，我们可以使用一个层次化的名字。像序列声明一样，对于在一个特性中使用并且不是特性的形式参数的变量，它们从特性被声明的作用域中进行层次化的解析。

使用多个时钟的特性将在17.12节中描述。

Group

17.11 声明特性

链接
17.11 声明特性


17.11.3 递归特性

链接
17.11 声明特性
SystemVerilog 3.1a语言参考手册
17.11.3 递归特性
17.11 声明特性

SystemVerilog允许使用递归的特性。如果一个命名特性的声明调用了其本身的一个实例，那么这个命名特性是递归的。递归提供了一种灵活的框架来对特性进行编码以便作为正在进行的假设、检查器或覆盖率监视器使用。

例如：

Copy Code
property prop_always(p);
    p and (1'b1 |=> prop_always(p));
endproperty

上述例子是一个递归特性，它表示作为形式参数的特性p必须在每一个周期保持。如果特性p保持的正在进行的需求在一个在序列s中编码的复杂的触发条件之后施加的话，这个例子非常有用。

Copy Code
property p1(s,p);
    s |=> prop_always(p);
endproperty

另外一个例子：

Copy Code
property prop_weak_until(p,q);
    q or (p and (1'b1 |=> prop_weak_until(p,q)));
endproperty

上述的递归特性表示作为形式参数的特性p必须在每一个周期保持直到（但不包括）作为形式参数的特性q保持的第一个周期。尽管作为形式参数的特性q并不要求永远保持。This example is useful if p must hold at every cycle after a complicated triggering condition encoded in sequence s, but the requirement on p is lifted by q:

Copy Code
property p2(s,p,q);
    s |=> prop_weak_until(p,q);
endproperty

More generally, several properties can be mutually recursive. For example

Copy Code
property check_phase1;
    s1 |-> (phase1_prop and (1'b1 |=> check_phase2));
endproperty

property check_phase2;
    s2 |-> (phase2_prop and (1'b1 |=> check_phase1));
endproperty

递归的特性声明具有三个限制。

限制1：The negation operator not cannot be applied to any property expression that instantiates a recursive property. In particular, the negation of a recursive property cannot be asserted or used in defining another property.

Here are examples of illegal property declarations that violate Restriction 1:

Copy Code
property illegal_recursion_1(p);
    not prop_always(not p);
endproperty

property illegal_recursion_2(p);
    p and (1'b1 |=> not illegal_recursion_2(p));
endproperty

限制2：The operator disable iff cannot be used in the declaration of a recursive property. This restriction is consistent with the restriction that disable iff cannot be nested.

Here is an example of an illegal property declaration that violates Restriction 2:

Copy Code
property illegal_recursion_3(p);
    disable iff (b)
        p and (1'b1 |=> illegal_recursion_3(p));
endproperty

The intent of illegal_recursion_3 can be written legally as

Copy Code
property legal_3(p);
    disable iff (b) prop_always(p);
endproperty

since legal_3 is not a recursive property.

限制3：If p is a recursive property, then, in the declaration of p, every instance of p must occur after a positive advance in time. In the case of mutually recursive properties, all recursive instances must occur after positive advances in time.

Here is an example of an illegal property declaration that violates Restriction 3:

Copy Code
property illegal_recursion_4(p);
    p and (1’b1 |-> illegal_recursion_4(p));
endproperty

If this form were legal, the recursion would be stuck in time, checking p over and over again at the same cycle.

Recursive properties can represent complicated requirements, such as those associated with varying numbers of data beats, out-of-order completions, retries, etc. Here is an example of using a recursive property to check complicated conditions of this kind.

EXAMPLE: Suppose that write data must be checked according to the following conditions:

  • Acknowledgment of a write request is indicated by the signal write_request together with write_request_ack. When a write request is acknowledged, it gets a 4-bit tag, indicated by signal write_reqest_ack_tag. The tag is used to distinguish data beats for multiple write transactions in flight at the same time.
  • It is understood that distinct write transactions in flight at the same time must be given distinct tags. For simplicity, this condition is not a part of what is checked in this example.
  • Each write transaction can have between 1 and 16 data beats, and each data beat is 8 bits. There is a model of the expected write data that is available at acknowledgment of a write request. The model is a 128-bit vector. The most significant group of 8 bits represents the expected data for the first beat, the next group of 8 bits represents the expected data for the second beat (if there is a second beat), and so forth.
  • Data transfer for a write transaction occurs after acknowledgment of the write request and, barring retry, ends with the last data beat. The data beats for a single write transaction occur in order.
  • A data beat is indicated by the data_valid signal together with the signal data_valid_tag to determine the relevant write transaction. The signal data is valid with data_valid and carries the data for that beat. The data for each beat must be correct according to the model of the expected write data.
  • The last data beat is indicated by signal last_data_valid together with data_valid and data_valid_tag. For simplicity, this example does not represent the number of data beats and does not check that last_data_valid is signaled at the correct beat.
  • At any time after acknowledgement of the write request, but not later than the cycle after the last data beat, a write transaction can be forced to retry. Retry is indicated by the signal retry together with signal retry_tag to identify the relevant write transaction. If a write transaction is forced to retry, then its current data transfer is aborted and the entire data transfer must be repeated. The transaction does not rerequest and its tag does not change.
  • There is no limit on the number of times a write transaction can be forced to retry.
  • A write transaction completes the cycle after the last data beat provided it is not forced to retry in that cycle.
Here is code to check these conditions:

Copy Code
property check_write;
    logic [0:127] expected_data; // local variable to sample model data
    logic [3:0] tag; // local variable to sample tag

    disable iff (reset)
    (
        write_request && write_request_ack,
        expected_data = model_data,
        tag = write_request_ack_tag
    )
    |=>
        check_write_data_beat(expected_data, tag, 4’h0);
endproperty

property check_write_data_beat
(
    expected_data, // [0:127]
    tag, // [3:0]
    i // [3:0]
);

    first_match
    (
        ##[0:$]
        (
            (data_valid && (data_valid_tag == tag))
            ||
            (retry && (retry_tag == tag))
        )
    )
    |->
    (
       (
           (data_valid && (data_valid_tag == tag))
           |->
           (data == expected_data[i*8+:8])
       )
       and
       (
           if (retry && (retry_tag == tag))
           (
               1’b1 |=> check_write_data_beat(tag, expected_data, 4’h0)
           )
           else if (!last_data_valid)
           (
               1’b1 |=> check_write_data_beat(tag, expected_data, i+4’h1)
           )
           else
           (
               ##1 (retry && (retry_tag == tag))
               |=>
               check_write_data_beat(tag, expected_data, 4’h0)
           )
       )
    );
endproperty
Group

17.11 声明特性

链接
17.11 声明特性


17.11.4 有限长度与无限长度行为

链接
17.11 声明特性
SystemVerilog 3.1a语言参考手册
17.11.4 有限长度与无限长度行为
17.11 声明特性

The formal semantics in Annex H defines whether a given property holds on a given behavior. How the outcome of this evaluation relates to the design depends on the behavior that was analyzed. In dynamic verification, only behaviors that are finite in length are considered. In such a case, SystemVerilog defines four levels of satisfaction of a property:

Holds strongly:

  • no bad states have been seen
  • all future obligations have been met
  • the property will hold on any extension of the path
Holds (but does not hold strongly):
  • no bad states have been seen
  • all future obligations have been met
  • the property may or may not hold on a given extension of the path
Pending:
  • no bad states have been seen
  • future obligations have not been met
  • the property may or may not hold on a given extension of the path
Fails:
  • a bad state has been seen
  • future obligations may or may not have been met
  • the property will not hold on any extension of the path

Group

17.11 声明特性

链接
17.11 声明特性


17.11.5 Non-degeneracy

链接
17.11 声明特性
SystemVerilog 3.1a语言参考手册
17.11.5 Non-degeneracy
17.11 声明特性

It is possible to define sequences that can never be matched. For example:

Copy Code
(1’b1) intersect(1’b1 ##1 1’b1)

It is also possible to define sequences that admit only empty matches. For example:

Copy Code
1’b1[*0]

A sequence that admits no match or that admits only empty matches is called degenerate. A sequence that admits at least one non-empty match is called non-degenerate. A more precise definition of non-degeneracy is given in Annex H.

The following restrictions apply:

  1. Any sequence that is used as a property must be non-degenerate and must not admit any empty match.
  2. Any sequence that is used as the antecedent of an overlapping implication (|->) must be non-degenerate.
  3. Any sequence that is used as the antecedent of a non-overlapping implication (|=>) must admit at least one match. Such a sequence can admit only empty matches.

The reason for these restrictions is that the use of degenerate sequences the forbidden ways results in counterintuitive property semantics, especially when the property is combined with a disable iff clause.

Group

17.11 声明特性

链接
17.11 声明特性


17.12 多时钟的支持

链接
第十七章 断言, 主题
SystemVerilog 3.1a语言参考手册
17.12 多时钟的支持
第十七章 断言 | 主题

多时钟序列和特性可以使用下列的语法说明。

Group

第十七章 断言

主题
主题 | 描述
17.12.1 多时钟控制序列 | Multiply-clocked sequences are built by concatenating singly-clocked subsequences using the single-delay concatenation operator ##1. This operator is non-overlapping and synchronizes between the clocks of the two sequences. The single delay indicated by ##1 is understood to be from the endpoint of the first sequence, which occurs at a tick of the first clock, to the nearest strictly subsequent tick of the second clock, where the second sequence begins. For example, consider
17.12.2 多时钟控制特性 | As in the case of singly-clocked properties, the result of evaluating a multiply-clocked property is either true or false. Multiply-clocked properties can be formed in a number of ways. Multiply-clocked sequences are themselves multiply-clocked properties. For example,
17.12.3 时钟流 | Throughout this subsection, c, d denote clocking event expressions and v, w, x, y, z denote sequences with no clocking events. Clock flow allows the scope of a clocking event to extend in a natural way through various parts of multiplyclocked sequences and properties and reduces the number of places at which the same clocking event must be specified. Intuitively, clock flow provides that in a multiply-clocked sequence or property the scope of a clocking event flows left-to-right across linear operators (e.g., repetition, concatenation, negation, implication) and distributes to the operands of branching operators (e.g., conjunction, disjunction, intersection, if...else) until... more
17.12.4 例子 | The following are examples of multiple-clock specifications:
17.12.5 在多时钟语境中检测和使用一个序列的结束点 | To detect the end point of a sequence when the clock of the source sequence is different than the destination sequence, method matched on the source sequence is used. The end point of a sequence is reached whenever there is a match on its expression. The occurrence of the end point can be tested in any sequence expression by using the method ended when the clocks of the source and destination sequences are the same, while method matched is used when the clocks are different. The syntax of the matched method is:
链接
第十七章 断言, 主题


17.12.1 多时钟控制序列

链接
17.12 多时钟的支持
SystemVerilog 3.1a语言参考手册
17.12.1 多时钟控制序列
17.12 多时钟的支持

Multiply-clocked sequences are built by concatenating singly-clocked subsequences using the single-delay concatenation operator ##1. This operator is non-overlapping and synchronizes between the clocks of the two sequences. The single delay indicated by ##1 is understood to be from the endpoint of the first sequence, which occurs at a tick of the first clock, to the nearest strictly subsequent tick of the second clock, where the second sequence begins.

For example, consider

Copy Code
@(posedge clk0) sig0 ##1 @(posedge clk1) sig1

A match of this sequence starts with a match of sig0 at posedge clk0. Then ##1 moves the time to the nearest strictly subsequent posedge clk1, and the match of the sequence ends at that point with a match of sig1. If clk0 and clk1 are not identical, then the clocking event for the sequence changes after ##1. If clk0 and clk1 are identical, then the clocking event does not change after ##1 and the above sequence is equivalent to the singly-clocked sequence

Copy Code
@(posedge clk0) sig0 ##1 sig1

When concatenating differently-clocked sequences, the maximal singly-clocked subsequences are required to admit only non-empty matches. Thus, if s1, s2 are sequence expressions with no clocking events, then the multiply-clocked sequence

Copy Code
@(posedge clk1) s1 ##1 @(posedge clk2) s2

is legal only if neither s1 nor s2 can match the empty word. The clocking event posedge clk1 applies throughout the match of s1, while the clocking event posedge clk2 applies throughout the match of s2. Since the match of s1 is non-empty, there is an end point of this match at posedge clk1. The ##1 synchronizes between this end point and the first occurrence of posedge clk2 strictly after it. That occurrence of posedge clk2 is the start point of the match of s2.

The restriction that maximal singly-clocked subsequences not match the empty word ensures that any multiply-clocked sequence has well-defined starting and ending clocking events and well-defined clock changes. If clk1 and clk2 are not identical, then the following sequence

Copy Code
@(posedge clk0) sig0 ##1 @(posedge clk1) sig1[*0:1]

is illegal because of the possibility of an empty match of sig1[*0:1], which would make ambiguous whether the ending clocking event is posedge clk0 or posedge clk1.

Differently-clocked or multiply-clocked sequence operands cannot be combined with any sequence operators other than ##1. For example, if clk1 and clk2 are not identical, then the following are illegal:

Copy Code
@(posedge clk1) s1 ##0 @(posedge clk2) s2
@(posedge clk1) s1 ##2 @(posedge clk2) s2
@(posedge clk1) s1 intersect @(posedge clk2) s2
Group

17.12 多时钟的支持

链接
17.12 多时钟的支持


17.12.2 多时钟控制特性

链接
17.12 多时钟的支持
SystemVerilog 3.1a语言参考手册
17.12.2 多时钟控制特性
17.12 多时钟的支持

As in the case of singly-clocked properties, the result of evaluating a multiply-clocked property is either true or false. Multiply-clocked properties can be formed in a number of ways.

Multiply-clocked sequences are themselves multiply-clocked properties. For example,

Copy Code
@(posedge clk0) sig0 ##1 @(posedge clk1) sig1

is a multiply-clocked property. If a multiply-clocked sequence is evaluated as a property starting at some point, the evaluation returns true if and only if there is a match of the multiply-clocked sequence beginning at that point.

The boolean property operators (not, and, or) can be used freely to combine singly- and multiply-clocked properties. The meanings of the boolean property operators are the usual ones, just as in the case of singlyclocked properties. For example,

Copy Code
(@(posedge clk0) sig0) and (@(posedge clk1) sig1)

is a multiply-clocked property, but it is not a multiply-clocked sequence. This property evaluates to true at a point if and only if the two sequences

Copy Code
@(posedge clk0) sig0

and

Copy Code
@(posedge clk1) sig1

both have matches beginning at the point.

The non-overlapping implication operator |=> can be used freely to create a multiply-clocked property from an antecedent sequence and a consequent property that are differently- or multiply-clocked. The meaning of multiply-clocked non-overlapping implication is similar to that of singly-clocked non-overlapping implication. For example, if s0, s1 are sequences with no clocking event, then in

Copy Code
@(posedge clk0) s0 |=> @(posedge clk1) s1

|=> synchronizes between posedge clk0 and posedge clk1. Starting at the point at which the implication is being evaluated, for each match of s0 clocked by clk0, time is advanced from the end point of the match to the nearest strictly future occurrence of posedge clk1, and from that point there must exist a match of s1 clocked by clk1.

The non-overlapping implication operator |=> can synchronize between the ending clock event of its antecedent and several leading clock events for subproperties of its consequent. For example, in

Copy Code
@(posedge clk0) s0 |=> (@(posedge clk1) s1) and (@(posedge clk2) s2)

|=> synchronizes between posedge clk0 and both posedge clk1 and posedge clk2.

Since synchronization between distinct clocks always requires strict advance of time, the two property building operators that require special care with multiple clocks are the overlapping implication |-> and if/if...else.

Since |-> overlaps the end of its antecedent with the beginning of its consequent, the clock for the end of the antecedent must be the same as the clock for the beginning of the consequent. For example, if clk0 and clk1 are not identical and s0, s1, s2 are sequences with no clocking events, then

Copy Code
@(posedge clk0) s0 |-> @(posedge clk1) s1 ##1 @(posedge clk2) s2

is illegal, but

Copy Code
@(posedge clk0) s0 |-> @(posedge clk0) s1 ##1 @(posedge clk2) s2

is legal.

The if/if...else operators overlap the test of the boolean condition with the beginning of the if clause property and, if present, the else clause property. Therefore, whenever using if or if...else, the if and else clause properties must begin on the same clock as the test of the boolean condition. For example, if clk0 and clk1 are not identical and s0, s1, s2 are sequences with no clocking events, then

Copy Code
@(posedge clk0) if (b) @(posedge clk0) s1

is legal, but

Copy Code
@(posedge clk0) if (b) @(posedge clk0) s1 else @(posedge clk1) s2

is illegal because the else clause property begins on a different clock than the if condition.

Group

17.12 多时钟的支持

链接
17.12 多时钟的支持


17.12.3 时钟流

链接
17.12 多时钟的支持
SystemVerilog 3.1a语言参考手册
17.12.3 时钟流
17.12 多时钟的支持

Throughout this subsection, c, d denote clocking event expressions and v, w, x, y, z denote sequences with no clocking events.

Clock flow allows the scope of a clocking event to extend in a natural way through various parts of multiplyclocked sequences and properties and reduces the number of places at which the same clocking event must be specified.

Intuitively, clock flow provides that in a multiply-clocked sequence or property the scope of a clocking event flows left-to-right across linear operators (e.g., repetition, concatenation, negation, implication) and distributes to the operands of branching operators (e.g., conjunction, disjunction, intersection, if...else) until it is replaced by a new clocking event.

For example,

Copy Code
@(c) x |=> @(c) y ##1 @(d) z

can be written more simply as

Copy Code
@(c) x |=> y ##1 @(d) z

because clock c is understood to flow across |=>.

Clock flow eliminates the need to write clocking events in positions where the clock is not allowed to change. For example,

Copy Code
@(c) x |-> @(c) y ##1 @(d) z

can be written as

Copy Code
@(c) x |-> y ##1 @(d) z

to reinforce the restriction that the clock not change across |->. Similarly,

Copy Code
@(c) if (b) @(c) w ##1 @(d) x else @(c) y ##1 @(d) z

can be written as

Copy Code
@(c) if (b) w ##1 @(d) x else y ##1 @(d) z

to reinforce the restriction that the clock not change from the boolean condition b to the beginnings of the if and else clause properties.

Clock flow also makes the adjointness relationships between concatenation and implication clean for multiplyclocked properties:

Copy Code
@(c) x ##1 y |=> @(d) z

is equivalent to

Copy Code
@(c) x |=> y |=> @(d) z

and

Copy Code
@(c) x ##0 y |=> @(d) z

is equivalent to

Copy Code
@(c) x |-> y |=> @(d) z

The scope of a clocking event flows into parenthesized subexpressions and, if the subexpression is a sequence, also flows left-to-right across the parenthesized subexpression. However, the scope of a clocking event does not flow out of enclosing parentheses.

For example, in

Copy Code
@(c) w ##1 (x ##1 @(d) y) |=> z

w, x, z are clocked at c and y is clocked at d. Clock c flows across ##1, across the parenthesized subsequence (x ##1 @(d) y), and across |=>. Clock c also flows into the parenthesized subsequence, but it does not flow through @(d). Clock d does not flow out of its enclosing parentheses.

As another example, in

Copy Code
@(c) v |=> (w ##1 @(d) x) and (y ##1 z)

v, w, y, z are clocked at c and x is clocked at d. Clock c flows across |=>, distributes to both operands of the and (which is a property conjunction due to the multiple clocking), and flows into each of the parenthesized subexpressions. Within (w ##1 @(d) x), c flows across ##1 but does not flow through @(d). Clock d does not flow out of its enclosing parentheses. Within (y ##1 z), c flows across ##1.

Similarly, the scope of a clocking event flows into an instance of a named sequence or property, and, if the instance is a sequence, also flows left-to-right across the instance. However, a clocking event in the declaration of a sequence or property does not flow out of an instance of that sequence or property.

Note that juxtaposing two clocking events nullifies the first of them:

Copy Code
@(d) @(c) x

is equivalent to

Copy Code
@(c) x

because the flow of clock d is immediately overridden by clock c.

Group

17.12 多时钟的支持

链接
17.12 多时钟的支持


17.12.4 例子

链接
17.12 多时钟的支持
SystemVerilog 3.1a语言参考手册
17.12.4 例子
17.12 多时钟的支持

The following are examples of multiple-clock specifications:

Copy Code
sequence s1;
    @(posedge clk1) a ##1 b; // single clock sequence
endsequence

sequence s2;
    @(posedge clk2) c ##1 d; // single clock sequence
endsequence

1) multiple-clock sequence

Copy Code
sequence mult_s;
    @(posedge clk) a ##1 @(posedge clk1) s1 ##1 @(posedge clk2) s2;
endsequence

2) property with a multiple-clock sequence

Copy Code
property mult_p1;
    @(posedge clk) a ##1 @(posedge clk1) s1 ##1 @(posedge clk2) s2;
endproperty

3) property with a named multiple-clock sequence

Copy Code
property mult_p2;
    mult_s;
endproperty

4) property with multiple-clock implication

Copy Code
property mult_p3;
    @(posedge clk) a ##1 @(posedge clk1) s1 |=> @(posedge clk2) s2;
endproperty

5) property with named sequences at different clocks. In this case, if s1 contains a clock, then it must be identical to (posedge clk1). Similarly, if s2 contains a clock, it must be identical to (posedge clk2).

Copy Code
property mult_p5
    @(posedge clk1) s1 |=> @(posedge clk2) s2;
endproperty

6) property with implication, where antecedent and consequent are named multi-clocked sequences

Copy Code
property mult_p6;
    mult_s |=> mult_s;
endproperty

7) property using clock flow and overlapped implication:

Copy Code
property mult_p7;
    @(posedge clk) a ##1 b |-> c ##1 @(posedge clk1) d;
endproperty

Here, a, b, and c are clocked at posedge clk.

8) property using clock flow and if...else:

Copy Code
property mult_p8;
    @(posedge clk) a ##1 b |->
    if (c)
        (1 |=> @(posedge clk1) d)
    else
        e ##1 @(posedge clk2) f ;
endproperty

Here, a, b, c, and e are clocked at posedge clk.

Group

17.12 多时钟的支持

链接
17.12 多时钟的支持


17.12.5 在多时钟语境中检测和使用一个序列的结束点

链接
17.12 多时钟的支持
SystemVerilog 3.1a语言参考手册
17.12.5 在多时钟语境中检测和使用一个序列的结束点
17.12 多时钟的支持

To detect the end point of a sequence when the clock of the source sequence is different than the destination sequence, method matched on the source sequence is used. The end point of a sequence is reached whenever there is a match on its expression. The occurrence of the end point can be tested in any sequence expression by using the method ended when the clocks of the source and destination sequences are the same, while method matched is used when the clocks are different.

The syntax of the matched method is:

Copy Code
sequence_instance.matched

matched is a method on a sequence which return true or false. Unlike ended, matched uses synchronization between the two clocks, by storing the result of the source sequence match until the arrival of the first destination clock tick after the match. When method matched is applied, it tests whether the source sequence has reached the end point at that particular point in time. The result of matched does not depend upon the starting point of the source sequence.

Like ended, matched can be used on sequences that have formal arguments.

An example is shown below:

Copy Code
sequence e1(a,b,c);
    @(posedge clk) $rose(a) ##1 b ##1 c ;
endsequence

sequence e2;
    @(posedge sysclk) reset ##1 inst ##1 e1(ready,proc1,proc2).matched [->1]
    ##1 branch_back;
endsequence

In this example, source sequence e1 is evaluated at clock clk, while the destination sequence e2 is evaluated at clock sysclk. In e2, the end point of the instance e1(ready,proc1,proc2) is tested to occur sometime after the occurrence of inst. Notice that method matched only tests for the end point of e1(ready,proc1,proc2) and has no bearing on the starting point of e1(ready,proc1,proc2).

Local variables can be passed into an instance of a named sequence to which matched is applied. The same restrictions apply as in the case of ended. Values of local variables sampled in an instance of a named sequence to which matched is applied will flow out under the same conditions as for ended. See Section 17.8.

As with ended, a sequence instance to which matched is applied can have multiple matches in a single cycle of the destination sequence clock. The multiple matches are treated semantically the same way as matching both disjuncts of an or. In other words, the thread evaluating the destination sequence will fork to account for such distinct local variable valuations.

Group

17.12 多时钟的支持

链接
17.12 多时钟的支持


17.13 并发断言

链接
第十七章 断言, 主题
SystemVerilog 3.1a语言参考手册
17.13 并发断言
第十七章 断言 | 主题

A property on its own is never evaluated for checking an expression. It must be used within a verification statement for this to occur. A verification statement states the verification function to be performed on the property. The statement can be one of the following:

  • assert to specify the property as a checker to ensure that the property holds for the design
  • assume to specify the property as an assumption for the environment
  • cover to monitor the property evaluation for coverage
A concurrent assertion statement can be specified in:
  • an always block or initial block as a statement, wherever these blocks can appear
  • a module
  • an interface
  • a program

Copy Code
procedural_assertion_statement ::=         // from Annex A.6.10
    concurrent_assertion_statement
  | immediate_assert_statement

concurrent_assertion_item ::=             // from Annex A.2.10
    [block_identifier :] concurrent_assertion_statement

concurrent_assertion_statement ::=
    assert_property_statement
  | assume_property_statement
  | cover_property_statement

assert_property_statement::=
    assert property (property_spec) action_block

assume_property_statement::=
    assume property (property_spec);

cover_property_statement::=
    cover property (property_spec) statement_or_null

Syntax 17-16—Concurrent assert construct syntax (excerpt from Annex A)

The assert, assume or cover statements can be referenced by their optional name. A hierarchical name can be used consistent with the SystemVerilog naming conventions. When a name is not provided, a tool shall assign a name to the statement for the purpose of reporting. Assertion control system tasks are described in Section 23.9.

Group

第十七章 断言

主题
主题 | 描述
17.13.1 断言语句 | The assert statement is used to enforce a property as a checker. When the property for the assert statement is evaluated to be true, the pass statements of the action block are executed. Otherwise, the fail statements of the action_block are executed. For example,
17.13.2 假设语句 | The purpose of the assume statement is to allow properties to be considered as assumptions for formal analysis as well as for dynamic simulation tools. When a property is assumed, the tools constrain the environment so that the property holds. For formal analysis, there is no obligation to verify that the assumed properties hold. An assumed property can be considered as a hypothesis to prove the asserted properties. For simulation, the environment must be constrained such that the properties that are assumed shall hold. Like an assert property, an assumed property must be checked and reported if it fails to... more
17.13.3 覆盖语句 | To monitor sequences and other behavioral aspects of the design for coverage, the same syntax is used with the cover statement. The tools can gather information about the evaluation and report the results at the end of simulation. When the property for the cover statement is successful, the pass statements can specify a coverage function, such as monitoring all paths for a sequence. The pass statement shall not include any concurrent assert, assume or cover statement. Coverage results are divided into two: coverage for properties, coverage for sequences. For sequence coverage, the statement appears as:
17.13.4 在过程化代码外部使用并发断言语句 | A concurrent assertion statement can be used outside of a procedural context. It can be used within a module, an interface, or a program. A concurrent assertion statement is an assert, an assume, or a cover statement.Such a concurrent assertion statement uses the always semantics. The following two forms are equivalent:
17.13.5 在过程化代码中嵌入并发断言 | A concurrent assertion statement can also be embedded in a procedural block. For example:
链接
第十七章 断言, 主题


17.13.1 断言语句

链接
17.13 并发断言
SystemVerilog 3.1a语言参考手册
17.13.1 断言语句
17.13 并发断言

The assert statement is used to enforce a property as a checker. When the property for the assert statement is evaluated to be true, the pass statements of the action block are executed. Otherwise, the fail statements of the action_block are executed. For example,

Copy Code
property abc(a,b,c);
    disable iff (a==2) not @clk (b ##1 c);
endproperty
env_prop: assert property (abc(rst,in1,in2)) pass_stat else fail_stat;

When no action is needed, a null statement (i.e.;) is specified. If no statement is specified for else, then $error is used as the statement when the assertion fails.

The action_block shall not include any concurrent assert, assume, or cover statement. The action_block, however, can contain immediate assertion statements.

Note: The pass and fail statements are executed in the Reactive region. The regions of execution are explained in the scheduling semantics section, Section 14.

Group

17.13 并发断言

链接
17.13 并发断言


17.13.2 假设语句

链接
17.13 并发断言
SystemVerilog 3.1a语言参考手册
17.13.2 假设语句
17.13 并发断言

The purpose of the assume statement is to allow properties to be considered as assumptions for formal analysis as well as for dynamic simulation tools. When a property is assumed, the tools constrain the environment so that the property holds.

For formal analysis, there is no obligation to verify that the assumed properties hold. An assumed property can be considered as a hypothesis to prove the asserted properties.

For simulation, the environment must be constrained such that the properties that are assumed shall hold. Like an assert property, an assumed property must be checked and reported if it fails to hold. There is no requirement on the tools to report successes of the assumed properties.

Additionally, for random simulation, biasing on the inputs provides a way to make random choices. An expression can be associated with biasing as shown below

Copy Code
expression dist { dist_list } ; // from Annex A.1.9

Distribution sets and the dist operator are explained in Section 12.4.4.

The biasing feature is only useful when properties are considered as assumptions to drive random simulation. When a property with biasing is used in an assertion or coverage, the dist operator is equivalent to inside operator, and the weight specification is ignored. For example,

Copy Code
a1:assume property @(posedge clk) req dist {0:=40, 1:=60} ;
property proto
    @(posedge clk) req |-> req[*1:$] ##0 ack;
endproperty

This is equivalent to:

Copy Code
a1_assertion:assert property req inside {0, 1} ;
property proto_assertion
    @(posedge clk) req |-> req[*1:$] ##0 ack;
endproperty

In the above example, signal req is specified with distribution in assumption a1, and is converted to an equivalent assertion a1_assertion.

It should be noted that the properties that are assumed must hold in the same way with or without biasing. When using an assume statement for random simulation, the biasing simply provides a means to select values of free variables, according to the specified weights, when there is a choice of selection at a particular time.

Consider an example specifying a simple synchronous request - acknowledge protocol, where variable req can be raised at any time and must stay asserted until ack is asserted. In the next clock cycle both req and ack must be de-asserted.

Properties governing req are:

Copy Code
property pr1;
    @(posedge clk) !reset_n |-> !req; //when reset_n is asserted (0),keep req 0
endproperty

property pr2;
    @(posedge clk) ack |=> !req; // one cycle after ack, req must be de-asserted
endproperty

property pr3;
    @(posedge clk) req |-> req[*1:$] ##0 ack; // hold req asserted until
    // and including ack asserted
endproperty

Properties governing ack are:

Copy Code
property pa1;
    @(posedge clk) !reset_n || !req |-> !ack;
endproperty

property pa2;
    @(posedge clk) ack |=> !ack;
endproperty

When verifying the behavior of a protocol controller which has to respond to requests on req, assertions assert_req1 and assert_req2 should be proven while assuming that statements a1, assume_ack1, assume_ack2 and assume_ack3 hold at all times.

Copy Code
a1:assume property @(posedge clk) req dist {0:=40, 1:=60} ;
assume_ack1:assume property (pr1);
assume_ack2:assume property (pr2);
assume_ack3:assume property (pr3);
assert_req1:assert property (pa1)
    else $display("\n ack asserted while req is still de-asserted");
assert_req2:assert property (pa2)
    else $display("\n ack is extended over more than one cycle");

Note that assume does not provide an action block, as the actions for an assumption serve no purpose.

Group

17.13 并发断言

链接
17.13 并发断言


17.13.3 覆盖语句

链接
17.13 并发断言
SystemVerilog 3.1a语言参考手册
17.13.3 覆盖语句
17.13 并发断言

To monitor sequences and other behavioral aspects of the design for coverage, the same syntax is used with the cover statement. The tools can gather information about the evaluation and report the results at the end of simulation. When the property for the cover statement is successful, the pass statements can specify a coverage function, such as monitoring all paths for a sequence. The pass statement shall not include any concurrent assert, assume or cover statement.

Coverage results are divided into two: coverage for properties, coverage for sequences.

For sequence coverage, the statement appears as:

Copy Code
cover property ( sequence_expr ) statement_or_null

The results of coverage statement for a property shall contain:

  • Number of times attempted
  • Number of times succeeded
  • Number of times failed
  • Number of times succeeded because of vacuity
In addition, statement_or_null is executed every time a property succeeds.

Vacuity rules are applied only when implication operator is used. A property succeeds non-vacuously only if the consequent of the implication contributes to the success.

Results of coverage for a sequence shall include:

  • Number of times attempted
  • Number of times matched (each attempt can generate multiple matches)
In addition, statement_or_null gets executed for every match. If there are multiple matches at the same time, the statement gets executed multiple times, one for each match.

Group

17.13 并发断言

链接
17.13 并发断言


17.13.4 在过程化代码外部使用并发断言语句

链接
17.13 并发断言
SystemVerilog 3.1a语言参考手册
17.13.4 在过程化代码外部使用并发断言语句
17.13 并发断言

A concurrent assertion statement can be used outside of a procedural context. It can be used within a module, an interface, or a program. A concurrent assertion statement is an assert, an assume, or a cover statement.Such a concurrent assertion statement uses the always semantics.

The following two forms are equivalent:

Copy Code
assert property ( property_spec ) action_block
always assert property ( property_spec ) action_block ;

Similarly, the following two forms are equivalent:

Copy Code
cover property ( property_spec ) statement_or_null
always cover property ( property_spec ) statement_or_null

For example:

Copy Code
module top(input bit clk);
    logic a,b,c;

    property rule3;
        @(posedge clk) a |-> b ##1 c;
    endproperty

    a1: assert property (rule3);

    ...
endmodule

rule3 is a property declared in module top. The assert statement a1 starts checking the property from the beginning to the end of simulation. The property is always checked. Similarly,

Copy Code
module top(input bit clk);
    logic a,b,c;

    sequence seq3;
        @(posedge clk) b ##1 c;
    endsequence

    c1: cover property (seq3);

    ...
endmodule

The cover statement c1 starts coverage of the sequence seq3 from beginning to the end of simulation. The sequence is always monitored for coverage.

Group

17.13 并发断言

链接
17.13 并发断言


17.13.5 在过程化代码中嵌入并发断言

链接
17.13 并发断言
SystemVerilog 3.1a语言参考手册
17.13.5 在过程化代码中嵌入并发断言
17.13 并发断言

A concurrent assertion statement can also be embedded in a procedural block. For example:

Copy Code
property rule;
    a ##1 b ##1 c;
endproperty

always @(posedge clk) begin
    <statements>
    assert property (rule);
end

If the statement appears in an always block, the property is always monitored. If the statement appears in an initial block, then the monitoring is performed only on the first clock tick.

Two inferences are made from the procedural context: clock from the event control of an always block, and the enabling conditions.

A clock is inferred if the statement is placed in an always or initial block with an event control abiding by the following rules:

  • The clock to be inferred must be placed as the first term of the event control as an edge specifier (posedge expression or negedge expression).
  • The variables in expression must not be used anywhere in the always or initial block.
For example:

Copy Code
property r1;
    q != d;
endproperty

always @(posedge mclk) begin
    q <= d1;
    r1_p: assert property (r1);
end

The above property can be checked by writing statement r1_p outside the always block, and declaring the property with the clock as:

Copy Code
property r1;
    @(posedge mclk)q != d;
endproperty

always @(posedge mclk) begin
    q <= d1;
end

r1p: assert property (r1);

If the clock is explicitly specified with a property, then it must be identical to the inferred clock, as shown below:

Copy Code
property r2;
    @(posedge mclk)(q != d);
endproperty

always @(posedge mclk) begin
    q <= d1;
    r2_p: assert property (r2);
end

In the above example, (posedge mclk) is the clock for property r2.

Another inference made from the context is the enabling condition for a property. Such derivation takes place when a property is placed in an if...else block or a case block. The enabling condition assumed from the context is used as the antecedent of the property.

Copy Code
property r3;
    @(posedge mclk)(q != d);
endproperty

always @(posedge mclk) begin
    if (a) begin
        q <= d1;
        r3_p: assert property (r3);
    end
end

The above example is equivalent to:

Copy Code
property r3;
    @(posedge mclk)a |-> (q != d);
endproperty

r3_p: assert property (r3);

always @(posedge mclk) begin
    if (a) begin
        q <= d1;
    end
end

Similarly, the enabling condition is also inferred from case statements.

Copy Code
property r4;
    @(posedge mclk)(q != d);
endproperty

always @(posedge mclk) begin
    case (a)
        1: begin q <= d1;
                r4p: assert property (r4);
           end

        default: q1 <= d1;
    endcase
end

The above example is equivalent to:

Copy Code
property r4;
    @(posedge mclk)(a==1) |-> (q != d);
endproperty

r4_p: assert property (r4);

always @(posedge mclk) begin
    case (a)
        1: begin q <= d1;
           end
        default: q1 <= d1;
    endcase
end

The enabling condition is inferred from procedural code inside an always or initial block, with the following restrictions:

  1. There must not be a preceding statement with a timing control.
  2. A preceding statement shall not invoke a task call which contains a timing control on any statement.
  3. The concurrent assertion statement shall not be placed in a looping statement, immediately, or in any nested scope of the looping statement.

Group

17.13 并发断言

链接
17.13 并发断言


17.14 时钟解析

链接
第十七章 断言, 主题
SystemVerilog 3.1a语言参考手册
17.14 时钟解析
第十七章 断言 | 主题

SystemVerilog具有多种方法为一个特性指定时钟。

— 具有一个时钟的序列实例，例如：

Copy Code
sequence s2;
    @(posedge clk)
        a ##2 b;
endsequence

property p2;
    not s2;
endproperty

assert property(p2);

— 特性，例如：

Copy Code
property p3; @(posedge clk) not (a ##2 b); endproperty
assert property (p3);

— contextually inferred clock from a procedural block, for example:

Copy Code
always @(posedge clk) assert property (not (a ##2 b));

— clocking block, for example:

Copy Code
clocking master_clk @(posedge clk);
    property p3; not (a ##2 b); endproperty
endclocking
assert property (master_clk.p3);

— default clock, for example:

Copy Code
default clocking master_clk ; // master clock as defined above
property p4; (a ##2 b); endproperty
assert property (p4);

For a multi-clocked assertion, the clocks are explicitly specified. No default clock or inferred clock is used. In addition, multi-clocked properties are not allowed to be defined within a clocking block.

A multi-clocked property assert statement must not be embedded in procedural code where a clock is inferred.For example, following forms are not allowed.

Copy Code
always @(clk) assert property (mult_clock_prop);// illegal
initial @(clk) assert property (mult_clock_prop);// illegal

The rules for an assertion with one clock are discussed in the following paragraphs.

The clock for an assertion statement is determined in the decreasing order of priority:

  1. Explicitly specified clock for the assertion.
  2. Inferred clock from the context of the code when embedded.
  3. Default clock, if specified.
A concurrent assertion statement must resolve to a clock. Otherwise, the statement is considered illegal.

Sequences and properties specified in clocking blocks resolve the clock by the following rules:

  1. Event control of the clocking block specifies the clock.
  2. No explicit event control is allowed in any property or sequence declaration.
  3. If a named sequence that is defined outside the clocking block is used , its clock, if specified, must be identical to the clocking block’s clock.
  4. Multi-clock properties are not allowed.
Resolution of clock for a sequence declaration assumes that only one explicit event control can be specified. Also, the named sequences used in the sequence declaration can, but do not need to, contain event control in their definitions.

Copy Code
sequence s;
    //sequence composed of two named subsequences
    @(posedge s_clk) e ##1 s1 ##1 s2 ##1 f;
endsequence

sequence s1;
    @(posedge clk1) a ##1 b; // single clock sequence
endsequence

sequence s2;
    @(posedge clk2) c ##1 d; // single clock sequence
endsequence

These example sequences are used in Table 17-3 to explain the clock resolution rules for a sequence declaration. The clock of any sequence when explicitly specified is indicated by X. Otherwise, it is indicated by a dash.

Table 17-3: Resolution of clock for a sequence declaration

s_clk | clk1 | clk2 | Resolved clock | Semantic restriction
- | - | - | unclocked | -
X | - | - | s_clk | -
X | X | - | s_clk | s_clk and clk1 must be identical
X | X | X | s_clk | s_clk, clk1 and clk2 must be identical
X | - | X | s_clk | s_clk and clk2 must be identical
- | X | - | unclocked | -
- | X | X | unclocked | clk1 and clk2 must be identical
- | - | X | unclocked | -

Once the clock for a sequence declaration is determined, the clock of a property declaration is resolved similar to the resolution for a sequence declaration. A single clocked property assumes that only one explicit event control can be specified. Also, the named sequences used in the property declaration can contain event control in their declarations. Table 17-4 specifies the rules for property declaration clock resolution. The property has the form:

Copy Code
property p;
    @(posedge p_clk) not s1 |=> s2;
endproperty

p_clk is the property for the clock, clk1 is the clock for sequence s1 and clk2 is the clock for sequence s2. The same rules apply for operator |->.

Table 17-4: Resolution of clock for a declaration

p_clk | clk1 | clk2 | Resolved clock | Semantic restriction
- | - | - | unclocked | -
X | - | - | p_clk | -
X | X | - | p_clk | p_clk and clk1 must be identical
X | X | X | p_clk | p_clk, clk1 and clk2 must be identical
X | - | X | p_clk | p_clk and clk2 must be identical
- | X | - | unlocked | -
- | X | X | unlocked or multi-clock | clk1 and clk2 must be identical. If clk1 and clk2 are different for the case of operator |=>, then it is considered a multi-clock implication
- | - | X | unlocked | -

Resolution of clock for an assert statement is based on the following assumptions:

  • assert can appear in an always block, initial block or outside procedural context
  • clock is inferred from an always or initial block
  • default clock can be specified using default clocking block
Table 17-5 specifies the rules for clock resolution when assert appears in an always or initial block, where i_clk is the inferred clock from an always or initial block, d_clk is the default clock, and p_clk is the property clock.

Table 17-5: Resolution of clock in an always or initial block

i_clk | d_clk | p_clk | Resolved clock | Semantic restriction
- | - | - | unclocked | Error. An assertion must have a clock
X | - | - | i_clk | -
- | X | - | d_clk |
- | - | X | p_clk |
X | - | X | i_clk | i_clk and p_clk must be identical
X | X | - | i_clk | -
- | X | X | p_clk |
- | - | X | p_clk | -

When the assert statement is outside any procedural block, there is no inferred clock. The rules for clock resolution are specified in Table 17-6.

Table 17-6: Resolution of clock outside a procedural block

d_clk | p_clk | Resolved clock | Semantic restriction
- | - | unlocked | Error. An assertion must have a clock
X | - | d_clk |
- | X | p_clk |
X | X | p_clk |
Group

第十七章 断言

主题
主题 | 描述
17.14.1 在多时钟控制特性中的时钟解析 | Throughout this subsection, s, s1, s2 denote sequences without clocking events; p, p1, p2 denote properties without clocking events; m, m1, m2 denote multiply-clocked sequences, q, q1, q2 denote multiply-clocked properties; and c, c1, c2 denote non-identical clocking event expressions. Due to clock flow, juxtaposition of two clocks nullifies the first. This and the nesting of clocking events within other property building operators mean that there are subtleties in the general interpretation of the restrictions about where the clock can change in multiply-clocked properties. For example,
链接
第十七章 断言, 主题


17.14.1 在多时钟控制特性中的时钟解析

链接
17.14 时钟解析
SystemVerilog 3.1a语言参考手册
17.14.1 在多时钟控制特性中的时钟解析
17.14 时钟解析

Throughout this subsection, s, s1, s2 denote sequences without clocking events; p, p1, p2 denote properties without clocking events; m, m1, m2 denote multiply-clocked sequences, q, q1, q2 denote multiply-clocked properties; and c, c1, c2 denote non-identical clocking event expressions.

Due to clock flow, juxtaposition of two clocks nullifies the first. This and the nesting of clocking events within other property building operators mean that there are subtleties in the general interpretation of the restrictions about where the clock can change in multiply-clocked properties. For example,

Copy Code
@(c) s |-> @(c) (p and @(c1) p1)

appears legal because the antecedent is clocked by c and the consequent begins syntactically with the clocking event @(c). However, the consequent sequence is equivalent to

Copy Code
(@(c) p) and (@(c1) p1)

and |-> cannot synchronize between clock c from the antecedent and clock c1 from the second conjunct of the consequent. Similarly,

Copy Code
@(c) s |-> @(c1) (@(c) p)

appears illegal due to the apparent clock change from c to c1 across |->. However, it is legal, although arguably misleading in style, because the consequent property is equivalent to @(c) p.

This subsection gives a more precise treatment of the restrictions on multiply-clocked use of |-> and if/if...else than the intuitive discussion in Section 17.12. The present treatment depends on the notion of the set of semantic leading clocks for a multiply-clocked sequence or property.

Some sequences and properties have no explicit leading clock event. Their initial clocking event is inherited from an outer clocking event according to the flow of clocking event scope. In this case, the semantic leading clock is said to be inherited. For example, in the property

Copy Code
@(c) s |=> p and @(c1) p1

the semantic leading clock of the subproperty p is inherited since the initial clock of p is the clock that flows

across |=>.

A multiply-clocked sequence has a unique semantic leading clock, defined inductively as follows.

  • The semantic leading clock of s is inherited.
  • The semantic leading clock of @(c) s is c.
  • If inherited is the semantic leading clock of m, then the semantic leading clock of @(c) m is c. Otherwise, the semantic leading clock of @(c) m is equal to the semantic leading clock of m.
  • The semantic leading clock of (m) is equal to the semantic leading clock of m.
  • The semantic leading clock of m1 ## m2 is equal to the semantic leading clock of m1.
The set of semantic leading clocks of a multiply-clocked property is defined inductively as follows.
  • The set of semantic leading clocks of m is {c}, where c is the unique semantic leading clock of m.
  • The set of semantic leading clocks of p is {inherited}.
  • If inherited is an element of the set of semantic leading clocks of q, then the set of semantic leading clocks of @(c) q is obtained from the set of semantic leading clocks of q by replacing inherited by c. Otherwise, the set of semantic leading clocks of @(c) q is equal to the set of semantic leading clocks of q.
  • The set of semantic leading clocks of (q) is equal to the set of semantic leading clocks of q.
  • The set of semantic leading clocks of not q is equal to the set of semantic leading clocks of q.
  • The set of semantic leading clocks of q1 and q2 is the union of the set of semantic leading clocks of q1 with
  • the set of semantic leading clocks of q2.
  • The set of semantic leading clocks of q1 or q2 is the union of the set of semantic leading clocks of q1 with the set of semantic leading clocks of q2.
  • The set of semantic leading clocks of m |-> p is equal to the set of semantic leading clocks of m.
  • The set of semantic leading clocks of m |=> p is equal to the set of semantic leading clocks of m.
  • The set of semantic leading clocks of if (b) q is {inherited}.
  • The set of semantic leading clocks of if (b) q1 else q2 is {inherited}.
  • The set of semantic leading clocks of a property instance is equal to the set of semantic leading clocks of the multiply-clocked property obtained from the body of its declaration by substituting in actual arguments.
For example, the multiply-clocked sequence

Copy Code
@(c1) s1 ## @(c2) s2

has c1 as its unique semantic leading clock, while the multiply-clocked property

Copy Code
not (p1 and (@(c2) p2)

has {inherited, c2} as its set of semantic leading clocks.

In the presence of an incoming outer clock, the inherited semantic leading clock is always understood to refer to the incoming outer clock. On the other hand, if a property has only explicit semantic leading clocks, then the incoming outer clock has no effect on the clocking of the property since the explicit clock events replace the incoming outer clock. Therefore, the clocking of a property q in the presence of incoming outer clock c is equivalent to the clocking of the property @(c) q.

The rules for using multiply-clocked overlapping implication and if/if...else in the presence of an incoming outer clock can now be stated more precisely.

1) Multiply-clocked overlapping implication.

Let c be the incoming outer clock. Then the clocking of m |-> q is equivalent to the clocking of @(c) m |-> q

In the presence of the incoming outer clock, m has a well-defined ending clock, and there is a welldefined clock that flows across |->. The multiply-clocked overlapped implication m |-> q is legal for incoming clock c if and only if the following two conditions are met:

a) Every explicit semantic leading clock of q is identical to the ending clock of m.

b) If inherited is a semantic leading clock of q, then the ending clock of m is equal to the clock that flows across |->.

For example

Copy Code
@(c) s |-> p1 or @(c2) p2

is not legal because the ending clock of the antecedent is c, while the consequent has c2 as an explicit semantic leading clock.

Also,

Copy Code
@(c) s ## (@(c1) s1) |-> p

is not legal because the set of semantic leading clocks of p is {inherited}, the ending clock of the antecedent is c1, and the clock that flows across |-> and is inherited by p is c.

On the other hand,

Copy Code
@(c) s |-> p1 or @(c) p2

and

Copy Code
@(c) s ## @(c1) s1 |-> p1 or @(c1) p2

are both legal.

2) Multiply-clocked if/if...else

Let c be the incoming outer clock. Then the clocking of if (b) q1 [ else q2 ] is equivalent to the clocking

of

Copy Code
@(c) if (b) q1 [ else q2 ]

The boolean condition b is clocked by c, so the multiply-clocked if/if...else if (b) q1 [ else q2 ] is legal for incoming clock c if and only if the following condition is met:

  • Every explicit semantic leading clock of q1 [ or q2 ] is identical to c.
For example,

Copy Code
@(c) if (b) p1 else @(c) p2

is legal, but

Copy Code
@(c) if (b) @(c) (p1 and @(c2) p2)

is not.

Group

17.14 时钟解析

链接
17.14 时钟解析


17.15 将特性绑定到作用域或实例

链接
第十七章 断言
SystemVerilog 3.1a语言参考手册
17.15 将特性绑定到作用域或实例
第十七章 断言

To facilitate verification separate from the design, it is possible to specify properties and bind them to specific modules or instances. The following are the goals of providing this feature:

  • It allows verification engineers to verify with minimum changes to the design code/files.
  • It allows a convenient mechanism to attach verification IP to a module or an instance.
  • No semantic changes to the assertions are introduced due to this feature. It is equivalent to writing properties external to a module, using hierarchical path names.
With this feature, a user can bind a module, interface, or program instance to a module or a module instance.

The syntax of the bind construct is:

Copy Code
bind_directive ::= bind hierarchical_identifier constant_select bind_instantiation;
                                                                // from Annex A.1.5
bind_instantiation ::=
    program_instantiation
  | module_instantiation
  | interface_instantiation

Syntax 17-17—bind construct syntax (excerpt from Annex A)

The bind directive can be specified in

  • a module
  • an interface
  • a compilation-unit scope
A program block contains non-design code (either testbench or properties) and executes in the Reactive region, as explained in Section 16.

Example of binding a program instance to a module:

Copy Code
bind cpu fpu_props fpu_rules_1(a,b,c);

Where:

  • cpu is the name of module.
  • fpu_props is the name of the program containing properties.
  • fpu_rules_1 is the program instance name.
  • Ports (a, b,c) get bound to signals (a,b,c) of module cpu.
  • Every instance of cpu gets the properties.
Example of binding a program instance to a specific instance of a module:

Copy Code
bind cpu1 fpu_props fpu_rules_1(a,b,c);

By binding a program to a module or an instance, the program becomes part of the bound object. The names of assertion-related declarations can be referenced using the SystemVerilog hierarchical naming conventions.

Binding of a module instance or an interface instance works the same way as described for programs above.

Copy Code
interface range (input clk,enable, input int minval,expr);
    property crange_en;
        @(posedge clk) enable |-> (minval <= expr);
    endproperty

    range_chk: assert property (crange_en);
endinteface

bind cr_unit range r1(c_clk,c_en,v_low,(in1&&in2));

In this example, interface range is instantiated in the module cr_unit. Effectively, every instance of module cr_unit shall contain the interface instance r1.

Group

第十七章 断言

链接
第十七章 断言


17.16 expect语句

链接
第十七章 断言
SystemVerilog 3.1a语言参考手册
17.16 expect语句
第十七章 断言

The expect statement is a procedural blocking statement that allows waiting on a property evaluation. The syntax of the expect statement accepts a named property or a property declaration, and is given below.

Copy Code
expect_property_statement ::=                    // 引用自附录A.2.10
    expect (property_spec) action_block

Syntax 17-18—expect statement syntax (excerpt from Annex A)

The expect statement accepts the same syntax used to assert a property. An expect statement causes the executing process to block until the given property succeeds or fails. The statement following the expect is scheduled to execute after processing the Observe region in which the property completes its evaluation. When the property succeeds or fails the process unblocks, and the property stops being evaluated (i.e., no property evaluation is started until that expect statement is executed again).

When executed, the expect statement starts a single thread of evaluation for the given property on the subsequent clocking event, that is, the first evaluation shall take place on the next clocking event. If the property fails at its clocking event, the optional else clause of the action block is executed. If the property succeeds the optional pass statement of the action block is executed.

Copy Code
program tst;
    initial begin
        # 200ms;
        expect( @(posedge clk) a ##1 b ##1 c ) else $error( "expect failed" );
        ABC: ...
    end
endprogram

In the above example, the expect statement specifies a property that consists of the sequence a ##1 b ##1 c. The expect statement (second statement in the initial block of program tst) blocks until the sequence a ##1 b ##1 c is matched, or is determined not to match. The property evaluation starts on the clocking event (posedge clk) following the 200ms delay. If the sequence is matched, the process is unblocked and continues to execute on the statement labeled ABC. If the sequence fails to match then the else clause is executed, which in this case generates a run-time error. For the expect above to succeed, the sequence a ##1 b ##1 c must match starting on the clocking event (posedge clk) immediately after time 200ms. The sequence will not match if a, b, or c are evaluated to be false at the first, second or third clocking event respectively.

The expect statement can be incorporated in any procedural code, including tasks or class methods. Because it is a blocking statement, the property can refer to automatic variables as well as static variables. For example, the task below waits between 1 and 10 clock ticks for the variable data to equal a particular value, which is specified by the automatic argument value. The second argument, success, is used to return the result of the expect statement: 1 for success and 0 for failure.

Copy Code
integer data;
...
task automatic wait_for( integer value, output bit success );
    expect( @(posedge clk) ##[1:10] data == value ) success = 1;
    else success = 0;
endtask

initial begin
    bit ok;
    wait_for( 23, ok ); // wait for the value 23
    ...
end
Group

第十七章 断言

链接
第十七章 断言


第十八章 层次

链接
主题
SystemVerilog 3.1a语言参考手册
第十八章 层次
主题
主题
主题
描述
18.1 简介（一般信息）
Verilog的组织结构较为简单。除系统任务和系统函数外，所有的数据、函数和任务都位于模块当中（系统任务和系统函数是全局的，并且可以在PLI中定义）。Verilog模块可以包含其它模块的实例。任何未被实例化的模块都位于顶层。这个规则不适用于库，因此库具有不同的状态和不同的过程来进行分析。一个层次名可以在实例层次的任何地方指定任何命名的对象。模块层次通常很随意，需要耗费很多精力来维护端口列表。

在Verilog中，只有线网、reg、integer和时间数据类型才可以通过模块端口传递。

为了表示设计层次，SystemVerilog加入了许多增强：
  • 包含诸如数据、类型、类、任务和函数声明的包
  • 支持分离的编译
  • 仅在编译单元内可见的编译单元范围
  • 使用嵌套的模块声明来帮助表示自包含的模块和库
  • 在端口声明中可以使用较宽松的规则
  • 使用“.name”来简化命名端口的连接
  • 使用“.”的隐式端口连接
  • 与模块绑定的时间单位和时间精度说明
  • 使用接口的概念来封装模块间的连接（在第十九章中提供）
SystemVerilog的一个重要增强就是加入了通过模块端口传递任何数据类型的能力，包括线网、以及包括实数、数组和结构体在内的所有变量类型。
18.2 包
SystemVerilog包提供了额外的机制在多个SystemVerilog模块、接口和程序间共享参数、数据、类型、任务、函数、序列以及特性的声明。包是显式命名的作用域，它出现在源文本的最外层（与顶层模块和原语处于同一层次）。类型、变量、任务、函数以及特性都可以在一个包中声明。这些声明可以在模块、宏模块、接口、程序和其它包中通过导入或完整解析的名字来引用。
18.3 编译单元的支持
通过使用编译单元，SystemVerilog支持分离的编译。SystemVerilog提供了下列的术语和定义：
  • 编译单元：a collection of one or more SystemVerilog source files compiled together
  • 编译单元作用域：a scope that is local to the compilation unit. It contains all declarations that lie outside of any other scope
  • $unit：用来显式地访问编译单元作用域中的标识符的名字
The exact mechanism for defining which files constitute a compilation unit is tool specific. Tools shall provide a mechanism to specify the files that make up a compilation unit. Two extreme cases are:
  1. All files make a single compilation unit (in which case the declarations in the compilation-unit scope are accessible anywhere within the design)
  2. Each file is a separate compilation unit (in which case the... more
18.4 顶层实例
The name $root is added to unambiguously refer to a top level instance, or to an instance path starting from the root of the instantiation tree. $root is the root of the instantiation tree.

For example:
18.5 模块声明
18.6 嵌套的模块
A module can be declared within another module. The outer name space is visible to the inner module, so that any name declared there can be used, unless hidden by a local name, provided the module is declared and instantiated in the same scope.

One purpose of nesting modules is to show the logical partitioning of a module without using ports. Names that are global are in the outermost scope, and names that are only used locally can be limited to local modules.
18.7 外部模块
To support separate compilation, extern declarations of a module can be used to declare the ports on a module without defining the module itself. An extern module declaration consists of the keyword extern followed by the module name and the list of ports for the module. Both list of ports syntax (possibly with parameters), and original Verilog style port declarations can be used. Note that the potential existence of defparams precludes the checking of the port connection information prior to elaboration time even for list of ports style declarations.

The following example demonstrates the usage of extern module declarations.
18.8 端口声明
18.9 端口表达式列表
Verilog 1364-2001 created a list_of_port_declarations alternate style which minimized the duplication of data used to specify the ports of a module. SystemVerilog adds an explicitly named port declaration to that style, allowing elements of arrays and structures, concatenations of elements, or aggregate expressions of elements declared in a module, interface or program to be specified on the port list.

Like explicitly named ports in a module port declaration, port identifiers exist in their own namespace for each port list. When port item is just a simple port identifier, that identifier is used as both a reference to an interface item... more
18.10 时间单位与精度
SystemVerilog has a time unit and precision declaration which has the equivalent functionality of the ‘timescale compiler directives in Verilog-2001. Use of these declarations removes the file order dependencies problems with compiler directives. The time unit and precision can be declared by the timeunit and timeprecision keywords, respectively, and set to a time literal which must be a power of 10 units. For example:
18.11 模块实例
18.12 端口连接规则
通过允许所有变量数据类型都能够通过端口传递，SystemVerilog扩展了Verilog的端口连接能力。通过允许端口连接的两侧具有相同的兼容类型，并且通过允许对变量的连续赋值，SystemVerilog做到了这一点。SystemVerilog还产生了一个新的端口限定符类型，ref，它允许共享的变量通过传递一个层次化的引用来跨越一个端口。
18.13 命名空间
SystemVerilog has eight name spaces for identifiers, two are global (definitions name space and package name space), two are global to the compilation unit (compilation unit name space and text macro name space) and four are local. The eight name spaces are described as follows:
  1. The definitions name space unifies all the non-nested module, macromodule, primitive, program, and interface identifiers defined outside of all other declarations. Once a name is used to define a module, macromodule, primitive, program, or interface within one compilation unit the name shall not be used again (in any compilation unit) to declare another non-nested module,... more
18.14 层次化的名字
Hierarchical names are also called nested identifiers. They consist of instance names separated by periods, where an instance name can be an array element. The instance name $root refers to the top of the instantiated design and is used to unambiguously gain access to the top of the design.
链接
主题


18.1 简介（一般信息）

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.1 简介（一般信息）
第十八章 层次

Verilog的组织结构较为简单。除系统任务和系统函数外，所有的数据、函数和任务都位于模块当中（系统任务和系统函数是全局的，并且可以在PLI中定义）。Verilog模块可以包含其它模块的实例。任何未被实例化的模块都位于顶层。这个规则不适用于库，因此库具有不同的状态和不同的过程来进行分析。一个层次名可以在实例层次的任何地方指定任何命名的对象。模块层次通常很随意，需要耗费很多精力来维护端口列表。

在Verilog中，只有线网、reg、integer和时间数据类型才可以通过模块端口传递。

为了表示设计层次，SystemVerilog加入了许多增强：

  • 包含诸如数据、类型、类、任务和函数声明的包
  • 支持分离的编译
  • 仅在编译单元内可见的编译单元范围
  • 使用嵌套的模块声明来帮助表示自包含的模块和库
  • 在端口声明中可以使用较宽松的规则
  • 使用“.name”来简化命名端口的连接
  • 使用“.”的隐式端口连接
  • 与模块绑定的时间单位和时间精度说明
  • 使用接口的概念来封装模块间的连接（在第十九章中提供）
SystemVerilog的一个重要增强就是加入了通过模块端口传递任何数据类型的能力，包括线网、以及包括实数、数组和结构体在内的所有变量类型。

Group

第十八章 层次

链接
第十八章 层次


18.2 包

链接
第十八章 层次, 主题
SystemVerilog 3.1a语言参考手册
18.2 包
第十八章 层次 | 主题

SystemVerilog包提供了额外的机制在多个SystemVerilog模块、接口和程序间共享参数、数据、类型、任务、函数、序列以及特性的声明。包是显式命名的作用域，它出现在源文本的最外层（与顶层模块和原语处于同一层次）。类型、变量、任务、函数以及特性都可以在一个包中声明。这些声明可以在模块、宏模块、接口、程序和其它包中通过导入或完整解析的名字来引用。

Copy Code
package_declaration ::=              // 引用自附录A.1.3
    {attribute_instance} package package_identifier;
        [timeunits_declaration] {{attribute_instance} package_item}
    endpackage [: package_identifier]

package_item ::=                    // 引用自附录A.1.10
    package_or_generate_item_declaration
  | specparam_declaration
  | anonymous_program
  | timeunits_declaration

package_or_generate_item_declaration ::=
    net_declaration
  | data_declaration
  | task_declaration
  | function_declaration
  | dpi_import_export
  | extern_constraint_declaration
  | class_declaration
  | class_constructor_declaration
  | parameter_declaration;
  | local_parameter_declaration
  | covergroup_declaration
  | overload_declaration
  | concurrent_assertion_item_declaration
  | ;

anonymous_program ::= program; {anonymous_program_item} endprogram

anonymous_program_item ::=
    task_declaration
  | function_declaration
  | class_declaration
  | covergroup_declaration
  | class_constructor_declaration
  | ;

语法18-1 — 包声明语法（摘录自附录A）

包声明产生了一个作用域，它包含了用于在一个或多个编译单元、模块、宏模块、接口或程序间共享的声明。位于包内的项目通常是类型定义、任务、以及函数。位于包内的项目不能具有层次化的引用。包还可能包含参数、变量和线网。对于那些不方便通过层次向下传递的全局项目，这种方式可能有用。与在一个编译单元或模块内声明的变量相同，位于包内的变量声明赋值应该出现在任何initial、always、always_comb、always_latch或always_ff块被启动之前。

下面是包的一个例子：

Copy Code
package ComplexPkg;
    typedef struct {
        float i, r;
    } Complex;

    function Complex add(Complex a, b);
        add.r = a.r + b.r;
        add.i = a.i + b.i;
    endfunction

    function Complex mul(Complex a, b);
        mul.r = (a.r * b.r) - (a.i * b.i);
        mul.i = (a.r * b.i) + (a.i * b.r);
    endfunction
endpackage : ComplexPkg
Group

第十八章 层次

主题
主题 | 描述
18.2.1 引用包中的数据 | 为了在包被导入的作用域内能够识别包中定义的项目，包必须存在。 使用一个包中所作声明的一种方法是使用域解析操作符“::”进行引用。
18.2.2 搜索顺序规则 | 对于从一个包中导入的声明，表格18-1为其描述了搜索顺序规则。为了方便以后的讨论，考虑下面的包声明：
链接
第十八章 层次, 主题


18.2.1 引用包中的数据

链接
18.2 包
SystemVerilog 3.1a语言参考手册
18.2.1 引用包中的数据
18.2 包

为了在包被导入的作用域内能够识别包中定义的项目，包必须存在。

使用一个包中所作声明的一种方法是使用域解析操作符“::”进行引用。

Copy Code
ComplexPkg::Complex cout = ComplexPkg::mul(a, b);

使用包声明的另外一个方法是通过import语句。

Copy Code
data_declaration ::=        // 引用自附录A.2.1.3
    ...
  | package_import_declaration

package_import_declaration ::=
    import package_import_item {, package_import_item};

package_import_item ::=
    package_identifier :: identifier
  | package_identifier :: *

语法 18-2 — 包导入语法（摘录自附录A）

import语句为包内的标识符提供了直接的可视性。它使得在包内声明的标识符能够不需要一个包名字限定符就可以在当前的作用域内可见。SystemVerilog提供了两种格式的导入语句：显式导入和通配导入。显式导入能够精确地控制哪些符号被导入：

Copy Code
import ComplexPkg::Complex;
import ComplexPkg::add;

如果被导入的标识符已经在相同的作用域内被声明或者已经显式地从另外一个包中被导入，那么这个显式导入是非法的，但SystemVerilog允许从相同的包中多次导入一个标识符。

通配导入使得一个包内声明的所有标识符都被导入，只要标识符在导入作用域内没有被定义：

Copy Code
import ComplexPkg::*;

通配导入使得包内的每一个标识符都成为导入的候选者。每一个这样的标识符只有当它在导入作用域内被引用并且它既没有被声明也没有被显式地导入作用域的时候才被导入。类似地，一个标识符的通配导入会被相同作用域内相同标识符的后续声明所过载。如果相同的标识符被从两个不同的包通配导入到一个作用域，那么这个标识符应该在作用域是未定义的，并且如果标识符被使用的话会导致一个错误。

Group

18.2 包

链接
18.2 包


18.2.2 搜索顺序规则

链接
18.2 包
SystemVerilog 3.1a语言参考手册
18.2.2 搜索顺序规则
18.2 包

对于从一个包中导入的声明，表格18-1为其描述了搜索顺序规则。为了方便以后的讨论，考虑下面的包声明：

Copy Code
package p;
    typedef enum {FALSE, TRUE} BOOL;
    const BOOL c = FALSE;
endpackage

package q;
    const int c = 0;
endpackage

表格18-1：包导入的作用域规则

例子
描述
包含了一个c的本地声明的作用域
没有包含一个c的本地声明的作用域
包含了一个使用q::c导入的c声明的作用域
包含了一个作为q::*导入的c声明的作用域
u = p::c;
y = p::TRUE;
一个限定的包标识符在任意作用域内可见（无需使用一条导入子句）
OK

对c的直接引用指向本地声明的c。

p::c指向包p中的c。
OK

对c的直接引用是非法的，因为它是未定义的。

p::c指向包p中的c。
OK

对c的直接引用指向从q中导入的c。

p::c指向包p中的c。
OK

对c的直接引用指向从q中导入的c。

p::c指向包p中的c。
import p::*;
. . .
y = FALSE;
包p内的所有声明在导入作用域内都具有潜在的直接可视性：
  • c
  • BOOL
  • FALSE
  • TRUE
OK

对c的直接引用指向本地声明的c。

对其它标识符（例如FALSE）的引用指向那些隐含地从包p中导入的标识符。
OK

对c的直接引用指向从p中导入的c。
OK

对c的直接引用指向从q中导入的c。
OK / ERROR

c在导入作用域内是未定义的。因此对c的直接引用是非法的并且会产生一个错误。

然而允许使用导入子句。
import p::c;
. . .
if(!c) ...
导入的标识符在导入作用域内变为直接可见
错误
OK

对c的直接引用指向从p中导入的c。
错误

导入一个在导入作用域中定义的标识符是非法的。
OK / ERROR

p::c的导入使得任何先前对c的引用成为非法的。

然而，对c的直接引用指向从包p中导入的c。

当使用一个通配导入的时候，对一个在包内部声明的未定义标识符的引用会导致这个标识符被导入到本地作用域中。然而，如果相同的标识符在后来又被声明或者被显式地导入的话则会产生一个错误。如下面的例子所示：

Copy Code
module foo;
    import q::*;
    wire a = c;  // 本条语句强制导入q::c;
    import p::c; // q::c和p::c之间的冲突会产生一个错误。
endmodule
Group

18.2 包

链接
18.2 包


18.3 编译单元的支持

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.3 编译单元的支持
第十八章 层次

通过使用编译单元，SystemVerilog支持分离的编译。SystemVerilog提供了下列的术语和定义：

  • 编译单元：a collection of one or more SystemVerilog source files compiled together
  • 编译单元作用域：a scope that is local to the compilation unit. It contains all declarations that lie outside of any other scope
  • $unit：用来显式地访问编译单元作用域中的标识符的名字
The exact mechanism for defining which files constitute a compilation unit is tool specific. Tools shall provide a mechanism to specify the files that make up a compilation unit. Two extreme cases are:
  1. All files make a single compilation unit (in which case the declarations in the compilation-unit scope are accessible anywhere within the design)
  2. Each file is a separate compilation unit (in which case the declarations in each compilation-unit scope are accessible only within its corresponding file)
The contents of files included using one or more ‘include directives become part of the compilation unit of the file they are included within.

If there is a declaration that is incomplete at the end of a file, then the compilation unit including that file will extend through each successive file until there are no incomplete declarations at the end of the group of files.

The default is that each file is a separate compilation unit.

A tool must also provide a mechanism (such as a command line switch) that specifies that all of the files compiled together are a single compilation unit.

There are other possible mappings of files to compilation units and the mechanism for defining them are tool specific and may not be portable.

The compilation-unit scope can contain any item that can be defined within a package. These items are in the compilation-unit scope name space.

The following items are visible in all compilation units: modules, macromodules, primitives, programs, interfaces, and packages. Items defined in the compilation-unit scope cannot be accessed by name from outside the compilation unit. Access to the items in a compilation-unit scope can be accessed using the PLI, which must provide an iterator to traverse all the compilation units.

In Verilog, compiler directives once seen by a tool apply to all forthcoming source text. This behavior shall be supported within a separately compiled unit; however, compiler directives from one separately compiled unit shall not affect other compilation units. This may result in a difference of behavior between compiling the units separately or as a single compilation unit containing the entire source.

When an identifier is referenced within a scope, SystemVerilog follows the Verilog name search rules:

  • First, the nested scope is searched (1364-2001 12.6) (including nested module declarations), including any identifiers made available through package import declarations
  • Next, the compilation-unit scope is searched (including any identifiers made available through package import declarations
  • Finally, the instance hierarchy is searched (1364-2001 12.5)
$unit is the name of the scope that encompasses a compilation unit. Its purpose is to allow the unambiguous reference to declarations at the outermost level of a compilation unit (i.e., those in the compilation-unit scope).This is done via the same scope resolution operator used to access package items.

For example:

Copy Code
bit b;

task foo;
    int b;
    b = 5 + $unit::b; // $unit::b is the one outside
endtask

The compilation-unit scope allows users to easily share declarations (e.g., types) across the unit of compilation, but without having to declare a package from which the declarations are subsequently imported. Thus, the compilation-unit scope is similar to an implicitly defined anonymous package. Because it has no name, the compilation-unit scope cannot be used with an import statement, and the identifiers declared within the scope are not accessible via hierarchical references. Within a particular compilation unit, however, the special name $unit can be used to explicitly access the declarations of its compilation-unit scope.

Group

第十八章 层次

链接
第十八章 层次


18.4 顶层实例

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.4 顶层实例
第十八章 层次

The name $root is added to unambiguously refer to a top level instance, or to an instance path starting from the root of the instantiation tree. $root is the root of the instantiation tree.

For example:

Copy Code
$root.A.B // item B within top instance A
$root.A.B.C // item C within instance B within instance A

$root allows explicit access to the top of the instantiation tree. This is useful to disambiguate a local path (which takes precedence) from the rooted path. In Verilog, a hierarchical path is ambiguous. For example, A.B.C can mean the local A.B.C or the top-level A.B.C (assuming there is an instance A that contains an instance B at both the top level and in the current module). Verilog addresses that ambiguity by giving priority to the local scope, thereby preventing access to the top level path. $root allows explicit access to the top level in those cases in which the name of the top level module is insufficient to uniquely identify the path.

Group

第十八章 层次

链接
第十八章 层次


18.5 模块声明

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.5 模块声明
第十八章 层次
Copy Code
module_declaration ::=         // 引用自附录A.1.3
    module_nonansi_header [timeunits_declaration] {module_item}
        endmodule [: module_identifier]
  | module_ansi_header [timeunits_declaration] {non_port_module_item}
        endmodule [: module_identifier]
  | {attribute_instance} module_keyword [lifetime] module_identifier(.*);
        [timeunits_declaration] {module_item} endmodule [: module_identifier]
  | extern module_nonansi_header
  | extern module_ansi_header

module_nonansi_header ::=
    {attribute_instance} module_keyword [lifetime] module_identifier [parameter_port_list]
        list_of_ports;

module_ansi_header ::=
    {attribute_instance} module_keyword [lifetime] module_identifier [parameter_port_list]
        [list_of_port_declarations];

module_keyword ::= module | macromodule

timeunits_declaration ::=
    timeunit time_literal;
  | timeprecision time_literal;
  | timeunit time_literal;
    timeprecision time_literal;
  | timeprecision time_literal;
    timeunit time_literal;

Syntax 18-3—Module declaration syntax (excerpt from Annex A)

In Verilog, a module must be declared apart from other modules, and can only be instantiated within another module. A module declaration can appear after it is instantiated in the source text.

SystemVerilog adds the capability to nest module declarations.

Copy Code
module m1(...); ... endmodule
module m2(...); ... endmodule
module m3(...);
    m1 i1(...); // instantiates the local m1 declared below
    m2 i4(...); // instantiates m2 - no local declaration
    module m1(...); ... endmodule // nested module declaration,
    // m1 module name is in m3’s name space
endmodule
Group

第十八章 层次

链接
第十八章 层次


18.6 嵌套的模块

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.6 嵌套的模块
第十八章 层次

A module can be declared within another module. The outer name space is visible to the inner module, so that any name declared there can be used, unless hidden by a local name, provided the module is declared and instantiated in the same scope.

One purpose of nesting modules is to show the logical partitioning of a module without using ports. Names that are global are in the outermost scope, and names that are only used locally can be limited to local modules.

Copy Code
// This example shows a D-type flip-flop made of NAND gates
module dff_flat(input d, ck, pr, clr, output q, nq);
    wire q1, nq1, q2, nq2;
    nand g1b (nq1, d, clr, q1);
    nand g1a (q1, ck, nq2, nq1);
    nand g2b (nq2, ck, clr, q2);
    nand g2a (q2, nq1, pr, nq2);
    nand g3a (q, nq2, clr, nq);
    nand g3b (nq, q1, pr, q);
endmodule

// This example shows how the flip-flop can be structured into 3 RS latches.
module dff_nested(input d, ck, pr, clr, output q, nq);
    wire q1, nq1, nq2;

    module ff1;
        nand g1b (nq1, d, clr, q1);
        nand g1a (q1, ck, nq2, nq1);
    endmodule

    ff1 i1();

    module ff2;
        wire q2; // This wire can be encapsulated in ff2
        nand g2b (nq2, ck, clr, q2);
        nand g2a (q2, nq1, pr, nq2);
    endmodule

    ff2 i2();

    module ff3;
        nand g3a (q, nq2, clr, nq);
        nand g3b (nq, q1, pr, q);
    endmodule

    ff3 i3();
endmodule

The nested module declarations can also be used to create a library of modules that is local to part of a design.

Copy Code
module part1(....);
    module and2(input a, b, output z);
        ....
    endmodule

    module or2(input a, b, output z);
        ....
    endmodule

    ....
    and2 u1(....), u2(....), u3(....);
    .....
endmodule

This allows the same module name, e.g. and2, to occur in different parts of the design and represent different modules. Note that an alternative way of handling this problem is to use configurations.

Nested modules with no ports that are not explicitly instantiated shall be implicitly instantiated once with an instance name identical to the module name. Otherwise, if they have ports and are not explicitly instantiated, they are ignored.

Group

第十八章 层次

链接
第十八章 层次


18.7 外部模块

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.7 外部模块
第十八章 层次

To support separate compilation, extern declarations of a module can be used to declare the ports on a module without defining the module itself. An extern module declaration consists of the keyword extern followed by the module name and the list of ports for the module. Both list of ports syntax (possibly with parameters), and original Verilog style port declarations can be used. Note that the potential existence of defparams precludes the checking of the port connection information prior to elaboration time even for list of ports style declarations.

The following example demonstrates the usage of extern module declarations.

Copy Code
extern module m (a,b,c,d);
extern module a #(parameter size= 8, parameter type TP = logic [7:0])
                 (input [size:0] a, output TP b);
module top ();
    wire [8:0] a;
    logic [7:0] b;
    m m (.*);
    a a (.*);
endmodule

Modules m and a are then assumed to be instantiated as:

Copy Code
module top ();
    m m (a,b,c,d);
    a a (a,b);
endmodule

If an extern declaration exists for a module, it is possible to use .* as the ports of the module. This usage shall be equivalent to placing the ports (and possibly parameters) of the extern declaration on the module.

For example,

Copy Code
extern module m (a,b,c,d);
extern module a #(parameter size = 8, parameter type TP = logic [7:0])
                 (input [size:0] a, output TP b);
module m (.*);
    input a,b,c;
    output d;
endmodule

module a (.*);
    ...
endmodule

is equivalent to writing:

Copy Code
module m (a,b,c,d);
    input a,b,c;
    output d;
endmodule

module a #(parameter size = 8, parameter type TP = logic [7:0])
          (input [size:0] a, output TP b);
    ...
endmodule

Extern module declarations can appear at any level of the instantiation hierarchy, but are visible only within the level of hierarchy in which they are declared. It shall be an error for the module definition to not exactly match the extern module declaration.

Group

第十八章 层次

链接
第十八章 层次


18.8 端口声明

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.8 端口声明
第十八章 层次
Copy Code
inout_declaration ::=   // 引用自附录A.2.1.2
    inout port_type list_of_port_identifiers

input_declaration ::=
    input port_type list_of_port_identifiers
  | input data_type list_of_variable_identifiers

output_declaration ::=
    output port_type list_of_port_identifiers
  | output data_type list_of_variable_port_identifiers

interface_port_declaration ::=
    interface_identifier list_of_interface_identifiers
  | interface_identifier.modport_identifier list_of_interface_identifiers

ref_declaration ::= ref data_type list_of_port_identifiers

port_type ::=            // 引用自附录A.2.2.1
    [net_type_or_trireg] [signing] {packed_dimension}

语法18-4 — 端口声明语法（摘录自附录A）

With SystemVerilog, a port can be a declaration of a net, an interface, an event, or a variable of any type, including an array, a structure or a union.

Copy Code
typedef struct {
    bit isfloat;
    union { int i; shortreal f; } n;
} tagged_st; // named structure

module mh1 (input int in1, input shortreal in2, output tagged_st out);
    ...
endmodule

For the first port, if neither a type nor a direction is specified, then it shall be assumed to be a member of a port list, and any port direction or type declarations must be declared after the port list. This is compatible with the Verilog-1995 syntax. If the first port type but no direction is specified, then the port direction shall default to inout. If the first port direction but no type is specified, then the port type shall default to wire. This default type can be changed using the ‘default_nettype compiler directive, as in Verilog.

Copy Code
// Any declarations must follow the port list, because first port does not
// have either a direction or type specified; Port directions default to inout
module mh4(x, y);
    wire x;
    tri0 y;
    ...
endmodule

For subsequent ports in the port list, if the type and direction are omitted, then both are inherited from the previous port. If only the direction is omitted, then it is inherited from the previous port. If only the type is omitted, it shall default to wire. This default type can be changed using the ‘default_nettype compiler directive, as in Verilog.

Copy Code
// second port inherits its direction and type from previous port
module mh3 (input byte a, b);
    ...
endmodule

Generic interface ports cannot be declared using the Verilog-1995 list of ports style. Generic interface ports can only be declared by using a list of port declaration style.

Copy Code
module cpuMod(interface d, interface j);

...
endmodule
Group

第十八章 层次

链接
第十八章 层次


18.9 端口表达式列表

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.9 端口表达式列表
第十八章 层次

Verilog 1364-2001 created a list_of_port_declarations alternate style which minimized the duplication of data used to specify the ports of a module. SystemVerilog adds an explicitly named port declaration to that style, allowing elements of arrays and structures, concatenations of elements, or aggregate expressions of elements declared in a module, interface or program to be specified on the port list.

Like explicitly named ports in a module port declaration, port identifiers exist in their own namespace for each port list. When port item is just a simple port identifier, that identifier is used as both a reference to an interface item and a port identifier. Once a port identifier has been defined, there shall not be another port definition with this same name.

For example:

Copy Code
module mymod (
    output .P1(r[3:0]),
    output .P2(r[7:4]),
    ref .Y(x),
    input bit R );
    logic [7:0] r;
    int x;
    ...
endmodule

The self-determined type of the port expression becomes the type for the port. If the port expression is to be an aggregate expression, then a cast must be used since self-determined aggregate expressions are not allowed. The port expression must resolve to a legal expression for type of module port (See section 18.12—Port connection rules). The port expression is optional because ports can be defined that do not connect to anything internal to the port.

Group

第十八章 层次

链接
第十八章 层次


18.10 时间单位与精度

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.10 时间单位与精度
第十八章 层次

SystemVerilog has a time unit and precision declaration which has the equivalent functionality of the ‘timescale compiler directives in Verilog-2001. Use of these declarations removes the file order dependencies problems with compiler directives. The time unit and precision can be declared by the timeunit and timeprecision keywords, respectively, and set to a time literal which must be a power of 10 units. For example:

Copy Code
timeunit 100ps;
timeprecision 10fs;

There shall be at most one time unit and one time precision for any module, program, package or interface definition, or in any compilation-unit scope. This shall define a time scope. If specified, the timeunit and timeprecision declarations shall precede any other items in the current time scope. The timeunit and timeprecision declarations can be repeated as later items, but must match the previous declaration within the current time scope.

If a timeunit is not specified in the module, program, package or interface definition, then the time unit is shall be determined using the following rules of precedence:

  1. If the module or interface definition is nested, then the time unit shall be inherited from the enclosing module or interface (programs and packages cannot be nested).
  2. Else, if a ‘timescale directive has been previously specified (within the compilation unit), then the time unit shall be set to the units of the last ‘timescale directive.
  3. Else, if the compilation-unit scope specifies a time unit (outside all other declarations), then the time unit shall be set to the time units of the compilation unit.
  4. Else, the default time unit shall be used.
The time unit of the compilation-unit scope can only be set by a timeunit declaration, not a ‘timescale directive. If it is not specified then the default time unit shall be used.

If a timeprecision is not specified in the current time scope, then the time precision shall be determined following the same precedence as with time units.

The global time precision is the minimum of all the timeprecision statements and the smallest time precision argument of all the `timescale compiler directives (known as the precision of the time unit of the simulation in Section 19.8 of the IEEE 1364-2001 standard) in the design. The step time unit is equal to the global time precision.

Group

第十八章 层次

链接
第十八章 层次


18.11 模块实例

链接
第十八章 层次, 主题
SystemVerilog 3.1a语言参考手册
18.11 模块实例
第十八章 层次 | 主题
Copy Code
module_instantiation ::=        // from Annex A.4.1.1
    module_identifier [parameter_value_assignment] hierarchical_instance {, hierarchical_instance};

parameter_value_assignment ::= # ( list_of_parameter_assignments )

list_of_parameter_assignments ::=
    ordered_parameter_assignment { , ordered_parameter_assignment }
  | named_parameter_assignment { , named_parameter_assignment }

ordered_parameter_assignment ::= param_expression

named_parameter_assignment ::= . parameter_identifier ( [ param_expression ] )

hierarchical_instance ::= name_of_instance ( [ list_of_port_connections ] )

name_of_instance ::= instance_identifier { unpacked_dimension }

list_of_port_connections17 ::=
    ordered_port_connection { , ordered_port_connection }
  | named_port_connection { , named_port_connection }

ordered_port_connection ::= { attribute_instance } [ expression ]

named_port_connection ::=
    { attribute_instance } . port_identifier [ ( [ expression ] ) ]
  | { attribute_instance } .*

param_expression ::= mintypmax_expression | data_type   // from Annex A.8.3

Syntax 18-5—Module instance syntax (excerpt from Annex A)

A module can be used (instantiated) in two ways, hierarchical or top level. Hierarchical instantiation allows more than one instance of the same type. The module name can be a module previously declared or one declared later. Actual parameters can be named or ordered. Port connections can be named, ordered or implicitly connected. They can be nets, variables, or other kinds of interfaces, events, or expressions. See below for the connection rules.

Consider an ALU accumulator (alu_accum) example module that includes instantiations of an ALU module, an accumulator register (accum) module and a sign-extension (xtend) module. The module headers for the three instantiated modules are shown in the following example code.

Copy Code
module alu (
    output reg [7:0] alu_out,
    output reg zero,
    input [7:0] ain, bin,
    input [2:0] opcode);
    // RTL code for the alu module
endmodule

module accum (
    output reg [7:0] dataout,
    input [7:0] datain,
    input clk, rst_n);
    // RTL code for the accumulator module
endmodule

module xtend (
    output reg [7:0] dout,
    input din,
    input clk, rst_n);
    // RTL code for the sign-extension module
endmodule
Group

第十八章 层次

主题
主题 | 描述
18.11.1 Instantiation using positional port connections | Verilog has always permitted instantiation of modules using positional port connections, as shown in the alu_accum1 module example, below.
18.11.2 Instantiation using named port connections | Verilog has always permitted instantiation of modules using named port connections as shown in the alu_accum2 module example.
18.11.3 Instantiation using implicit .name port connections | SystemVerilog adds the capability to implicitly instantiate ports using a .name syntax if the instance-port name and size match the connecting variable-port name and size. This enhancement eliminates the requirement to list a port name twice when the port name and signal name are the same, while still listing all of the ports of the instantiated module for documentation purposes. In the following alu_accum3 example, all of the ports of the instantiated alu module match the names of the variables connected to the ports, except for the unconnected zero port, which is listed using a named port connection, showing that... more
18.11.4 Instantiation using implicit .* port connections | SystemVerilog adds the capability to implicitly instantiate ports using a .* syntax for all ports where the instance-port name and size match the connecting variable-port name and size. This enhancement eliminates the requirement to list any port where the name and size of the connecting variable match the name and size of the instance port. This implicit port connection style is used to indicate that all port names and sizes match the connections where emphasis is placed only on the exception ports. The implicit .* port connection syntax can greatly facilitate rapid block-level testbench generation where all of the testbench... more
链接
第十八章 层次, 主题


18.11.1 Instantiation using positional port connections

链接
18.11 模块实例
SystemVerilog 3.1a语言参考手册
18.11.1 Instantiation using positional port connections
18.11 模块实例

Verilog has always permitted instantiation of modules using positional port connections, as shown in the alu_accum1 module example, below.

Copy Code
module alu_accum1 (
    output [15:0] dataout,
    input [7:0] ain, bin,
    input [2:0] opcode,
    input clk, rst_n);
    wire [7:0] alu_out;
    alu alu (alu_out, , ain, bin, opcode);
    accum accum (dataout[7:0], alu_out, clk, rst_n);
    xtend xtend (dataout[15:8], alu_out[7], clk, rst_n);
endmodule

As long as the connecting variables are ordered correctly and are the same size as the instance-ports that they are connected to, there shall be no warnings and the simulation shall work as expected.

Group

18.11 模块实例

链接
18.11 模块实例


18.11.2 Instantiation using named port connections

链接
18.11 模块实例
SystemVerilog 3.1a语言参考手册
18.11.2 Instantiation using named port connections
18.11 模块实例

Verilog has always permitted instantiation of modules using named port connections as shown in the alu_accum2 module example.

Copy Code
module alu_accum2 (
    output [15:0] dataout,
    input [7:0] ain, bin,
    input [2:0] opcode,
    input clk, rst_n);
    wire [7:0] alu_out;
    alu alu (.alu_out(alu_out), .zero(),
             .ain(ain), .bin(bin), .opcode(opcode));
    accum accum (.dataout(dataout[7:0]), .datain(alu_out),
                 .clk(clk), .rst_n(rst_n));
    xtend xtend (.dout(dataout[15:8]), .din(alu_out[7]),
                 .clk(clk), .rst_n(rst_n));
endmodule

Named port connections do not have to be ordered the same as the ports of the instantiated module. The variables connected to the instance ports must be the same size or a port-size mismatch warning shall be reported.

Group

18.11 模块实例

链接
18.11 模块实例


18.11.3 Instantiation using implicit .name port connections

链接
18.11 模块实例
SystemVerilog 3.1a语言参考手册
18.11.3 Instantiation using implicit .name port connections
18.11 模块实例

SystemVerilog adds the capability to implicitly instantiate ports using a .name syntax if the instance-port name and size match the connecting variable-port name and size. This enhancement eliminates the requirement to list a port name twice when the port name and signal name are the same, while still listing all of the ports of the instantiated module for documentation purposes.

In the following alu_accum3 example, all of the ports of the instantiated alu module match the names of the variables connected to the ports, except for the unconnected zero port, which is listed using a named port connection, showing that the port is unconnected. Implicit .name port connections are made for all name and size matching connections on the instantiated module.

In the same alu_accum3 example, the accum module has an 8-bit port called dataout that is connected to a 16-bit bus called dataout. Because the internal and external sizes of dataout do not match, the port must be connected by name, showing which bits of the 16-bit bus are connected to the 8-bit port. The datain port on the accum is connected to a bus by a different name (alu_out), so this port is also connected by name. The clk and rst_n ports are connected using implicit .name port connections. Also in the same alu_accum3 example, the xtend module has an 8-bit output port called dout and a 1- bit input port called din. Since neither of these port names match the names (or sizes) of the connecting variables, both are connected by name. The clk and rst_n ports are connected using implicit .name port connections.

Copy Code
module alu_accum3 (
    output [15:0] dataout,
    input [7:0] ain, bin,
    input [2:0] opcode,
    input clk, rst_n);
    wire [7:0] alu_out;
    alu alu (.alu_out, .zero(), .ain, .bin, .opcode);
    accum accum (.dataout(dataout[7:0]), .datain(alu_out), .clk, .rst_n);
    xtend xtend (.dout(dataout[15:8]), .din(alu_out[7]), .clk, .rst_n);
endmodule

A .port_identifier port connection is semantically equivalent to the named port connection .port_identifier(name) port connection with the following exceptions:

  • The identifier referenced by .port_identifier shall not create an implicit wire declaration.
  • It shall be illegal for a .port_identifier port connection to create an implicit cast. This includes truncation or padding.
  • A conversion between a 2-state and 4-state type of the same bit length is a legitimate cast.
  • A port connection between a net type and a variable type of the same bit length is a legitimate cast.
  • It shall be an error if a .port_identifier port connection between two dissimilar net types would generate a warning message as required by the Verilog-2001 standard.

Group

18.11 模块实例

链接
18.11 模块实例


18.11.4 Instantiation using implicit .* port connections

链接
18.11 模块实例
SystemVerilog 3.1a语言参考手册
18.11.4 Instantiation using implicit .* port connections
18.11 模块实例

SystemVerilog adds the capability to implicitly instantiate ports using a .* syntax for all ports where the instance-port name and size match the connecting variable-port name and size. This enhancement eliminates the requirement to list any port where the name and size of the connecting variable match the name and size of the instance port. This implicit port connection style is used to indicate that all port names and sizes match the connections where emphasis is placed only on the exception ports. The implicit .* port connection syntax can greatly facilitate rapid block-level testbench generation where all of the testbench variables are chosen to match the instantiated module port names and sizes.

In the following alu_accum4 example, all of the ports of the instantiated alu module match the names of the variables connected to the ports, except for the unconnected zero port, which is listed using a named port connection, showing that the port is unconnected. The implicit .* port connection syntax connects all other ports on the instantiated module.

In the same alu_accum4 example, the accum module has an 8-bit port called dataout that is connected to a 16-bit bus called dataout. Because the internal and external sizes of dataout do not match, the port must be connected by name, showing which bits of the 16-bit bus are connected to the 8-bit port. The datain port on the accum is connected to a bus by a different name (alu_out), so this port is also connected by name. The clk and rst_n ports are connected using implicit .* port connections. Also in the same alu_accum4 example, the xtend module has an 8-bit output port called dout and a 1- bit input port called din. Since neither of these port names match the names (or sizes) of the connecting variables, both are connected by name. The clk and rst_n ports are connected using implicit .* port connections.

Copy Code
module alu_accum4 (
    output [15:0] dataout,
    input [7:0] ain, bin,
    input [2:0] opcode,
    input clk, rst_n);
    wire [7:0] alu_out;
    alu alu (.*, .zero());
    accum accum (.*, .dataout(dataout[7:0]), .datain(alu_out));
    xtend xtend (.*, .dout(dataout[15:8]), .din(alu_out[7]));
endmodule

An implicit .* port connection is semantically equivalent to a default .name port connection for every port declared in the instantiated module. A named port connection can be mixed with a .* connection to override the port connection to a different expression or to leave the port unconnected.

When the implicit .* port connection is mixed in the same instantiation with named port connections, the implicit .* port connection token can be placed anywhere in the port list. The .* token can only appear at most once in the port list.

Modules can be instantiated into the same parent module using any combination of legal positional, named, implicit .name connected and implicit .* connected instances as shown in alu_accum5 example.

Copy Code
module alu_accum5 (
    output [15:0] dataout,
    input [7:0] ain, bin,
    input [2:0] opcode,
    input clk, rst_n);
    wire [7:0] alu_out;
    // mixture of named port connections and
    // implicit .name port connections
    alu alu (.ain(ain), .bin(bin), .alu_out, .zero(), .opcode);
    // positional port connections
    accum accum (dataout[7:0], alu_out, clk, rst_n);
    // mixture of named port connections and implicit .* port connections
    xtend xtend (.dout(dataout[15:8]), .*, .din(alu_out[7]));
endmodule
Group

18.11 模块实例

链接
18.11 模块实例


18.12 端口连接规则

链接
第十八章 层次, 主题
SystemVerilog 3.1a语言参考手册
18.12 端口连接规则
第十八章 层次 | 主题

通过允许所有变量数据类型都能够通过端口传递，SystemVerilog扩展了Verilog的端口连接能力。通过允许端口连接的两侧具有相同的兼容类型，并且通过允许对变量的连续赋值，SystemVerilog做到了这一点。SystemVerilog还产生了一个新的端口限定符类型，ref，它允许共享的变量通过传递一个层次化的引用来跨越一个端口。

Group

第十八章 层次

主题
主题
描述
18.12.1 变量的端口连接规则
如果一个端口声明具有一个变量数据类型，那么它的方向控制端口实例如何连接，变量的端口连接规则如下：
  • 一个输入端口可以连接到一个兼容类型的任意表达式。A continuous assignment shall be implied when a variable is connected to an input port declaration. Assignments to variables declared as an input port shall be illegal. If left unconnected, the port shall have the default initial value corresponding to the data type.
  • An output port can be connected to a variable (or a concatenation) of a compatible data type. A continuous assignment shall be implied when a variable is connected the output port of an instance. Procedural or continuous assignments to a variable connected to the output port of an instance shall be illegal.
  • An output port can... more
18.12.2 线网的端口连接规则
If a port declaration has a wire type (which is the default), or any other net type, then its direction controls how it can be connected as follows:
  • An input can be connected to any expression of a compatible data type. If left unconnected, it shall have the value 'z.
  • An output can be connected to a net type (or a concatenation of net types) or a compatible variable type (or a concatenation of variable types).
  • An inout can be connected to a net type (or a concatenation of net types) or left unconnected, but not to a variable type.... more
18.12.3 接口的端口连接规则
A port declaration can be a generic interface or named interface type. An interface port instance must always be connected to an interface instance or a higher-level interface port. An interface port cannot be left unconnected.

If a port declaration has a generic interface type, then it can be connected to an interface instance of any type. If a port declaration has a named interface type, then it must be connected to an interface instance of the identical type.
18.12.4 兼容的端口类型
The same rules for assignment compatibility are used for compatible port types for ports declared as an input or an output variable, or for output ports connected to variables. SystemVerilog does not change any of the other port connection compatibility rules
18.12.5 非压缩数组端口与实例数组
For an unpacked array port, the port and the array connected to the port must have the same number of unpacked dimensions, and each dimension of the port must have the same size as the corresponding dimension of the array being connected.

If the size and type of the port connection match the size and type of a single instance port, the connection shall be made to each instance in an array of instances.

If the port connection is an unpacked array, the unpacked array dimensions of each port connection shall be compared with the dimensions of the instance array.... more
链接
第十八章 层次, 主题


18.12.1 变量的端口连接规则

链接
18.12 端口连接规则
SystemVerilog 3.1a语言参考手册
18.12.1 变量的端口连接规则
18.12 端口连接规则

如果一个端口声明具有一个变量数据类型，那么它的方向控制端口实例如何连接，变量的端口连接规则如下：

  • 一个输入端口可以连接到一个兼容类型的任意表达式。A continuous assignment shall be implied when a variable is connected to an input port declaration. Assignments to variables declared as an input port shall be illegal. If left unconnected, the port shall have the default initial value corresponding to the data type.
  • An output port can be connected to a variable (or a concatenation) of a compatible data type. A continuous assignment shall be implied when a variable is connected the output port of an instance. Procedural or continuous assignments to a variable connected to the output port of an instance shall be illegal.
  • An output port can be connected to a net (or a concatenation) of a compatible data type. In this case, multiple drivers shall be permitted on the net as in Verilog-2001.
  • A variable data type is not permitted on either side of an inout port.
  • A ref port shall be connected to an equivalent variable data type. References to the port variable shall be treated as hierarchal references to the variable it is connected to in its instantiation. This kind of port cannot be left unconnected. See Section 5.8.1, Equivalent types.

Group

18.12 端口连接规则

链接
18.12 端口连接规则


18.12.2 线网的端口连接规则

链接
18.12 端口连接规则
SystemVerilog 3.1a语言参考手册
18.12.2 线网的端口连接规则
18.12 端口连接规则

If a port declaration has a wire type (which is the default), or any other net type, then its direction controls how it can be connected as follows:

  • An input can be connected to any expression of a compatible data type. If left unconnected, it shall have the value 'z.
  • An output can be connected to a net type (or a concatenation of net types) or a compatible variable type (or a concatenation of variable types).
  • An inout can be connected to a net type (or a concatenation of net types) or left unconnected, but not to a variable type.
Note that where the data types differ between the port declaration and connection, an initial value change event can be caused at time zero.

Group

18.12 端口连接规则

链接
18.12 端口连接规则


18.12.3 接口的端口连接规则

链接
18.12 端口连接规则
SystemVerilog 3.1a语言参考手册
18.12.3 接口的端口连接规则
18.12 端口连接规则

A port declaration can be a generic interface or named interface type. An interface port instance must always be connected to an interface instance or a higher-level interface port. An interface port cannot be left unconnected.

If a port declaration has a generic interface type, then it can be connected to an interface instance of any type. If a port declaration has a named interface type, then it must be connected to an interface instance of the identical type.

Group

18.12 端口连接规则

链接
18.12 端口连接规则


18.12.4 兼容的端口类型

链接
18.12 端口连接规则
SystemVerilog 3.1a语言参考手册
18.12.4 兼容的端口类型
18.12 端口连接规则

The same rules for assignment compatibility are used for compatible port types for ports declared as an input or an output variable, or for output ports connected to variables. SystemVerilog does not change any of the other port connection compatibility rules

Group

18.12 端口连接规则

链接
18.12 端口连接规则


18.12.5 非压缩数组端口与实例数组

链接
18.12 端口连接规则
SystemVerilog 3.1a语言参考手册
18.12.5 非压缩数组端口与实例数组
18.12 端口连接规则

For an unpacked array port, the port and the array connected to the port must have the same number of unpacked dimensions, and each dimension of the port must have the same size as the corresponding dimension of the array being connected.

If the size and type of the port connection match the size and type of a single instance port, the connection shall be made to each instance in an array of instances.

If the port connection is an unpacked array, the unpacked array dimensions of each port connection shall be compared with the dimensions of the instance array. If they match exactly in size, each element of the port connection shall be matched to the port left index to left index, right index to right index. If they do not match it shall be considered an error.

If the port connection is a packed array, each instance shall get a part-select of the port connection, starting with all right-hand indices to match the right most part-select, and iterating through the right most dimension first. Too many or too few bits to connect all the instances shall be considered an error.

Group

18.12 端口连接规则

链接
18.12 端口连接规则


18.13 命名空间

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.13 命名空间
第十八章 层次

SystemVerilog has eight name spaces for identifiers, two are global (definitions name space and package name space), two are global to the compilation unit (compilation unit name space and text macro name space) and four are local. The eight name spaces are described as follows:

  1. The definitions name space unifies all the non-nested module, macromodule, primitive, program, and interface identifiers defined outside of all other declarations. Once a name is used to define a module, macromodule, primitive, program, or interface within one compilation unit the name shall not be used again (in any compilation unit) to declare another non-nested module, macromodule, primitive, program, or interface outside of all other declarations. This is compatible with the definitions name space as defined in IEEE 1364-2001.
  2. The package name space unifies all the package identifiers defined among all compilation units. Once a name is used to define a package within one compilation unit the name shall not be used again to declare another package within any compilation unit.
  3. The compilation-unit scope name space exists outside the module, macromodule, interface, package, program, and primitive constructs. It unifies the definitions of the functions, tasks, parameters, named events, net declarations, variable declarations and user defined types within the compilation-unit scope.
  4. The text macro name space is global within the compilation unit. Since text macro names are introduced and used with a leading ‘ character, they remain unambiguous with any other name space. The text macro names are defined in the linear order of appearance in the set of input files that make up the compilation unit. Subsequent definitions of the same name override the previous definitions for the balance of the input files.
  5. The module name space is introduced by the module, macromodule, interface, package, program, and primitive constructs. It unifies the definition of modules, macromodules, interfaces, programs, functions, tasks, named blocks, instance names, parameters, named events, net declarations, variable declarations and user defined types within the enclosing construct.
  6. The block name space is introduced by named or unnamed blocks, the specify, function, and task constructs. It unifies the definitions of the named blocks, functions, tasks, parameters, named events, variable type of declaration and user defined types within the enclosing construct.
  7. The port name space is introduced by the module, macromodule, interface, primitive, and program constructs. It provides a means of structurally defining connections between two objects that are in two different name spaces. The connection can be unidirectional (either input or output) or bidirectional (inout or ref). The port name space overlaps the module and the block name spaces. Essentially, the port name space specifies the type of connection between names in different name spaces. The port type of declarations includes input, output, inout, and ref. A port name introduced in the port name space can be reintroduced in the module name space by declaring a variable or a net with the same name as the port name.
  8. The attribute name space is enclosed by the (* and *) constructs attached to a language element (see Section 2.8). An attribute name can be defined and used only in the attribute name space. Any other type of name cannot be defined in this name space.

Group

第十八章 层次

链接
第十八章 层次


18.14 层次化的名字

链接
第十八章 层次
SystemVerilog 3.1a语言参考手册
18.14 层次化的名字
第十八章 层次

Hierarchical names are also called nested identifiers. They consist of instance names separated by periods, where an instance name can be an array element. The instance name $root refers to the top of the instantiated design and is used to unambiguously gain access to the top of the design.

Copy Code
$root.mymodule.u1   // absolute name
u1.struct1.field1   // u1 must be visible locally or above, including globally
adder1[5].sum

Nested identifiers can be read (in expressions), written (in assignments or task/function calls) or triggered off (in event expressions). They can also be used as task or function names.

Group

第十八章 层次

链接
第十八章 层次


第十九章 接口

链接
主题
SystemVerilog 3.1a语言参考手册
第十九章 接口
主题
主题
主题 | 描述
19.1 简介（一般信息） | The communication between blocks of a digital system is a critical area that can affect everything from ease of RTL coding, to hardware-software partitioning to performance analysis to bus implementation choices and protocol checking. The interface construct in SystemVerilog was specifically created to encapsulate the communication between blocks, allowing a smooth migration from abstract system-level design through successive refinement down to lower-level register-transfer and structural views of the design. By encapsulating the communication between blocks, the interface construct also facilitates design re-use. The inclusion of interface capabilities is one of the major advantages of SystemVerilog. At its lowest level, an... more
19.2 接口语法 |
19.3 接口中的端口 | One limitation of simple interfaces is that the nets and variables declared within the interface are only used to connect to a port with the same nets and variables. To share an external net or variable, one that makes a connection from outside of the interface as well as forming a common connection to all module ports that instantiate the interface, an interface port declaration is required. The difference between nets or variables in the interface port list and other nets or variables within the interface is that only those in the port list can be connected externally by name... more
19.4 modport | To restrict interface access within a module, there are modport lists with directions declared within the interface. The keyword modport indicates that the directions are declared as if inside the module.
19.5 接口与specify块 | The specify block is used to describe various paths across a module and perform timing checks to ensure that events occurring at the module inputs satisfy the timing constraints of the device described by the module. The module paths are from module input ports to output ports and the timing checks are relative to the module inputs. The specify block refers to these ports as terminal descriptor. Module inout ports can function as either an input or output terminal. When one of the port instances is an interface, each signal in the interface becomes an available terminal, with the default... more
19.6 接口中的任务与函数 | Tasks and functions can be defined within an interface, or they can be defined within one or more of the modules connected. This allows a more abstract level of modeling. For example “read” and “write” can be defined as tasks, without reference to any wires, and the master module can merely call these tasks. In a modport these tasks are declared as import tasks. If a module is connected to a modport containing an exported task or function, and the module does not define that task or function, then an elaboration error shall occur. Similarly if the modport contains an... more
19.7 参数化接口 | Interface definitions can take advantage of parameters and parameter redefinition, in the same manner as module definitions. This example shows how to use parameters in interface definitions.
19.8 虚拟接口 | Virtual interfaces provide a mechanism for separating abstract models and test programs from the actual signals that make up the design. A virtual interface allows the same subprogram to operate on different portions of a design, and to dynamically control the set of signals associated with the subprogram. Instead of referring to the actual set of signals directly, users are able to manipulate a set of virtual signals. Changes to the underlying design do not require the code using virtual interfaces to be re-written. By abstracting the connectivity and functionality of a set of blocks, virtual interfaces promote code-reuse. A... more
19.9 对接口对象的访问 | Access to all objects declared in an interface is always available by hierarchical reference, regardless of whether or not the interface is connected through a port. When an interface is connected with a modport in either the module header or port connection, access by port reference is limited to only those objects listed in the modport, for only those types of objects legal to be listed in modports (nets, variables, tasks, and functions) All objects are still visible by hierarchical reference. For example:
链接
主题


19.1 简介（一般信息）

链接
第十九章 接口
SystemVerilog 3.1a语言参考手册
19.1 简介（一般信息）
第十九章 接口

The communication between blocks of a digital system is a critical area that can affect everything from ease of RTL coding, to hardware-software partitioning to performance analysis to bus implementation choices and protocol checking. The interface construct in SystemVerilog was specifically created to encapsulate the communication between blocks, allowing a smooth migration from abstract system-level design through successive refinement down to lower-level register-transfer and structural views of the design. By encapsulating the communication between blocks, the interface construct also facilitates design re-use. The inclusion of interface capabilities is one of the major advantages of SystemVerilog.

At its lowest level, an interface is a named bundle of nets or variables. The interface is instantiated in a design and can be accessed through a port as a single item, and the component nets or variables referenced where needed. A significant proportion of a Verilog design often consists of port lists and port connection lists, which are just repetitions of names. The ability to replace a group of names by a single name can significantly reduce the size of a description and improve its maintainability.

Additional power of the interface comes from its ability to encapsulate functionality as well as connectivity, making an interface, at its highest level, more like a class template. An interface can have parameters, constants, variables, functions and tasks. The types of elements in an interface can be declared, or the types can be passed in as parameters. The member variables and functions are referenced relative to the instance name of the interface as instance.member. Thus, modules that are connected via an interface can simply call the task/function members of that interface to drive the communication. With the functionality thus encapsulated in the interface, and isolated from the module, the abstraction level and/or granularity of the communication protocol can be easily changed by replacing the interface with a different interface containing the same members but implemented at a different level of abstraction. The modules connected via the interface don’t need to change at all.

To provide direction information for module ports and to control the use of tasks and functions within particular modules, the modport construct is provided. As the name indicates, the directions are those seen from the module.

In addition to task/function methods, an interface can also contain processes (i.e. initial or always blocks) and continuous assignments, which are useful for system-level modeling and testbench applications. This allows the interface to include, for example, its own protocol checker that automatically verifies that all modules connected via the interface conform to the specified protocol. Other applications, such as functional coverage recording and reporting, protocol checking and assertions can also be built into the interface.

The methods can be abstract, i.e. defined in one module and called in another, using the export and import constructs. This could be coded using hierarchical path names, but this would impede re-use because the names would be design-specific. A better way is to declare the task and function names in the interface, and to use local hierarchical names from the interface instance for both definition and call. Broadcast communication is modeled by forkjoin tasks, which can be defined in more than one module and executed concurrently.

Group

第十九章 接口

链接
第十九章 接口


19.2 接口语法

链接
第十九章 接口, 主题
SystemVerilog 3.1a语言参考手册
19.2 接口语法
第十九章 接口 | 主题
Copy Code
interface_declaration ::=      // from Annex A.1.3
    interface_nonansi_header [timeunits_declaration] {interface_item}
        endinterface [: interface_identifier]
  | interface_ansi_header [timeunits_declaration] {non_port_interface_item}
        endinterface [: interface_identifier]
  | {attribute_instance} interface interface_identifier(.*);
        [timeunits_declaration] {interface_item}
    endinterface [: interface_identifier]
  | extern interface_nonansi_header
  | extern interface_ansi_header

interface_nonansi_header ::=
    {attribute_instance} interface [lifetime] interface_identifier
        [parameter_port_list] list_of_ports;

interface_ansi_header ::=
    {attribute_instance} interface [lifetime] interface_identifier
        [parameter_port_list] [list_of_port_declarations];

modport_declaration ::= modport modport_item {, modport_item};  // from Annex A.2.9

modport_item ::= modport_identifier(modport_ports_declaration {, modport_ports_declaration})

modport_ports_declaration ::=
    {attribute_instance} modport_simple_ports_declaration
  | {attribute_instance} modport_hierarchical_ports_declaration
  | {attribute_instance} modport_tf_ports_declaration
  | {attribute_instance} modport_clocking_declaration

modport_clocking_declaration ::= clocking clocking_identifier

modport_simple_ports_declaration ::=
    port_direction modport_simple_port {, modport_simple_port}

modport_simple_port ::=
    port_identifier
  | .port_identifier([expression])

modport_hierarchical_ports_declaration ::=
    interface_instance_identifier[[constant_expression]].modport_identifier

modport_tf_ports_declaration ::=
    import_export modport_tf_port {, modport_tf_port}

modport_tf_port ::=
    method_prototype
  | tf_identifier

import_export ::= import | export

interface_instantiation ::=
    interface_identifier [parameter_value_assignment]
        hierarchical_instance {, hierarchical_instance};     // from Annex A.4.1.2

Syntax 19-1—Interface syntax (excerpt from Annex A)

The interface construct provides a new hierarchical structure. It can contain smaller interfaces and can be passed through ports.

The aim of interfaces is to encapsulate communication. At the lower level, this means bundling variables and wires in interfaces, and can impose access restrictions with port directions in modports. The modules can be made generic so that the interfaces can be changed. The following examples show these features. At a higher level of abstraction, communication can be done by tasks and functions. Interfaces can include task and function definitions, or just task and function prototypes (see Section 19.6.1 An example of using tasks in an interface) with the definition in one module (server/slave) and the call in another (client/master).

A simple interface declaration is as follows (see Syntax 19-1 for the complete syntax):

Copy Code
interface identifier;
    ...
    interface_items
    ...
endinterface [: identifier]

An interface can be instantiated hierarchically like a module, with or without ports. For example:

Copy Code
myinterface #(100) scalar1, vector[9:0];

In this example, 11 instances of the interface of type myinterface have been instantiated and the first parameter within each interface is changed to 100. One myinterface instance is instantiated with the name scalar1, and an array of 10 myinterface interfaces are instantiated with instance names vector[9] to vector[0].

Interfaces can be declared and instantiated in modules (either flat or hierarchical) but modules can neither be declared nor instantiated in interfaces.

The simplest use of an interface is to bundle wires, as is illustrated in the examples below.

Group

第十九章 接口

主题
主题 | 描述
19.2.1 Example without using interfaces | This example shows a simple bus implemented without interfaces. Note that the logic type can replace wire and reg if no resolution of multiple drivers is needed.
19.2.2 Interface example using a named bundle | The simplest form of a SystemVerilog interface is a bundled collection of variables or nets. When an interface is referenced as a port, the variables and nets in it are assumed to have ref and inout access, respectively. The following interface example shows the basic syntax for defining, instantiating and connecting an interface. Usage of the SystemVerilog interface capability can significantly reduce the amount of code required to model port connections.
19.2.3 Interface example using a generic bundle | A module header can be created with an unspecified interface reference as a place-holder for an interface to be selected when the module itself is instantiated. The unspecified interface is referred to as a “generic” interface reference. This generic interface reference can only be declared by using the list of port declaration style of reference. It shall be illegal to declare such a generic interface reference using the old Verilog-1995 list of port style. The following interface example shows how to specify a generic interface reference in a module definition.
链接
第十九章 接口, 主题


19.2.1 Example without using interfaces

链接
19.2 接口语法
SystemVerilog 3.1a语言参考手册
19.2.1 Example without using interfaces
19.2 接口语法

This example shows a simple bus implemented without interfaces. Note that the logic type can replace wire and reg if no resolution of multiple drivers is needed.

Copy Code
module memMod( input    bit req,
                        bit clk,
                        bit start,
                        logic [1:0] mode,
                        logic [7:0] addr,
               inout    wire [7:0] data,
               output   bit gnt,
                        bit rdy );
    logic avail;
    ...
endmodule

module cpuMod(
    input   bit clk,
            bit gnt,
            bit rdy,
    inout   wire [7:0] data,
    output  bit req,
            bit start,
            logic [7:0] addr,
            logic [1:0] mode );
    ...
endmodule

module top;
    logic req, gnt, start, rdy; // req is logic not bit here
    logic clk = 0;
    logic [1:0] mode;
    logic [7:0] addr;
    wire [7:0] data;

    memMod mem(req, clk, start, mode, addr, data, gnt, rdy);

    cpuMod cpu(clk, gnt, rdy, data, req, start, addr, mode);
endmodule
Group

19.2 接口语法

链接
19.2 接口语法


19.2.2 Interface example using a named bundle

链接
19.2 接口语法
SystemVerilog 3.1a语言参考手册
19.2.2 Interface example using a named bundle
19.2 接口语法

The simplest form of a SystemVerilog interface is a bundled collection of variables or nets. When an interface is referenced as a port, the variables and nets in it are assumed to have ref and inout access, respectively. The following interface example shows the basic syntax for defining, instantiating and connecting an interface. Usage of the SystemVerilog interface capability can significantly reduce the amount of code required to model port connections.

Copy Code
interface simple_bus; // Define the interface
    logic req, gnt;
    logic [7:0] addr, data;
    logic [1:0] mode;
    logic start, rdy;
endinterface: simple_bus

module memMod(simple_bus a, // Access the simple_bus interface
              input     bit clk);
    logic avail;
    // When memMod is instantiated in module top, a.req is the req
    // signal in the sb_intf instance of the ’simple_bus’ interface
    always @(posedge clk) a.gnt <= a.req & avail;
endmodule

module cpuMod(simple_bus b, input bit clk);
    ...
endmodule

module top;
    logic clk = 0;
    simple_bus sb_intf(); // Instantiate the interface
    memMod mem(sb_intf, clk); // Connect the interface to the module instance
    cpuMod cpu(.b(sb_intf), .clk(clk)); // Either by position or by name
endmodule

In the preceding example, if the same identifier, sb_intf, had been used to name the simple_bus interface in the memMod and cpuMod module headers, then implicit port declarations also could have been used to instantiate the memMod and cpuMod modules into the top module, as shown below.

Copy Code
module memMod (simple_bus sb_intf, input bit clk);
    ...
endmodule

module cpuMod (simple_bus sb_intf, input bit clk);
    ...
endmodule

module top;
    logic clk = 0;
    simple_bus sb_intf();
    memMod mem (.*); // implicit port connections
    cpuMod cpu (.*); // implicit port connections
endmodule
Group

19.2 接口语法

链接
19.2 接口语法


19.2.3 Interface example using a generic bundle

链接
19.2 接口语法
SystemVerilog 3.1a语言参考手册
19.2.3 Interface example using a generic bundle
19.2 接口语法

A module header can be created with an unspecified interface reference as a place-holder for an interface to be selected when the module itself is instantiated. The unspecified interface is referred to as a “generic” interface reference.

This generic interface reference can only be declared by using the list of port declaration style of reference. It shall be illegal to declare such a generic interface reference using the old Verilog-1995 list of port style.

The following interface example shows how to specify a generic interface reference in a module definition.

Copy Code
// memMod and cpuMod can use any interface
module memMod (interface a, input bit clk);
    ...
endmodule

module cpuMod(interface b, input bit clk);
    ...
endmodule

interface simple_bus; // Define the interface
    logic req, gnt;
    logic [7:0] addr, data;
    logic [1:0] mode;
    logic start, rdy;
endinterface: simple_bus

module top;
    logic clk = 0;
    simple_bus sb_intf(); // Instantiate the interface
    // Reference the sb_intf instance of the simple_bus
    // interface from the generic interfaces of the
    // memMod and cpuMod modules
    memMod mem (.a(sb_intf), .clk(clk));
    cpuMod cpu (.b(sb_intf), .clk(clk));
endmodule

An implicit port cannot be used to reference a generic interface. A named port must be used to reference a generic interface, as shown below.

Copy Code
module memMod (interface a, input bit clk);
    ...
endmodule

module cpuMod (interface b, input bit clk);
    ...
endmodule

module top;
    logic clk = 0;
    simple_bus sb_intf();
    memMod mem (.*, .a(sb_intf)); // partial implicit port connections
    cpuMod cpu (.*, .b(sb_intf)); // partial implicit port connections
endmodule
Group

19.2 接口语法

链接
19.2 接口语法


19.3 接口中的端口

链接
第十九章 接口
SystemVerilog 3.1a语言参考手册
19.3 接口中的端口
第十九章 接口

One limitation of simple interfaces is that the nets and variables declared within the interface are only used to connect to a port with the same nets and variables. To share an external net or variable, one that makes a connection from outside of the interface as well as forming a common connection to all module ports that instantiate the interface, an interface port declaration is required. The difference between nets or variables in the interface port list and other nets or variables within the interface is that only those in the port list can be connected externally by name or position when the interface is instantiated.

Copy Code
interface i1 (input a, output b, inout c);
    wire d;
endinterface

The wires a, b and c can be individually connected to the interface and thus shared with other interfaces.

The following example shows how to specify an interface with inputs, allowing a wire to be shared between two instances of the interface.

Copy Code
interface simple_bus (input bit clk); // Define the interface
    logic req, gnt;
    logic [7:0] addr, data;
    logic [1:0] mode;
    logic start, rdy;
endinterface: simple_bus

module memMod(simple_bus a); // Uses just the interface
    logic avail;

    always @(posedge a.clk) // the clk signal from the interface
        a.gnt <= a.req & avail; // a.req is in the ’simple_bus’ interface
endmodule

module cpuMod(simple_bus b);
    ...
endmodule

module top;
    logic clk = 0;
    simple_bus sb_intf1(clk); // Instantiate the interface
    simple_bus sb_intf2(clk); // Instantiate the interface
    memMod mem1(.a(sb_intf1)); // Reference simple_bus 1 to memory 1
    cpuMod cpu1(.b(sb_intf1));
    memMod mem2(.a(sb_intf2)); // Reference simple_bus 2 to memory 2
    cpuMod cpu2(.b(sb_intf2));
endmodule

Note: Because the instantiated interface names do not match the interface names used in the memMod and cpuMod modules, implicit port connections cannot be used for this example.

Group

第十九章 接口

链接
第十九章 接口


19.4 modport

链接
第十九章 接口, 主题
SystemVerilog 3.1a语言参考手册
19.4 modport
第十九章 接口 | 主题

To restrict interface access within a module, there are modport lists with directions declared within the interface. The keyword modport indicates that the directions are declared as if inside the module.

Copy Code
interface i2;
    wire a, b, c, d;
    modport master (input a, b, output c, d);
    modport slave (output a, b, input c, d);
endinterface

In this example, the modport list name (master or slave) can be specified in the module header, where the interface name selects an interface and the modport name selects the appropriate directional information for the interface signals accessed in the module header.

Copy Code
module m (i2.master i);
    ...
endmodule

module s (i2.slave i);
    ...
endmodule

module top;
    i2 i();
    m u1(.i(i));
    s u2(.i(i));
endmodule

The syntax of interface_name.modport_name reference_name gives a local name for a hierarchical reference. Note that this can be generalized to any interface with a given modport name by writing interface.modport_name reference_name. The modport list name (master or slave) can also be specified in the port connection with the module instance, where the modport name is hierarchical from the interface instance.

Copy Code
module m (i2 i);
    ...
endmodule

module s (i2 i);
    ...
endmodule

module top;
    i2 i();
    m u1(.i(i.master));
    s u2(.i(i.slave));
endmodule

If a port connection specifies a modport list name in both the module instance and module header declaration, then the two modport list names shall be identical.

In a hierarchically nested interface, the directions in a modport declaration can themselves be modport plus name.

Copy Code
interface i1;
    interface i3;
        wire a, b, c, d;
        modport master (input a, b, output c, d);
        modport slave (output a, b, input c, d);
    endinterface
    i3 ch1(), ch2();
    modport master2 (ch1.master, ch2.master);
endinterface

All of the names used in a modport declaration shall be declared by the same interface as is the modport itself. In particular, the names used shall not be those declared by another enclosing interface, and a modport declaration shall not implicitly declare new ports. No hierarchical references shall be permitted within a modport.

The following interface declarations would be illegal:

Copy Code
interface i;
    wire x, y;
    interface illegal_i;
        wire a, b, c, d;
        // x, y not declared by this interface
        modport master(input a, b, x, output c, d, y);
        modport slave(input a, b, x, output c, d, y);
    endinterface : illegal_i
    illegal_i ch1(), ch2();
    modport master2 (ch1.master, ch2.master);
endinterface : i

interface illegal_i;
    // a, b, c, d not declared by this interface
    modport master(input a, b, output c, d);
    modport slave(output a, b, output c, d);
endinterface : illegal_i

Note that if no modport is specified in the module header or in the port connection, then all the nets and variables in the interface are accessible with direction inout or ref, as in the examples above.

Group

第十九章 接口

主题
主题 | 描述
19.4.1 An example of a named port bundle | This interface example shows how to use modports to control signal directions as in port declarations. It uses the modport name in the module definition.
19.4.2 An example of connecting a port bundle | This interface example shows how to use modports to restrict interface signal access and control their direction. It uses the modport name in the module instantiation.
19.4.3 An example of connecting a port bundle to a generic interface | This interface example shows how to use modports to control signal directions. It shows the use of the interface keyword in the module definition. The actual interface and modport are specified in the module instantiation.
19.4.4 Modport expressions | A modport expression allows elements of arrays and structures, concatenations of elements, aggregate expressions of elements declared in an interface to be included in a modport list. This modport expression is explicitly named with a port identifier, visible only through the modport connection. Like explicitly named ports in a module port declaration, port identifiers exist in their own namespace for each modport list. When modport item is just a simple port identifier, that identifier is used as both a reference to an interface item and a port identifier. Once a port identifier has been defined, there shall not be another... more
19.4.5 Clocking blocks and modports | The modport construct can also be used to specify the direction of clocking blocks declared within an interface. As with other modport declarations, the directions of the clocking block are those seen from the module in which the interface becomes a port. The syntax for this is shown below.
链接
第十九章 接口, 主题


19.4.1 An example of a named port bundle

链接
19.4 modport
SystemVerilog 3.1a语言参考手册
19.4.1 An example of a named port bundle
19.4 modport

This interface example shows how to use modports to control signal directions as in port declarations. It uses the modport name in the module definition.

Copy Code
interface simple_bus (input bit clk); // Define the interface
    logic req, gnt;
    logic [7:0] addr, data;
    logic [1:0] mode;
    logic start, rdy;
    modport slave (input req, addr, mode, start, clk,
                   output gnt, rdy,
                   ref data);
    modport master(input gnt, rdy, clk,
                   output req, addr, mode, start,
                   ref data);
endinterface: simple_bus

module memMod (simple_bus.slave a); // interface name and modport name
    logic avail;

    always @(posedge a.clk) // the clk signal from the interface
        a.gnt <= a.req & avail; // the gnt and req signal in the interface
endmodule

module cpuMod (simple_bus.master b);
    ...
endmodule

module top;
    logic clk = 0;
    simple_bus sb_intf(clk); // Instantiate the interface
    initial repeat(10) #10 clk++;
    memMod mem(.a(sb_intf)); // Connect the interface to the module instance
    cpuMod cpu(.b(sb_intf));
endmodule
Group

19.4 modport

链接
19.4 modport


19.4.2 An example of connecting a port bundle

链接
19.4 modport
SystemVerilog 3.1a语言参考手册
19.4.2 An example of connecting a port bundle
19.4 modport

This interface example shows how to use modports to restrict interface signal access and control their direction. It uses the modport name in the module instantiation.

Copy Code
interface simple_bus (input bit clk); // Define the interface
    logic req, gnt;
    logic [7:0] addr, data;
    logic [1:0] mode;
    logic start, rdy;
    modport slave (input req, addr, mode, start, clk,
                   output gnt, rdy,
                   ref data);
    modport master(input gnt, rdy, clk,
                   output req, addr, mode, start,
                   ref data);
endinterface: simple_bus

module memMod(simple_bus a); // Uses just the interface name
    logic avail;
    always @(posedge a.clk) // the clk signal from the interface
        a.gnt <= a.req & avail; // the gnt and req signal in the interface
endmodule

module cpuMod(simple_bus b);
    ...
endmodule

module top;
    logic clk = 0;
    simple_bus sb_intf(clk); // Instantiate the interface
    initial repeat(10) #10 clk++;
    memMod mem(sb_intf.slave); // Connect the modport to the module instance
    cpuMod cpu(sb_intf.master);
endmodule
Group

19.4 modport

链接
19.4 modport


19.4.3 An example of connecting a port bundle to a generic interface

链接
19.4 modport
SystemVerilog 3.1a语言参考手册
19.4.3 An example of connecting a port bundle to a generic interface
19.4 modport

This interface example shows how to use modports to control signal directions. It shows the use of the interface keyword in the module definition. The actual interface and modport are specified in the module instantiation.

Copy Code
interface simple_bus (input bit clk); // Define the interface
    logic req, gnt;
    logic [7:0] addr, data;
    logic [1:0] mode;
    logic start, rdy;
    modport slave (input req, addr, mode, start, clk,
                   output gnt, rdy,
                   ref data);
    modport master(input gnt, rdy, clk,
                   output req, addr, mode, start,
                   ref data);
endinterface: simple_bus

module memMod(interface a); // Uses just the interface
    logic avail;
    always @(posedge a.clk) // the clk signal from the interface
        a.gnt <= a.req & avail; // the gnt and req signal in the interface
endmodule

module cpuMod(interface b);
    ...
endmodule

module top;
    logic clk = 0;
    simple_bus sb_intf(clk); // Instantiate the interface
    memMod mem(sb_intf.slave); // Connect the modport to the module instance
    cpuMod cpu(sb_intf.master);
endmodule
Group

19.4 modport

链接
19.4 modport


19.4.4 Modport expressions

链接
19.4 modport
SystemVerilog 3.1a语言参考手册
19.4.4 Modport expressions
19.4 modport

A modport expression allows elements of arrays and structures, concatenations of elements, aggregate expressions of elements declared in an interface to be included in a modport list. This modport expression is explicitly named with a port identifier, visible only through the modport connection.

Like explicitly named ports in a module port declaration, port identifiers exist in their own namespace for each modport list. When modport item is just a simple port identifier, that identifier is used as both a reference to an interface item and a port identifier. Once a port identifier has been defined, there shall not be another port definition with this same name.

For example:

Copy Code
interface I;
    logic [7:0] r;
    const int x=1;
    bit R;
    modport A (output .P(r[3:0]), input .Q(x), R);
    modport B (output .P(r[7:4]), input .Q(2), R);
endinterface

module M ( interface i);,
    initial i.P = i.Q;
endmodule

module top;
    I i1;
    M u1 (i1.A);
    M u2 (i1.B);
    initial #1 $display("%b", i1.r); // displays 00010010
endmodule

The self-determined type of the port expression becomes the type for the port. If the port expression is to be an aggregate expression, then a cast must be used since self-determined aggregate expressions are not allowed. The port expression must resolve to a legal expression for type of module port (See section 18.12—Port connection rules). In the example above, the Q port could not be an output or inout because the port expression is a constant. The port expression is optional because ports can be defined that do not connect to anything internal to the port.

Group

19.4 modport

链接
19.4 modport


19.4.5 Clocking blocks and modports

链接
19.4 modport
SystemVerilog 3.1a语言参考手册
19.4.5 Clocking blocks and modports
19.4 modport

The modport construct can also be used to specify the direction of clocking blocks declared within an interface. As with other modport declarations, the directions of the clocking block are those seen from the module in which the interface becomes a port. The syntax for this is shown below.

Copy Code
modport_declaration ::= modport modport_item {, modport_item};  // from Annex A.2.9

modport_item ::= modport_identifier(modport_ports_declaration {, modport_ports_declaration})

modport_ports_declaration ::=
    {attribute_instance} modport_simple_ports_declaration
  | {attribute_instance} modport_hierarchical_ports_declaration
  | {attribute_instance} modport_tf_ports_declaration
  | {attribute_instance} modport_clocking_declaration

modport_clocking_declaration ::= clocking clocking_identifier

Syntax 19-2—modport clocking declaration syntax (excerpt from Annex A)

All of the clocking blocks used in a modport declaration shall be declared by the same interface as is the modport itself. Like all modport declarations, the direction of the clocking signals are those seen from the module in which the interface becomes a port. The example below shows how modports can be used to create both synchronous as well as asynchronous ports. When used in conjunction with virtual interfaces (see Section 19.8.2), these constructs facilitate the creation of abstract synchronous models.

Copy Code
interface A_Bus( input bit clk );
    wire req, gnt;
    wire [7:0] addr, data;
    clocking sb @(posedge clk);
        input gnt;
        output req, addr;
        inout data;
        property p1; req ##[1:3] gnt; endproperty
    endclocking

    modport DUT (input clk, req, addr, // Device under test modport
                 output gnt,
                 inout data );

    modport STB (clocking sb); // synchronous testbench modport
    modport TB (input gnt, // asynchronous testbench modport
                output req, addr,
                inout data );
endinterface

The above interface A_Bus can then be instantiated as shown below:

Copy Code
module dev1(A_Bus.DUT b); // Some device: Part of the design
    ...
endmodule

module dev2(A_Bus.DUT b); // Some device: Part of the design
    ...
endmodule

module top;
    bit clk;
    A_Bus b1( clk );
    A_Bus b2( clk );
    dev1 d1( b1 );
    dev2 d2( b2 );
    T tb( b1, b2 );
endmodule

program T (A_Bus.STB b1, A_Bus.STB b2 ); // Testbench: 2 synchronous ports
    assert property (b1.p1); // assert property from within program
    initial begin
        b1.sb.req <= 1;
        wait( b1.sb.gnt == 1 );
        ...
        b1.sb.req <= 0;
        b2.sb.req <= 1;
        wait( b2.sb.gnt == 1 );
        ...
        b2.sb.req <= 0;
    end
endprogram

The example above shows the program block using the synchronous interface designated by the clockingmodport of interface ports b1 and b2. In addition to the procedural drives and samples of the clocking block signals, the program asserts the property p1 of one of its interfaces b1.

Group

19.4 modport

链接
19.4 modport


19.5 接口与specify块

链接
第十九章 接口
SystemVerilog 3.1a语言参考手册
19.5 接口与specify块
第十九章 接口

The specify block is used to describe various paths across a module and perform timing checks to ensure that events occurring at the module inputs satisfy the timing constraints of the device described by the module. The module paths are from module input ports to output ports and the timing checks are relative to the module inputs. The specify block refers to these ports as terminal descriptor. Module inout ports can function as either an input or output terminal. When one of the port instances is an interface, each signal in the interface becomes an available terminal, with the default direction as defined for an interface, or as restricted by a modport. A ref port cannot be used as a terminal in a specify block.

The following shows an example of using interfaces together with a specify block:

Copy Code
interface itf;
    logic c,q,d;
    modport flop (input c,d, output q);
endinterface

module dtype (itf.flop ch);
    always_ff @(posedge ch.c) ch.q <= ch.d;
    specify
        ( posedge ch.c => (ch.q+:ch.d)) = (5,6);
        $setup( ch.d, posedge ch.c, 1 );
    endspecify
endmodule
Group

第十九章 接口

链接
第十九章 接口


19.6 接口中的任务与函数

链接
第十九章 接口, 主题
SystemVerilog 3.1a语言参考手册
19.6 接口中的任务与函数
第十九章 接口 | 主题

Tasks and functions can be defined within an interface, or they can be defined within one or more of the modules connected. This allows a more abstract level of modeling. For example “read” and “write” can be defined as tasks, without reference to any wires, and the master module can merely call these tasks. In a modport these tasks are declared as import tasks.

If a module is connected to a modport containing an exported task or function, and the module does not define that task or function, then an elaboration error shall occur. Similarly if the modport contains an exported task or function prototype, and the task or function defined in the module does not exactly match that prototype, then an elaboration error shall occur.

If the tasks or functions are defined in a module, using a hierarchical name, they must also be declared as extern in the interface, or as export in a modport.

Tasks (not functions) can be defined in a module that is instantiated twice, e.g. two memories driven from the same CPU. Such multiple task definitions are allowed by a forkjoin extern declaration in the interface.

Group

第十九章 接口

主题
主题 | 描述
19.6.1 An example of using tasks in an interface |
19.6.2 An example of using tasks in modports | This interface example shows how to use modports to control signal directions and task access in a full read/write interface.
19.6.3 An example of exporting tasks and functions | This interface example shows how to define tasks in one module and call them in another, using modports to control task access.
19.6.4 An example of multiple task exports | It is normally an error for more than one module to export the same task name. However, several instances of the same modport type can be connected to an interface, such as memory modules in the previous example. So that these can still export their read and write tasks, the tasks must be declared in the interface using the extern forkjoin keywords. The call to extern forkjoin task countslaves( ); in the example below behaves as:
链接
第十九章 接口, 主题


19.6.1 An example of using tasks in an interface

链接
19.6 接口中的任务与函数
SystemVerilog 3.1a语言参考手册
19.6.1 An example of using tasks in an interface
19.6 接口中的任务与函数
Copy Code
interface simple_bus (input bit clk); // Define the interface
    logic req, gnt;
    logic [7:0] addr, data;
    logic [1:0] mode;
    logic start, rdy;

    task masterRead(input logic [7:0] raddr); // masterRead method
        // ...
    endtask: masterRead

    task slaveRead; // slaveRead method
        // ...
    endtask: slaveRead
endinterface: simple_bus

module memMod(interface a); // Uses any interface
    logic avail;

    always @(posedge a.clk) // the clk signal from the interface
        a.gnt <= a.req & avail // the gnt and req signals in the interface

    always @(a.start)
        a.slaveRead;
endmodule

module cpuMod(interface b);
    enum {read, write} instr;
    logic [7:0] raddr;

    always @(posedge b.clk)
        if (instr == read)

    b.masterRead(raddr); // call the Interface method
    ...
endmodule

module top;
    logic clk = 0;
    simple_bus sb_intf(clk); // Instantiate the interface
    memMod mem(sb_intf);
    cpuMod cpu(sb_intf);
endmodule

A function prototype specifies the types and directions of the arguments and the return value of a function which is defined elsewhere. Similarly, a task prototype specifies the types and directions of the arguments of a task which is defined elsewhere. In a modport, the import and export constructs can either use task or function prototypes or use just the identifiers. The only exception is when a modport is used to import a function or task from another module, in which case a full prototype shall be used.

The number and types of arguments in a prototype must match the argument types in the function or task declaration. The rules for type equivalency are described in Section 5.8.1, Equivalent types.

Group

19.6 接口中的任务与函数

链接
19.6 接口中的任务与函数


19.6.2 An example of using tasks in modports

链接
19.6 接口中的任务与函数
SystemVerilog 3.1a语言参考手册
19.6.2 An example of using tasks in modports
19.6 接口中的任务与函数

This interface example shows how to use modports to control signal directions and task access in a full read/write interface.

Copy Code
interface simple_bus (input bit clk); // Define the interface
    logic req, gnt;
    logic [7:0] addr, data;
    logic [1:0] mode;
    logic start, rdy;

    modport slave (input req, addr, mode, start, clk,
                   output gnt, rdy,
                   ref data,
                   import task slaveRead(),
                          task slaveWrite());
                   // import into module that uses the modport

    modport master(input gnt, rdy, clk,
                   output req, addr, mode, start,
                   ref data,
                   import masterRead,
                          masterWrite);
                   // import into module that uses the modport

    task masterRead(input logic [7:0] raddr); // masterRead method
        // ...
    endtask

    task slaveRead; // slaveRead method
        // ...
    endtask

    task masterWrite(input logic [7:0] waddr);
        //...
    endtask

    task slaveWrite;
        //...
    endtask
endinterface: simple_bus

module memMod(interface a); // Uses just the interface
    logic avail;

    always @(posedge a.clk) // the clk signal from the interface
        a.gnt <= a.req & avail; // the gnt and req signals in the interface

    always @(a.start)
        if (a.mode[0] == 1’b0)
            a.slaveRead;
        else
            a.slaveWrite;
endmodule

module cpuMod(interface b);
    enum {read, write} instr = $rand();
    logic [7:0] raddr = $rand();

    always @(posedge b.clk)
        if (instr == read)
            b.masterRead(raddr); // call the Interface method
            // ...
        else
            b.masterWrite(raddr);
endmodule

module omniMod( interface b);
    //...
endmodule: omniMod

module top;
    logic clk = 0;
    simple_bus sb_intf(clk); // Instantiate the interface
    memMod mem(sb_intf.slave); // only has access to the slave tasks
    cpuMod cpu(sb_intf.master); // only has access to the master tasks
    omniMod omni(sb_intf); // has access to all master and slave tasks
endmodule
Group

19.6 接口中的任务与函数

链接
19.6 接口中的任务与函数


19.6.3 An example of exporting tasks and functions

链接
19.6 接口中的任务与函数
SystemVerilog 3.1a语言参考手册
19.6.3 An example of exporting tasks and functions
19.6 接口中的任务与函数

This interface example shows how to define tasks in one module and call them in another, using modports to control task access.

Copy Code
interface simple_bus (input bit clk); // Define the interface
    logic req, gnt;
    logic [7:0] addr, data;
    logic [1:0] mode;
    logic start, rdy;

    modport slave( input req, addr, mode, start, clk,
                   output gnt, rdy,
                   ref data,
                   export task Read(),
                   task Write());
                   // export from module that uses the modport

    modport master(input gnt, rdy, clk,
                   output req, addr, mode, start,
                   ref data,
                   import task Read(input logic [7:0] raddr),
                          task Write(input logic [7:0] waddr));
                   // import requires the full task prototype
endinterface: simple_bus

module memMod(interface a); // Uses just the interface keyword
    logic avail;

    task a.Read; // Read method
        avail = 0;
        ...
        avail = 1;
    endtask

    task a.Write;
        avail = 0;
        ...
        avail = 1;
    endtask
endmodule

module cpuMod(interface b);
    enum {read, write} instr;
    logic [7:0] raddr;

    always @(posedge b.clk)
        if (instr == read)
            b.Read(raddr); // call the slave method via the interface
            ...
        else
            b.Write(raddr);
endmodule

module top;
    logic clk = 0;
    simple_bus sb_intf(clk); // Instantiate the interface
    memMod mem(sb_intf.slave); // exports the Read and Write tasks
    cpuMod cpu(sb_intf.master); // imports the Read and Write tasks
endmodule
Group

19.6 接口中的任务与函数

链接
19.6 接口中的任务与函数


19.6.4 An example of multiple task exports

链接
19.6 接口中的任务与函数
SystemVerilog 3.1a语言参考手册
19.6.4 An example of multiple task exports
19.6 接口中的任务与函数

It is normally an error for more than one module to export the same task name. However, several instances of the same modport type can be connected to an interface, such as memory modules in the previous example. So that these can still export their read and write tasks, the tasks must be declared in the interface using the extern forkjoin keywords.

The call to extern forkjoin task countslaves( ); in the example below behaves as:

Copy Code
fork
    top.mem1.a.countslaves;
    top.mem2.a.countslaves;
join

For a read task, only one module should actively respond to the task call, e.g. the one containing the appropriate address. The tasks in the other modules should return with no effect. Only then should the active task write to the result variables.

Note multiple export of functions is not allowed, because they must always write to the result.

The effect of a disable on an extern forkjoin task is as follows:

  • If the task is referenced via the interface instance, all task calls shall be disabled.
  • If the task is referenced via the module instance, only the task call to that module instance shall be disabled.
  • If an interface contains an extern forkjoin task, and no module connected to that interface defines the task, then any call to that task shall report a run-time error and return immediately with no effect.

This interface example shows how to define tasks in more than one module and call them in another using extern forkjoin. The multiple task export mechanism can also be used to count the instances of a particular modport that are connected to each interface instance.

Copy Code
interface simple_bus (input bit clk); // Define the interface
    logic req, gnt;
    logic [7:0] addr, data;
    logic [1:0] mode;
    logic start, rdy;
    int slaves = 0;

    // tasks executed concurrently as a fork/join block
    extern forkjoin task countSlaves();
    extern forkjoin task Read (input logic [7:0] raddr);
    extern forkjoin task Write (input logic [7:0] waddr);

    modport slave (input req,addr, mode, start, clk,
                   output gnt, rdy,
                   ref data, slaves,
                   export Read, Write, countSlaves);
                   // export from module that uses the modport

    modport master (input gnt, rdy, clk,
                    output req, addr, mode, start,
                    ref data,
                    import task Read(input logic [7:0] raddr),
                           task Write(input logic [7:0] waddr));
                    // import requires the full task prototype

    initial begin
        slaves = 0;
        countSlaves;
        $display ("number of slaves = %d", slaves);
    end
endinterface: simple_bus

module memMod #(parameter int minaddr=0, maxaddr=0;) (interface a);
    logic avail = 1;
    logic [7:0] mem[255:0];

    task a.countSlaves();
        a.slaves++;
    endtask

    task a.Read(input logic [7:0] raddr); // Read method
        if (raddr >= minaddr && raddr <= maxaddr) begin
            avail = 0;
            #10 a.data = mem[raddr];
            avail = 1;
        end
    endtask

    task a.Write(input logic [7:0] waddr); // Write method
        if (waddr >= minaddr && waddr <= maxaddr) begin
            avail = 0;
            #10 mem[waddr] = a.data;
            avail = 1;
        end
    endtask
endmodule

module cpuMod(interface b);
    typedef enum {read, write} instr;
    instr inst;
    logic [7:0] raddr;
    integer seed;

    always @(posedge b.clk) begin
        inst = instr’($dist_uniform(seed, 0, 1));
        raddr = $dist_uniform(seed, 0, 3);
        if (inst == read) begin
            $display("%t begin read %h @ %h", $time, b.data, raddr);
            callr:b.Read(raddr);
            $display("%t end read %h @ %h", $time, b.data, raddr);
        end
        else begin
            $display("%t begin write %h @ %h", $time, b.data, raddr);
            b.data = raddr;
            callw:b.Write(raddr);
            $display("%t end write %h @ %h", $time, b.data, raddr);
        end
    end
endmodule

module top;
    logic clk = 0;

    function void interrupt();
        disable mem1.a.Read; // task via module instance
        disable sb_intf.Write; // task via interface instance
        if (mem1.avail == 0)
            $display ("mem1 was interrupted");

        if (mem2.avail == 0)
            $display ("mem2 was interrupted");
    endfunction

    always #5 clk++;

    initial begin
        #28 interrupt();
        #10 interrupt();
        #100 $finish;
    end

    simple_bus sb_intf(clk);
    memMod #(0, 127) mem1(sb_intf.slave);
    memMod #(128, 255) mem2(sb_intf.slave);
    cpuMod cpu(sb_intf.master);
endmodule
Group

19.6 接口中的任务与函数

链接
19.6 接口中的任务与函数


19.7 参数化接口

链接
第十九章 接口
SystemVerilog 3.1a语言参考手册
19.7 参数化接口
第十九章 接口

Interface definitions can take advantage of parameters and parameter redefinition, in the same manner as module definitions. This example shows how to use parameters in interface definitions.

Copy Code
interface simple_bus #(AWIDTH = 8, DWIDTH = 8)
    (input bit clk); // Define the interface
    logic req, gnt;
    logic [AWIDTH-1:0] addr;
    logic [DWIDTH-1:0] data;
    logic [1:0] mode;
    logic start, rdy;

    modport slave( input req, addr, mode, start, clk,
                   output gnt, rdy,
                   ref data,
                   import task slaveRead(),
                          task slaveWrite());
                   // import into module that uses the modport

    modport master(input gnt, rdy, clk,
                   output req, addr, mode, start,
                   ref data,
                   import task masterRead(input logic [AWIDTH-1:0] raddr),
                          task masterWrite(input logic [AWIDTH-1:0] waddr));
                   // import requires the full task prototype

    task masterRead(input logic [AWIDTH-1:0] raddr); // masterRead method
        ...
    endtask

    task slaveRead; // slaveRead method
        ...
    endtask

    task masterWrite(input logic [AWIDTH-1:0] waddr);
        ...
    endtask

    task slaveWrite;
        ...
    endtask
endinterface: simple_bus

module memMod(interface a); // Uses just the interface keyword
    logic avail;
    always @(posedge a.clk) // the clk signal from the interface
    a.gnt <= a.req & avail; //the gnt and req signals in the interface

    always @(a.start)
        if (a.mode[0] == 1’b0)
            a.slaveRead;
        else
            a.slaveWrite;
endmodule

module cpuMod(interface b);
    enum {read, write} instr;
    logic [7:0] raddr;

    always @(posedge b.clk)
        if (instr == read)
            b.masterRead(raddr); // call the Interface method
            // ...
        else
            b.masterWrite(raddr);
endmodule

module top;
    logic clk = 0;
    simple_bus sb_intf(clk); // Instantiate default interface
    simple_bus #(.DWIDTH(16)) wide_intf(clk); // Interface with 16-bit data

    initial repeat(10) #10 clk++;
    memMod mem(sb_intf.slave); // only has access to the slaveRead task
    cpuMod cpu(sb_intf.master); // only has access to the masterRead task
    memMod memW(wide_intf.slave); // 16-bit wide memory
    cpuMod cpuW(wide_intf.master); // 16-bit wide cpu
endmodule
Group

第十九章 接口

链接
第十九章 接口


19.8 虚拟接口

链接
第十九章 接口, 主题
SystemVerilog 3.1a语言参考手册
19.8 虚拟接口
第十九章 接口 | 主题

Virtual interfaces provide a mechanism for separating abstract models and test programs from the actual signals that make up the design. A virtual interface allows the same subprogram to operate on different portions of a design, and to dynamically control the set of signals associated with the subprogram. Instead of referring to the actual set of signals directly, users are able to manipulate a set of virtual signals. Changes to the underlying design do not require the code using virtual interfaces to be re-written. By abstracting the connectivity and functionality of a set of blocks, virtual interfaces promote code-reuse.

A virtual interface is a variable that represents an interface instance. The syntax to declare a virtual interface variable is given below.

Copy Code
virtual_interface_declaration ::=        // from Annex A.2.9
    virtual [interface] interface_identifier list_of_virtual_interface_decl;

list_of_virtual_interface_decl ::=       // from Annex A.2.3
    variable_identifier [= interface_instance_identifier
        {, variable_identifier [= interface_instance_identifier]}

data_declaration ::=                    // from Annex A.2.1.3
    ...
  | virtual_interface_declaration

data_type ::=                           // from Annex A.2.2.1
    ...
  | virtual [interface] interface_identifier

Syntax 19-3—virtual interface declaration syntax (excerpt from Annex A)

Virtual interface variables can be passed as arguments to tasks, functions, or methods. A single virtual interface variable can thus represent different interface instances at different times throughout the simulation. A virtual interface must be initialized before it can be used; it has the value null before it is initialized. Attempting to use an uninitialized virtual interface shall result in a fatal run-time error.

Only the following operations are directly allowed on virtual interface variables:

  • Assignment ( = ) to:
    • another virtual interface of the same type
    • an interface instance of the same type
    • the special constant null
  • Equality ( == ) and inequality ( != ) with:
    • another virtual interface of the same type
    • an interface instance of the same type
    • the special constant null
Virtual interfaces shall not be used as ports, interface items, or as members of unions.

Once a virtual interface has been initialized, all the components of the underlying interface instance are directly available to the virtual interface via the dot notation. These components can only be used in procedural statements; they cannot be used in continuous assignments or sensitivity lists. In order for a net to be driven via a virtual interface, the interface itself must provide a procedural means to do so. This can be accomplished either via a clocking block or by including a driver that is updated by a continuous assignment from a variable within the interface.

Virtual interfaces can be declared as class properties, which can be initialized procedurally or by an argument to new(). This allows the same virtual interface to be used in different classes. The following example shows how the same transactor class can be used to interact with various different devices.

Copy Code
interface SBus; // A Simple bus interface
    logic req, grant;
    logic [7:0] addr, data;
endinterface

class SBusTransctor; // SBus transactor class
    virtual SBus bus; // virtual interface of type Sbus

    function new( virtual SBus s );
        bus = s; // initialize the virtual interface
    endfunction

    task request(); // request the bus
        bus.req <= 1’b1;
    endtask

    task wait_for_bus(); // wait for the bus to be granted
        @(posedge bus.grant);
    endtask
endclass

module devA( Sbus s ) ... endmodule // devices that use SBus

module devB( Sbus s ) ... endmodule

module top;
    SBus s[1:4] (); // instantiate 4 interfaces
    devA a1( s[1] ); // instantiate 4 devices
    devB b1( s[2] );
    devA a2( s[3] );
    devB b2( s[4] );

    initial begin
        SbusTransactor t[1:4]; // create 4 bus-transactors and bind
        t[1] = new( s[1] );
        t[2] = new( s[2] );
        t[3] = new( s[3] );
        t[4] = new( s[4] );
        // test t[1:4]
    end
endmodule

In the preceding example, the transaction class SbusTransctor is a simple reusable component. It is written without any global or hierarchical references, and is unaware of the particular device with which it will interact. Nevertheless, the class can interact with any number of devices (4 in the example) that adhere to the interface’s protocol.

Group

第十九章 接口

主题
主题 | 描述
19.8.1 Virtual interfaces and clocking blocks | Clocking blocks and interfaces can be combined to represent the interconnect between synchronous blocks. Moreover, because clocking blocks provide a procedural mechanism to assign values to both nets and variables, they are ideally suited to be used by virtual interfaces. For example:
19.8.2 Virtual interfaces modports and clocking blocks | As shown in the example above, once a virtual interface is declared, its clocking block can be referenced using dot-notation. However, this only works for interfaces with no modports. Typically, a device under test and its testbench exhibit modport direction. This common case can be handled by including the clocking in the corresponding modport as described in Section 19.4.5. The example below shows how modports used in conjunction with virtual interfaces facilitate the creation of abstract synchronous models.
链接
第十九章 接口, 主题


19.8.1 Virtual interfaces and clocking blocks

链接
19.8 虚拟接口
SystemVerilog 3.1a语言参考手册
19.8.1 Virtual interfaces and clocking blocks
19.8 虚拟接口

Clocking blocks and interfaces can be combined to represent the interconnect between synchronous blocks. Moreover, because clocking blocks provide a procedural mechanism to assign values to both nets and variables, they are ideally suited to be used by virtual interfaces. For example:

Copy Code
interface SyncBus( input bit clk );
    wire a, b, c;

    clocking sb @(posedge clk);
        input a;
        output b;
        inout c;
    endclocking
endinterface

typedef virtual SyncBus VI; // A virtual interface type

task do_it( VI v ); // handles any SyncBus via clocking sb
    if( v.sb.a == 1 )
        v.sb.b <= 0;
    else
        v.sb.c <= ##1 1;
endtask

In the preceding example, interface SyncBus includes a clocking block, which is used by task do_it to ensure synchronous access to the interface’s signals: a, b, and c. Note that changes to the storage type of the interface signals (from net to variable and vice-versa) requires no changes to the task. The interfaces can be instantiated as shown below.

Copy Code
module top;
    bit clk;
    SyncBus b1( clk );
    SyncBus b2( clk );

    initial begin
        VI v[2] = { b1, b2 };
        repeat( 20 )
            do_it( v[ $urandom_range( 0, 1 ) ] );
    end
endmodule

The top module above shows how a virtual interface can be used to randomly select among a set of interfaces to be manipulated, in this case by the do_it task.

Group

19.8 虚拟接口

链接
19.8 虚拟接口


19.8.2 Virtual interfaces modports and clocking blocks

链接
19.8 虚拟接口
SystemVerilog 3.1a语言参考手册
19.8.2 Virtual interfaces modports and clocking blocks
19.8 虚拟接口

As shown in the example above, once a virtual interface is declared, its clocking block can be referenced using dot-notation. However, this only works for interfaces with no modports. Typically, a device under test and its testbench exhibit modport direction. This common case can be handled by including the clocking in the corresponding modport as described in Section 19.4.5.

The example below shows how modports used in conjunction with virtual interfaces facilitate the creation of abstract synchronous models.

Copy Code
interface A_Bus( input bit clk );
    wire req, gnt;
    wire [7:0] addr, data;

    clocking sb @(posedge clk);
        input gnt;
        output req, addr;
        inout data;

        property p1;
            req ##[1:3] gnt;
        endproperty
    endclocking

    modport DUT ( input clk, req, addr, // Device under test modport
                  output gnt,
                  inout data );

    modport STB ( clocking sb ); // synchronous testbench modport

    modport TB ( input gnt, // asynchronous testbench modport
                 output req, addr,
                 inout data );
endinterface

The above interface A_Bus can then be instantiated as shown below:

Copy Code
module dev1(A_Bus.DUT b); // Some device: Part of the design
    ...
endmodule

module dev2(A_Bus.DUT b); // Some device: Part of the design
    ...
endmodule

program T (A_Bus.STB b1, A_Bus.STB b2 ); // Testbench: 2 synchronous ports
    ...
endprogram

module top;
    bit clk;
    A_Bus b1( clk );
    A_Bus b2( clk );
    dev1 d1( b1 );
    dev2 d2( b2 );
    T tb( b1, b2 );
endmodule

And, within the testbench program, the virtual interface can refer directly to the clocking block.

Copy Code
program T (A_Bus.STB b1, A_Bus.STB b2 ); // Testbench: 2 synchronous ports
    typedef virtual A_Bus.STB SYNCTB;

    task request( SYNCTB s );
        s.sb.req <= 1;
    endtask

    task wait_grant( SYNCTB s );
        wait( s.sb.gnt == 1 );
    endtask

    task drive(SYNCTB s, logic [7:0] adr, data );
        if( s.sb.gnt == 0 ) begin
            request(s); // acquire bus if needed
            wait_grant(s);
        end

        s.sb.addr = adr;
        s.sb.data = data;
        repeat(2) @s.sb;
        s.sb.req = 0; //release bus
    endtask

    assert property (b1.p1); // assert property from within program

    initial begin
        drive( b1, $random, $random );
        drive( b2, $random, $random );
    end
endprogram

The example above shows how the clocking block is referenced via the virtual interface by the tasks within the program block.

Group

19.8 虚拟接口

链接
19.8 虚拟接口


19.9 对接口对象的访问

链接
第十九章 接口
SystemVerilog 3.1a语言参考手册
19.9 对接口对象的访问
第十九章 接口

Access to all objects declared in an interface is always available by hierarchical reference, regardless of whether or not the interface is connected through a port. When an interface is connected with a modport in either the module header or port connection, access by port reference is limited to only those objects listed in the modport, for only those types of objects legal to be listed in modports (nets, variables, tasks, and functions) All objects are still visible by hierarchical reference. For example:

Copy Code
interface ebus_i;
    integer I; // reference to I not allowed through modport mp
    typedef enum {Y,N} choice;
    choice Q;
    parameter True = 1;
    modport mp(input Q);
endinterface

module Top;
    ebus_i ebus;
    sub s1(ebus.mod);
endmodule

module sub(interface.mp i);
    typedef i.choice yes_no; // import type from interface
    yes_no P;
    assign P = i.Q; // refer to Q with a port reference

    initial
        Top.s1.Q = i.True; // refer to Q with a hierarchical reference

    initial
        Top.s1.I = 0; // referring to i.I would not be legal because
        // is not in modport mp
endmodule
Group

第十九章 接口

链接
第十九章 接口


第二十章 覆盖

链接
主题
SystemVerilog 3.1a语言参考手册
第二十章 覆盖
主题
主题
主题
描述
20.1 简介（一般信息）
Functional verification comprises a large portion of the resources required to design and validate a complex system. Often, the validation must be comprehensive without redundant effort. To minimize wasted effort, coverage is used as a guide for directing verification resources by identifying tested and untested portions of the design.

Coverage is defined as the percentage of verification objectives that have been met. It is used as a metric for evaluating the progress of a verification project in order to reduce the number of simulation cycles spent in verifying a design Broadly speaking, there are two types of coverage metrics. Those... more
20.2 定义覆盖模型：covergroup
The covergroup construct encapsulates the specification of a coverage model. Each covergroup specification can include the following components:
  • A clocking event that synchronizes the sampling of coverage points
  • A set of coverage points
  • Cross coverage between coverage points
  • Optional formal arguments
  • Coverage options
The covergroup construct is a user-defined type. The type definition is written once, and multiple instances of that type can be created in different contexts. Similar to a class, once defined, a covergroup instance can be created via the new() operator. A covergroup can be defined in a module, program, interface, or class.
20.3 在类中使用covergroup
By embedding a coverage group within a class definition, the covergroup provides a simple way to cover a subset of the class properties. This integration of coverage with classes provides an intuitive and expressive mechanism for defining the coverage model associated with a class. For example, In class xyz, defined below, members m_x and m_y are covered using an embedded covergroup:
20.4 定义覆盖点
A covergroup can contain one or more coverage points. A coverage point can be an integral variable or an integral expression. Each coverage point includes a set of bins associated with its sampled values or its valuetransitions. The bins can be explicitly defined by the user or automatically created by SystemVerilog. The syntax for specifying coverage points is given below.
20.5 Defining cross coverage
A coverage group can specify cross coverage between two or more coverage points or variables. Cross coverage is specified using the cross construct. When a variable V is part of a cross coverage, SystemVerilog implicitly creates a coverage point for the variable, as if it had been created by the statement coverpoint V;. Thus, a cross involves only coverage points. Expressions cannot be used directly in a cross; a coverage point must be explicitly defined first.

The syntax for specifying cross coverage is given below.
20.6 Specifying coverage options
Options control the behavior of the covergroup, coverpoint and cross. There are two types of options: those that are specific to an instance of a covergroup, and those that specify an option for the covergroup type as a whole.

The following table lists instance specific covergroup options and their description. Each instance of a covergroup can initialize an instance specific option to a different value. The initialized option value affects only
that instance.

Table 20-1: Instance specific coverage options

20.7 Predefined coverage methods
The following coverage methods are provided for the covergroup. These methods can be invoked procedurally at any time.

Table 20-5: Predefined coverage methods

20.8 Predefined coverage system tasks and functions
SystemVerilog provides the following system tasks and functions to help manage coverage data collection.

$set_coverage_db_name ( name ) — Sets the filename of the coverage database into which coverage information is saved at the end of a simulation run.

$load_coverage_db ( name ) — Load from the given filename the cumulative coverage information for all coverage group types.

$get_coverage ( ) — Returns as a real number in the range 0 to 100 the overall coverage of all coverage group types. This number is computed as described above.
20.9 Organization of option and type_option members
The type and type_option members of a covergroup, coverpoint, and cross items are implicitly declared structures with the following composition:
链接
主题


20.1 简介（一般信息）

链接
第二十章 覆盖
SystemVerilog 3.1a语言参考手册
20.1 简介（一般信息）
第二十章 覆盖

Functional verification comprises a large portion of the resources required to design and validate a complex system. Often, the validation must be comprehensive without redundant effort. To minimize wasted effort, coverage is used as a guide for directing verification resources by identifying tested and untested portions of the design.

Coverage is defined as the percentage of verification objectives that have been met. It is used as a metric for evaluating the progress of a verification project in order to reduce the number of simulation cycles spent in verifying a design Broadly speaking, there are two types of coverage metrics. Those that can be automatically extracted from the design code, such as code coverage, and those that are user-specified in order to tie the verification environment to the design intent or functionality. This latter form is referred to as Functional Coverage, and is the topic of this section.

Functional coverage is a user-defined metric that measures how much of the design specification, as enumerated by features in the test plan, has been exercised. It can be used to measure whether interesting scenarios, corner cases, specification invariants, or other applicable design conditions—captured as features of the test plan—have been observed, validated and tested.

The key aspects of functional coverage are:

  • It is user-specified, and is not automatically inferred from the design
  • It is based on the design specification (i.e., its intent) and is thus independent of the actual design code or its structure.

Since it is fully specified by the user, functional coverage requires more up front effort (someone has to write the coverage model). Functional coverage also requires a more structured approach to verification. Although functional coverage can shorten the overall verification effort and yield higher quality designs, these shortcomings can impede its adoption.

The SystemVerilog functional coverage extensions address these shortcomings by providing language constructs for easy specification of functional coverage models. This specification can be efficiently executed by the SystemVerilog simulation engine, thus, enabling coverage data manipulation and analysis tools that speed up the development of high quality tests. The improved set of tests can exercise more corner cases and required scenarios, without redundant work.

The SystemVerilog functional coverage constructs enable:

  • Coverage of variables and expressions, as well as cross coverage between them.
  • Automatic as well as user-defined coverage bins.
  • Associate bins with sets of values, transitions, or cross products.
  • Filtering conditions at multiple levels.
  • Events and sequences to automatically trigger coverage sampling.
  • Procedural activation and query of coverage.
  • Optional directives to control and regulate coverage.

Group

第二十章 覆盖

链接
第二十章 覆盖


20.2 定义覆盖模型：covergroup

链接
第二十章 覆盖
SystemVerilog 3.1a语言参考手册
20.2 定义覆盖模型：covergroup
第二十章 覆盖

The covergroup construct encapsulates the specification of a coverage model. Each covergroup specification can include the following components:

  • A clocking event that synchronizes the sampling of coverage points
  • A set of coverage points
  • Cross coverage between coverage points
  • Optional formal arguments
  • Coverage options
The covergroup construct is a user-defined type. The type definition is written once, and multiple instances of that type can be created in different contexts. Similar to a class, once defined, a covergroup instance can be created via the new() operator. A covergroup can be defined in a module, program, interface, or class.

Copy Code
covergroup_declaration ::=        // from Annex A.2.11
    covergroup covergroup_identifier[([tf_port_list])][coverage_event];
        {coverage_spec_or_option;}
    endgroup [: covergroup_identifier]

coverage_spec_or_option ::=
    {attribute_instance} coverage_spec
  | {attribute_instance} coverage_option;

coverage_option ::=
    option.member_identifier = expression
  | type_option.member_identifier = expression

coverage_spec ::=
    cover_point
  | cover_cross

coverage_event ::=
    clocking_event
  | @@(block_event_expression)

block_event_expression :: =
    block_event_expression or block_event_expression
  | begin hierarchical_btf_identifier
  | end hierarchical_btf_identifier

hierarchical_btf_identifier :: =
    hierarchical_tf_identifier
  | hierarchical_block_identifier
  | hierarchical_identifier [class_scope] method_identifier

variable_decl_assignment ::=           // from Annex A.2.4
    ...
  | [covergroup_variable_identifier] = new[(list_of_arguments)] // 16

16. It shall be legal to omit the covergroup_variable_identifer from a covergroup
    instantiation only if this implicit instantiation is within a class that has no
    other instantiation of the covergroup.

Syntax 20-1—Covergroup syntax (excerpt from Annex A)

The identifier associated with the covergroup declaration defines the name of the coverage model. Using this name, an arbitrary number of coverage model instances can be created. For example:

Copy Code
covergroup cg; ... endgroup
cg cg_inst = new;

The above example defines a covergroup named cg. An instance of cg is declared as cg_inst and created using the new operator.

A covergroup can specify an optional list of arguments. When the covergroup specifies a list of formal arguments, its instances must provide to the new operator all the actual arguments that are not defaulted. Actual arguments are evaluated when the new operator is executed. A ref argument allows a different variable to be sampled by each instance of a covergroup. Input arguments will not track value of their arguments; they will use the value passed to the new operator.

If a clocking event is specified, it defines the event at which coverage points are sampled. If the clocking event is omitted, users must procedurally trigger the coverage sampling. This is done via the built-in sample() method (see Section 20.7). Optionally, the strobe option can be used to modify the sampling behavior. When the strobe option is not set (the default), a coverage point is sampled the instant the clocking event takes place, as if the process triggering the event were to call the built-in sample() method. If the clocking event occurs multiple times in a time step, the coverage point will also be sampled multiple times. The strobe option (see Section 20.6.1) can be used to specify that coverage points are sampled in the postponed region, thereby filtering multiple clocking events so that only one sample per time slot is taken.

As an alternative to a clocking event, a coverage group accepts a block event expression to indicate that the coverage sample is to be triggered by the start or the end of execution of a given named block, task, function, or class method. Block event expressions that specify the begin keyword followed by a hierarchical identifier denoting a named block, task, function, or class method shall be triggered immediately before the corresponding block, task, function, or method begins executing its first statement. Block event expressions that specify the end keyword followed by a hierarchical identifier denoting a named block, task, function, or class method shall be triggered immediately after the corresponding block, task, function, or method executes its last statement.Block event expressions that specify the end of execution shall not be triggered if the block, task, function, or method is disabled.

A covergroup can contain one or more coverage points. A coverage point can be a variable or an expression. Each coverage point includes a set of bins associated with its sampled values or its value-transitions. The bins can be explicitly defined by the user or automatically created by the tool. Coverage points are discussed in detail in Section 20.4.

Copy Code
enum { red, green, blue } color;
covergroup g1 @(posedge clk);
    c: coverpoint color;
endgroup

The above example defines coverage group g1 with a single coverage point associated with variable color. The value of the variable color is sampled at the indicated clocking event: the positive edge of signal clk. Since the coverage point does not explicitly define any bins, the tool automatically creates 3 bins, one for each possible value of the enumerated type. Automatic bins are described in Section 20.4.2.

A coverage group can also specify cross coverage between two or more coverage points or variables. Any combination of more than two variables or previously declared coverage points is allowed. For example:

Copy Code
enum { red, green, blue } color;
bit [3:0] pixel_adr, pixel_offset, pixel_hue;

covergroup g2 @(posedge clk);
    Hue: coverpoint pixel_hue;
    Offset: coverpoint pixel_offset;
    AxC: cross color, pixel_adr; // cross 2 variables (implicitly declared
    // coverpoints)
    all: cross color, Hue, Offset; // cross 1 variable and 2 coverpoints
endgroup

The example above creates coverage group g2 that includes 2 coverage points and two cross coverage items. Explicit coverage points labeled Offset and Hue are defined for variables pixel_offset and pixel_hue. SystemVerilog implicitly declares coverage points for variables color and pixel_adr in order to track their cross coverage. Implicitly declared cover points are described in Section 20.5.

A coverage group can also specify one or more options to control and regulate how coverage data is structured and collected. Coverage options can be specified for the coverage group as a whole, or for specific items within the coverage group, that is, any of its coverage points or crosses. In general, a coverage option specified at the covergroup level applies to all of its items unless overridden by them. Coverage options are described in Section 20.6.

Group

第二十章 覆盖

链接
第二十章 覆盖


20.3 在类中使用covergroup

链接
第二十章 覆盖
SystemVerilog 3.1a语言参考手册
20.3 在类中使用covergroup
第二十章 覆盖

By embedding a coverage group within a class definition, the covergroup provides a simple way to cover a subset of the class properties. This integration of coverage with classes provides an intuitive and expressive mechanism for defining the coverage model associated with a class. For example, In class xyz, defined below, members m_x and m_y are covered using an embedded covergroup:

Copy Code
class xyz;
    bit [3:0] m_x;
    int m_y;
    bit m_z;

    covergroup cov1 @m_z; // embedded covergroup
        coverpoint m_x;
        coverpoint m_y;
    endgroup

    function new(); cov1 = new; endfunction
endclass

In this example, data members m_x and m_y of class xyz are sampled on every change of data member m_z. When a covergroup is defined within a class, and no explicit variables of that covergroup are declared in the class then a variable with the same name as the coverage group is implicitly declared, e.g, in the above example, a variable cov1 (of the embedded coverage group) is implicitly declared. Whether the coverage group variable is implicitly or explicitly declared, each class contains exactly one variable of each embedded coverage group. Each embedded coverage group thus becomes part of the class, tightly binding the class properties to the coverage definition. Declaring multiple variables of the same embedded coverage group shall result in a compiler error.

An embedded covergroup can define a coverage model for protected and local class properties without any changes to the class data encapsulation. Class members can become coverage points or can be used in other coverage constructs, such as conditional guards or option initialization.

A class can have more than one covergroup. The following example shows two cover groups in class MC.

Copy Code
class MC;
    logic [3:0] m_x;
    local logic m_z;
    bit m_e;
    covergroup cv1 @(posedge clk); coverpoint m_x; endgroup
    covergroup cv2 @m_e ; coverpoint m_z; endgroup
endclass

In covergroup cv1, public class member variable m_x is sampled at every positive edge of signal clk. Local class member m_z is covered by another covergroup cv2. Each coverage groups is sampled by a different clocking event.

An embedded coverage group must be explicitly instantiated in the new method. If it is not, then the coverage group is not created and no data will be sampled.

Below is an example of an embedded coverage_group that does not have any passed-in arguments, and uses explicit instantiation to synchronize with another object:

Copy Code
class Helper;
    int m_ev;
endclass

class MyClass;
    Helper m_obj;
    int m_a;
    covergroup Cov @(m_obj.m_ev);
        coverpoint m_a;
    endgroup

    function new();
        m_obj = new;
        Cov = new; // Create embedded covergroup after creating m_obj
    endfunction
endclass

In this example, covergroup Cov is embedded within class MyClass, which contains an object of type Helper class, called m_obj. The clocking event for the embedded coverage group refers to data member m_ev of m_obj. Because the coverage group Cov uses m_obj, m_obj must be instantiated before Cov. Therefore, the coverage group Cov is instantiated after instantiating m_obj in the class constructor. As shown above, the instantiation of an embedded coverage group is done by assigning the result of the new operator to the coverage group identifier.

The following example shows how arguments passed in to an embedded coverage group can be used to set a coverage option of the coverage group.

Copy Code
class C1;
    bit [7:0] x;

    covergroup cv (int arg) @(posedge clk);
        option.at_least = arg;
        coverpoint x;
    endgroup

    function new(int p1);
        cv = new(p1);
    endfunction
endclass

initial begin
    C1 obj = new(4);
end
Group

第二十章 覆盖

链接
第二十章 覆盖


20.4 定义覆盖点

链接
第二十章 覆盖, 主题
SystemVerilog 3.1a语言参考手册
20.4 定义覆盖点
第二十章 覆盖 | 主题

A covergroup can contain one or more coverage points. A coverage point can be an integral variable or an integral expression. Each coverage point includes a set of bins associated with its sampled values or its valuetransitions. The bins can be explicitly defined by the user or automatically created by SystemVerilog. The syntax for specifying coverage points is given below.

Copy Code
cover_point ::=         // from Annex A.2.11
    [cover_point_identifer :] coverpoint expression [iff(expression)] bins_or_empty

bins_or_empty ::=
    {{attribute_instance} {bins_or_options;}}
  | ;

bins_or_options ::=
    coverage_option
  | [wildcard] bins_keyword bin_identifier[[[expression]]]={range_list}[iff(expression)]
  | [wildcard] bins_keyword bin_identifier[[]]=trans_list [iff(expression)]
  | bins_keyword bin_identifier[[[expression]]]=default [iff(expression)]
  | bins_keyword bin_identifier = default sequence [iff(expression)]

bins_keyword::= bins | illegal_bins | ignore_bins

range_list ::= value_range {, value_range}

value_range ::=                        // from Annex A.8.3
    expression
  | [expression : expression]

Syntax 20-2—coverpoint syntax (excerpt from Annex A)

A coverage point creates a hierarchical scope, and can be optionally labeled. If the label is specified then it designates the name of the coverage point. This name can be used to add this coverage point to a cross coverage specification, or to access the methods of the coverage point. If the label is omitted and the coverage point is associated with a single variable then the variable name becomes the name of the coverage point. Otherwise, an implementation can generate a name for the coverage point only for the purposes of coverage reporting, that is, generated names cannot be used within the language.

A coverage point can sample the values that correspond to a particular scheduling region (see Section 14) by specifying a clocking block signal. Thus, a coverage point that denotes a clocking block signal will sample the values made available by the clocking block. If the clocking block specifies a skew of #1step, the coverage point will sample the signal values from the Preponed region. If the clocking block specifies a skew of #0, the coverage point will sample the signal values from the Observe region.

The expression within the iff construct specifies an optional condition that disables coverage for that cover point. If the guard expression evaluates to false at a sampling point, the coverage point is ignored. For example:

Copy Code
covergroup g4;
    coverpoint s0 iff(!reset);
endgroup

In the preceding example, cover point s0 is covered only if the value reset is false.

A coverage-point bin associates a name and a count with a set of values or a sequence of value transitions. If the bin designates a set of values, the count is incremented every time the coverage point matches one of the values in the set. If the bin designates a sequence of value transitions, the count is incremented every time the coverage point matches the entire sequence of value transitions.

The bins for a coverage point can be automatically created by SystemVerilog or explicitly defined using the bins construct to name each bin. If the bins are not explicitly defined, they are automatically created by SystemVerilog. The number of automatically created bins can be controlled using the auto_bin_max coverage option. Coverage options are described in Section 20.6.

The bins construct allows creating a separate bin for each value in the given range-list, or a single bin for the entire range of values. To create a separate bin for each value (an array of bins) the square brackets, [], must follow the bin name. To create a fixed number of bins for a set of values, a number can be specified inside the square brackets. The range_list used to specify the set of values associated with a bin shall be constant expressions, instance constants (for classes only) or non-ref arguments to the coverage group.

If a fixed number of bins is specified, and that number is smaller than the number of values in the bin then the possible bin values are uniformly distributed among the specified bins. If the number of values is not divisible by the number of bins then the last bin will include the remaining items. For example:

Copy Code
bins fixed [3] = {1:10};

The 11 possible values are distributed as follows: <1,2,3>, <4,5,6>, <7,8,9,10>. If the number of bins exceeds the number of values then some of the bins will be empty.

The expression within the iff construct at the end of a bin definition provides a per-bin guard condition. If the expression is false at a sampling point, the count for the bin is not incremented.

The default specification defines a bin that is associated with none of the defined value bins. The default bin catches the values of the coverage point that do not lie within any of the defined bins. However, the coverage calculation for a coverage point shall not take into account the coverage captured by the default bin. The default is useful for catching unplanned or invalid values. The default sequence form can be used to catch all transitions (or sequences) that do not lie within any of the defined transition bins (see Section 20.4.1). The default sequence specification does not accept multiple transition bins (the [] notation is not allowed).

Copy Code
bit [9:0] v_a;
covergroup cg @(posedge clk);
    coverpoint v_a
    {
        bins a = { [0:63],65 };
        bins b[] = { [127:150],[148:191] }; // note overlapping values
        bins c[] = { 200,201,202 };
        bins d = { [1000:$] };
        bins others[] = default;
    }
endgroup

In the example above, the first bins construct associates bin a with the values of variable v_a between 0 and 63, and the value 65. The second bins construct creates a set of 65 bins b[127], b[128],...b[191]. Likewise, the third bins construct creates 3 bins: c[200], c[201], and c[202]. The fourth bins construct associates bin d with the values between 1000 and 1023 ($ represents the maximum value of v_a). Every value that does not match bins a, b[], c[], or d[] is added into its own distinct bin.

A default or default sequence bin specification cannot be explicitly ignored (see Section 20.4.4). It shall be an error for bins designated as ignore_bins to also specify a default or default sequence.

Generic coverage groups can be written by passing their traits as arguments to the constructor. For example:

Copy Code
covergroup gc (ref int ra, int low, int high ) @(posedge clk);
    coverpoint ra // sample variable passed by reference
    {
        bins good = { [low : high] };
        bins bad[] = default;
    }
endgroup
...
int va, vb;
cg c1 = new( va, 0, 50 ); // cover variable va in the range 0 to 50
cg c2 = new( vb, 120, 600 ); // cover variable vb in the range 120 to 600

The example above defines a coverage group, gc, in which the signal to be sampled as well as the extent of the coverage bins are specified as arguments. Later, two instances of the coverage group are created; each instance samples a different signal and covers a different range of values.

Group

第二十章 覆盖

主题
主题
描述
20.4.1 Specifying bins for transitions
The syntax for specifying transition bins accepts a subset of the sequence syntax described in Section 17:
20.4.2 Automatic bin creation for coverage points
If a coverage point does not define any bins, SystemVerilog automatically creates state bins. This provides an easy-to-use mechanism for binning different values of a coverage point. Users can either let the tool automatically create state bins for coverage points or explicitly define named bins for each coverage point.

When the automatic bin creation mechanism is used, SystemVerilog creates N bins to collect the sampled values of a coverage point. The value N is determined as follows:
  • For an enum coverage point, N is the cardinality of the enumeration.
  • For any other integral coverage point, N is the minimum of... more
20.4.3 Wildcard specification of coverage point bins
By default, a value or transition bin definition can specify 4-state values. When a bin definition includes an X or Z, it indicates that the bin count should only be incremented when the sampled value has an X or Z in the same bit positions, i.e., the comparison is done using ===. The wildcard bins definition causes all X, Z, or ? to be treated as wildcards for 0 or 1 (similar to the =?= operator). For example:
20.4.4 Excluding coverage point values or transitions
A set of values or transitions associated with a coverage-point can be explicitly excluded from coverage by specifying them as ignore_bins. For example:
20.4.5 Specifying Illegal coverage point values or transitions
A set of values or transitions associated with a coverage-point can be marked as illegal by specifying them as illegal_bins. For example:
链接
第二十章 覆盖, 主题


20.4.1 Specifying bins for transitions

链接
20.4 定义覆盖点
SystemVerilog 3.1a语言参考手册
20.4.1 Specifying bins for transitions
20.4 定义覆盖点

The syntax for specifying transition bins accepts a subset of the sequence syntax described in Section 17:

Copy Code
bins_or_options ::=   // from Annex A.2.11
    ...
  | [wildcard] bins_keyword bin_identifier[[[expression]]]={range_list} [iff(expression)]
  | [wildcard] bins_keyword bin_identifier[[]] = trans_list [iff(expression)]
    ...
bins_keyword::= bins | illegal_bins | ignore_bins

range_list ::= value_range {, value_range}

trans_list ::= (trans_set) {,(trans_set)}

trans_set ::= trans_range_list => trans_range_list {=> trans_range_list}

trans_range_list ::=
    trans_item
  | trans_item[[*repeat_range]]
  | trans_item[[–>repeat_range]]
  | trans_item[[=repeat_range]]

trans_item ::= range_list

repeat_range ::=
    expression
  | expression : expression

Syntax 20-3—Transition bin syntax (excerpt from Annex A)

A trans_list specifies one or more sets of ordered value transitions of the coverage point. A single value transition is thus specified as:

Copy Code
value1 => value2

It represents the value of coverage point at two successive sample points, that is, value1 followed by value2 at the next sample point.

A sequence of transitions is represented as:

Copy Code
value1 => value3 => value4 => value5

In this case, value1 is followed by value3, followed by value4 and followed by value5. A sequence can be of any arbitrary length.

A set of transitions can be specified as:

Copy Code
range_list1 => range_list2

This specification expands to transitions between each value in range_list1 and each value in range_list2. For example,

Copy Code
1,5 => 6, 7

specifies the following four transitions:

Copy Code
1=>6, 1=>7, 5=>6, 5=>7

Consecutive repetitions of transitions are specified using (see Annex H):

Copy Code
trans_item [* repeat_range ]

Here, trans_item is repeated for repeat_range times. For example,

Copy Code
3 [* 5]

is the same as

Copy Code
3=>3=>3=>3=>3

An example of a range of repetition is:

Copy Code
3 [* 3:5]

is the same as

Copy Code
3=>3=>3, 3=>3=>3=>3, 3=>3=>3=>3=>3

The repetition with non-consecutive occurrence of a value is specified using: trans_item [-> repeat_range ]. Here, the occurrence of a value is specified with an arbitrary number of sample points where the value does not occur. For example,

Copy Code
3 [-> 3]

is the same as

Copy Code
...3=>...=>3...=>3

where the dots (...) represent any transition that does not contain the value 3.

Non-consecutive repetition is where a sequence of transitions continues until the next transition. For example,

Copy Code
3 [= 2]

is same as the transitions below excluding the last transition.

Copy Code
3=>...=>3...=>3

A trans_list specifies one or more sets of ordered value transitions of the coverage point. If the sequence of value transitions of the coverage point matches any complete sequence in the trans_list, the coverage count of the corresponding bin is incremented. For example:

Copy Code
bit [4:1] v_a;
covergroup cg @(posedge clk);
    coverpoint v_a
    {
        bins sa = (4 => 5 => 6), ([7:9],10=>11,12);
        bins sb[] = (4=> 5 => 6), ([7:9],10=>11,12);
        bins allother = default sequence ;
    }
endgroup

The example above defines two transition coverage bins. The first bins construct associates the following sequences with bin sa: 4=>5=>6, or 7=>11, 8=>11, 9=>11, 10=>11, 7=>12, 8=>12, 9=>12, 10=>12. The second bins construct associates an individual bin with each of the above sequences: sb[4=>5=>6], ..., sb[10=>12]. The bin allother tracks all other transitions that are not covered by the other bins: sa and sb.

Transitions that specify sequences of unbounded or undetermined varying length cannot be used with the multiple bins construct (the [] notation). For example, the length of the transition: 3[=2], which uses non-consecutive repetition, is unbounded and can vary during simulation. An attempt to specify multiple bins with such sequences shall result in an error.

Group

20.4 定义覆盖点

链接
20.4 定义覆盖点


20.4.2 Automatic bin creation for coverage points

链接
20.4 定义覆盖点
SystemVerilog 3.1a语言参考手册
20.4.2 Automatic bin creation for coverage points
20.4 定义覆盖点

If a coverage point does not define any bins, SystemVerilog automatically creates state bins. This provides an easy-to-use mechanism for binning different values of a coverage point. Users can either let the tool automatically create state bins for coverage points or explicitly define named bins for each coverage point.

When the automatic bin creation mechanism is used, SystemVerilog creates N bins to collect the sampled values of a coverage point. The value N is determined as follows:

  • For an enum coverage point, N is the cardinality of the enumeration.
  • For any other integral coverage point, N is the minimum of 2M and the value of the auto_bin_max option, where M is the number of bits needed to represent the coverage point.

If the number of automatic bins is smaller than the number of possible values (N < 2M ) then the 2M values are uniformly distributed in the N bins. If the number of values, 2M,is not divisible by N, then the last bin will include the additional (up to N-1) remaining items. For example, if M is 3, and N is 3 then the 8 possible values are distributed as follows: <0:1> ,<2:3>,<4,5,6,7>.

Automatically created bins only consider 2-state values; sampled values containing X or Z are excluded.

SystemVerilog implementations can impose a limit on the number of automatic bins. See the Section 20.6 for the default value of auto_bin_max.

Each automatically created bin will have a name of the form: auto[value], where value is either a single coverage point value, or the range of coverage point values included in the bin—in the form low:high. For enumerated types, value is the named constant associated with a particular enumerated value.

Group

20.4 定义覆盖点

链接
20.4 定义覆盖点


20.4.3 Wildcard specification of coverage point bins

链接
20.4 定义覆盖点
SystemVerilog 3.1a语言参考手册
20.4.3 Wildcard specification of coverage point bins
20.4 定义覆盖点

By default, a value or transition bin definition can specify 4-state values. When a bin definition includes an X or Z, it indicates that the bin count should only be incremented when the sampled value has an X or Z in the same bit positions, i.e., the comparison is done using ===. The wildcard bins definition causes all X, Z, or ? to be treated as wildcards for 0 or 1 (similar to the =?= operator). For example:

Copy Code
wildcard bins g12_16 = { 4’b11?? };

The count of bin g12_16 is incremented when the sampled variable is between 12 and 16:

Copy Code
1100 1101 1110 1111

Similarly, transition bins can define wildcard bins. For example:

Copy Code
wildcard bins T0_3 = (2’b0x => 2’b1x);

The count of transition bin T0_3 is incremented for the following transitions (as if by (0,1=>2,3)):

Copy Code
00 => 10 00 => 11 01 => 10 01 => 11

A wildcard bin definition only consider 2-state values; sampled values containing X or Z are excluded. Thus, the range of values covered by a wildcard bin is established by replacing every wildcard digit by 0 to compute the low bound and 1 to compute the high bound.

Group

20.4 定义覆盖点

链接
20.4 定义覆盖点


20.4.4 Excluding coverage point values or transitions

链接
20.4 定义覆盖点
SystemVerilog 3.1a语言参考手册
20.4.4 Excluding coverage point values or transitions
20.4 定义覆盖点

A set of values or transitions associated with a coverage-point can be explicitly excluded from coverage by specifying them as ignore_bins. For example:

Copy Code
covergroup cg23;
    coverpoint a
    {
        ignore_bins ignore_vals = {7,8};
        ignore_bins ignore_trans = (1=>3=>5);
    }
endgroup

All values or transitions associated with ignored bins are excluded from coverage. Ignored values or transitions are excluded even if they are also included in another bin.

Group

20.4 定义覆盖点

链接
20.4 定义覆盖点


20.4.5 Specifying Illegal coverage point values or transitions

链接
20.4 定义覆盖点
SystemVerilog 3.1a语言参考手册
20.4.5 Specifying Illegal coverage point values or transitions
20.4 定义覆盖点

A set of values or transitions associated with a coverage-point can be marked as illegal by specifying them as illegal_bins. For example:

Copy Code
covergroup cg3;
    coverpoint b
    {
        illegal_bins bad_vals = {1,2,3};
        illegal_bins bad_trans = (4=>5=>6);
    }
endgroup

All values or transitions associated with illegal bins are excluded from coverage. If they occur, a run-time error is issued. Illegal bins take precedence over any other bins, that is, they will result in a run-time error even if they are also included in another bin.

Group

20.4 定义覆盖点

链接
20.4 定义覆盖点


20.5 Defining cross coverage

链接
第二十章 覆盖, 主题
SystemVerilog 3.1a语言参考手册
20.5 Defining cross coverage
第二十章 覆盖 | 主题

A coverage group can specify cross coverage between two or more coverage points or variables. Cross coverage is specified using the cross construct. When a variable V is part of a cross coverage, SystemVerilog implicitly creates a coverage point for the variable, as if it had been created by the statement coverpoint V;. Thus, a cross involves only coverage points. Expressions cannot be used directly in a cross; a coverage point must be explicitly defined first.

The syntax for specifying cross coverage is given below.

Copy Code
cover_cross ::=         // from Annex A.2.11
    [cover_point_identifer :] cross list_of_coverpoints[iff(expression)] select_bins_or_empty

list_of_coverpoints ::= cross_item , cross_item {, cross_item }

cross_item ::=
    cover_point_identifier
  | variable_identifier

select_bins_or_empty ::=
    {{bins_selections_or_option;}}
  | ;

bins_selection_or_option ::=
    {attribute_instance} coverage_option
  | {attribute_instance} bins_selection

bins_selection ::= bins_keyword bin_identifier=select_expression[iff(expression)]

select_expression ::=
    select_condition
  | !select_condition
  | select_expression && select_expression
  | select_expression || select_expression
  | (select_expression)

select_condition ::= binsof(bins_expression)[intersect{open_range_list}]

bins_expression ::=
    variable_identifier
  | cover_point_identifier[.bins_identifier]

open_range_list ::= open_value_range {, open_value_range}

open_value_range ::= value_range

Syntax 20-4—Cross coverage syntax (excerpt from Annex A)

The label for a cross declaration provides an optional name. The label also creates a hierarchical scope for the bins defined within the cross.

The expression within the optional iff provides a conditional guard for the cross coverage. If at any sample point, the condition evaluates to false, the cross coverage is ignored. The expression within the optional iff construct at the end of a cross bin definition provides a per-bin guard condition. If the expression is false, the cross bin is ignored.

Cross coverage of a set of N coverage points is defined as the coverage of all combinations of all bins associated with the N coverage points, that is, the Cartesian product of the N sets of coverage-point bins. For example:

Copy Code
bit [3:0] a, b;
covergroup cov @(posedge clk);
    aXb : cross a, b;
endgroup

The coverage group cov in the example above specifies the cross coverage of two 4-bit variables, a and b. SystemVerilog implicitly creates a coverage point for each variable. Each coverage point has 16 bins, namely auto[0]...auto[15]. The cross of a and b (labeled aXb), therefore, has 256 cross products, and each cross product is a bin of aXb.

Cross coverage between expressions previously defined as coverage points is also allowed. For example:

Copy Code
bit [3:0] a, b, c;

covergroup cov2 @(posedge clk);
    BC: coverpoint b+c;
    aXb : cross a, BC;
endgroup

The coverage group cov2 has the same number of cross products as the previous example, but in this case, one of the coverage points is the expression b+c, which is labeled BC.

Copy Code
bit [31:0] a_var;
bit [3:0] b_var;

covergroup cov3 @(posedge clk);
    A: coverpoint a_var { bins yy[] = { [0:9] }; }
    CC: cross b_var, A;
endgroup

The coverage group cov3 crosses variable b_var with coverage point A (labeled CC). Variable b_var automatically creates 16 bins (auto[0]...auto[15]). Coverage point A explicitly creates 10 bins yy[0]...yy[9]. The cross of two coverage points creates 16 * 10 = 160 cross product bins, namely the pairs shown below:

Copy Code
<auto[0], yy[0]>
<auto[0], yy[1]>
...
<auto[0], yy[9]>
<auto[1], yy[0]>
...
<auto[15], yy[9]>

Cross coverage is allowed only between coverage points defined within the same coverage group. Coverage points defined in a coverage group other than the one enclosing the cross cannot participate in a cross. Attempts to cross items from different coverage groups shall result in a compiler error.

In addition to specifying the coverage points that are crossed, SystemVerilog includes a powerful set of operators that allow defining cross coverage bins. Cross coverage bins can be specified in order to group together a set of cross products. A cross-coverage bin associates a name and a count with a set of cross products. The count of the bin is incremented every time any of the cross products match, i.e., every coverage point in the cross matches its corresponding bin in the cross product.

User-defined bins for cross coverage are defined using bins select-expressions. The syntax for defining these bin selection expressions is given in Syntax 20-4.

The binsof construct yields the bins of its expression, which can be either a coverage point (explicitly defined or implicitly defined for a single variable) or a coverage-point bin. The resulting bins can be further selected by including (or excluding) only the bins whose associated values intersect a desired set of values. The desired set of values can be specified using a comma-separated list of open_value_range as shown in Syntax 20-4. For example, the following select expression:

Copy Code
binsof( x ) intersect { y }

denotes the bins of coverage point x whose values intersect the range given by y. Its negated form:

Copy Code
! binsof( x ) intersect { y }

denotes the bins of coverage point x whose values do not intersect the range given by y.

The open_value_range syntax can specify a single value, a range of values, or an open range, which denotes the following:

Copy Code
[ $ : value ] => The set of values less than or equal to value
[ value : $ ] => The set of values greater or equal to value

The bins selected can be combined with other selected bins using the logical operators && and || .

Group

第二十章 覆盖

主题
主题 | 描述
20.5.1 Example of user-defined cross coverage and select expressions |
20.5.2 Excluding cross products | A group of bins can be excluded from coverage by specifying a select expression using ignore_bins. For example:
20.5.3 Specifying Illegal cross products | A group of bins can be marked as illegal by specifying a select expression using illegal_bins. For example:
链接
第二十章 覆盖, 主题


20.5.1 Example of user-defined cross coverage and select expressions

链接
20.5 Defining cross coverage
SystemVerilog 3.1a语言参考手册
20.5.1 Example of user-defined cross coverage and select expressions
20.5 Defining cross coverage
Copy Code
bit [7:0] v_a, v_b;

covergroup cg @(posedge clk);
    a: coverpoint v_a
    {
        bins a1 = { [0:63] };
        bins a2 = { [64:127] };
        bins a3 = { [128:191] };
        bins a4 = { [192:255] };
    }

    b: coverpoint v_b
    {
        bins b1 = {0};
        bins b2 = { [1:84] };
        bins b3 = { [85:169] };
        bins b4 = { [170:255] };
    }

    c : cross v_a, v_b
    {
        bins c1 = ! binsof(a) intersect {[100:200]};// 4 cross products
        bins c2 = binsof(a.a2) || binsof(b.b2);// 7 cross products
        bins c3 = binsof(a.a1) && binsof(b.b4);// 1 cross product
    }
endgroup

The example above defines a coverage-group named cg that samples its cover-points on the positive edge of signal clk (not shown). The coverage-group includes two cover-points, one for each of the two 8-bit variables, v_a and v_b. The coverage-point labeled ‘a’ associated with variable v_a, defines four equal-sized bins for each possible value of variable v_a. Likewise, the coverage-point labeled ‘b’ associated with variable v_b, defines four bins for each possible value of variable v_b. The cross definition labeled ‘c’, specifies the cross coverage of the two cover-points v_a and v_b. If the cross coverage of cover-points a and b were defined without any additional cross-bins (select expressions), then cross coverage of a and b would include 16 cross products corresponding to all combinations of bins a1 through a4 with bins b1 through b4, that is, cross products <a1, b1>, <a1,b2>, <a1,b3>, <a1,b4>...<a4, b1>, <a4,b2>, <a4,b3>, <a4,b4>.

The first user-defined cross bin, c1, specifies that c1should include only cross products of cover-point a that do not intersect the value range 100-200. This select expression excludes bins a2, a3, and a4. Thus, c1 will cover only four cross-products of <a1,b1>, <a1,b2>, <a1,b3>, and <a1,b4>.

The second user-defined cross bin, c2, specifies that bin c2 should include only cross products whose values are covered by bin a2 of cover-point a or cross products whose values are covered by bin b2 of cover-point b. This select expression includes the following 7 cross products: <a2, b1>, <a2,b2>, <a2,b3>, <a2,b4>, <a1, b2>, <a3,b2>, and <a4,b2>.

The final user-defined cross bin, c3, specifies that c3 should include only cross products whose values are covered by bin a1 of cover-point a and cross products whose values are covered by bin b4 of cover-point b. This select expression includes only one cross-product <a1, b4>.

When select expressions are specified on transition bins, the binsof operator uses the last value of the transition.

Group

20.5 Defining cross coverage

链接
20.5 Defining cross coverage


20.5.2 Excluding cross products

链接
20.5 Defining cross coverage
SystemVerilog 3.1a语言参考手册
20.5.2 Excluding cross products
20.5 Defining cross coverage

A group of bins can be excluded from coverage by specifying a select expression using ignore_bins. For example:

Copy Code
covergroup yy;
    cross a, b
    {
        ignore_bins foo = binsof(a) intersect { 5, [1:3] };
    }
endgroup

All cross products that satisfy the select expression are excluded from coverage. Ignored cross products are excluded even if they are included in other cross-coverage bins of the enclosing cross.

Group

20.5 Defining cross coverage

链接
20.5 Defining cross coverage


20.5.3 Specifying Illegal cross products

链接
20.5 Defining cross coverage
SystemVerilog 3.1a语言参考手册
20.5.3 Specifying Illegal cross products
20.5 Defining cross coverage

A group of bins can be marked as illegal by specifying a select expression using illegal_bins. For example:

Copy Code
covergroup zz(int bad);
    cross x, y
    {
        illegal_bins foo = binsof(y) intersect {bad};
    }
endgroup

All cross products that satisfy the select expression are excluded from coverage, and a run-time error is issued. Illegal cross products take precedence over any other cross products, that is, they will result in a run-time error even if they are also explicitly ignored (using an ignore_bins) or included in another cross bin.

Group

20.5 Defining cross coverage

链接
20.5 Defining cross coverage


20.6 Specifying coverage options

链接
第二十章 覆盖, 主题
SystemVerilog 3.1a语言参考手册
20.6 Specifying coverage options
第二十章 覆盖 | 主题

Options control the behavior of the covergroup, coverpoint and cross. There are two types of options: those that are specific to an instance of a covergroup, and those that specify an option for the covergroup type as a whole.

The following table lists instance specific covergroup options and their description. Each instance of a covergroup can initialize an instance specific option to a different value. The initialized option value affects only

that instance.

Table 20-1: Instance specific coverage options

Option name | Default | Description
weight= number | 1 | If set at the covergroup syntactic level, it specifies the weight of this covergroup instance for computing the overall instance coverage of the simulation. If set at the coverpoint (or cross) syntactic level, it specifies the weight of a coverpoint (or cross) for computing the instance coverage of the enclosing covergroup.
goal=number | 90 | Specifies the target goal for a covergroup instance, or a coverpoint or a cross of an instance.
name=string | unique name | Specify a name for the covergroup instance. If unspecified, a unique name for each instance is automatically generated by the tool.
comment=string | “” | A comment that appears with the instance of a covergroup, or a coverpoint or cross of the covergroup instance. The comment is saved in the coverage database and included in the coverage report.
at_least=number | 1 | Minimum number of hits for each bin. A bin with a hit count that is less than number is not considered covered.
detect_overlap=boolean | 0 | When true, a warning is issued if there is an overlap between the range list (or transition list) of two bins of a coverpoint.
auto_bin_max=number | 64 | Maximum number of automatically created bins when no bins are explicitly defined for a coverpoint.
cross_auto_bin_max=number | unbounded | Maximum number of automatically created cross product bins for a cross.
cross_num_print_missing= number | 0 | Number of missing (not covered) cross product bins that must be saved to the coverage database and printed in the coverage report.
per_instance=boolean | 0 | Each instance contributes to the overall coverage information for the covergroup type. When true, coverage information for this covergroup instance is tracked as well.

The instance specific options mentioned above can be set in the covergroup definition. The syntax for setting these options in the covergroup definition is:

Copy Code
option.option_name = expression ;

The identifier option is a built-in member of any coverage group (see Section 20.9 for a description). An example is shown below.

Copy Code
covergroup g1 (int w, string instComment) @(posedge clk) ;
    // track coverage information for each instance of g1 in addition
    // to the cumulative coverage information for covergroup type g1
    option.per_instance = 1;

    // comment for each instance of this covergroup
    option.comment = instComment;

    a : coverpoint a_var
    {
        // Create 128 automatic bins for coverpoint “a” of each instance of g1
        option.auto_bin_max = 128;
    }

    b : coverpoint b_var
    {
        // This coverpoint contributes w times as much to the coverage of an
        // instance of g1 than coverpoints "a" and "c1"
        option.weight = w;
    }

    c1 : cross a_var, b_var ;
endgroup

Option assignment statements in the covergroup definition are evaluated at the time that the covergroup is instantiated. The per_instance option can only be set in the covergroup definition. Other instance specific options can be set procedurally after a covergroup has been instantiated. The syntax is:

Copy Code
coverage_option_assignment ::=   // not in Annex A
    instance_name.option.option_name = expression;
  | instance_name.covergroup_item_identifier.option.option_name = expression;

Syntax 20-5—Coverage option assignment syntax (not in Annex A)

Here is an example:

Copy Code
covergroup gc @(posedge clk) ;
    a : coverpoint a_var;
    b : coverpoint b_var;
endgroup
...
gc g1 = new;
g1.option.comment = "Here is a comment set for the instance g1";
g1.a.option.weight = 3; // Set weight for coverpoint “a” of instance g1

The following table summarizes the syntactical level (covergroup, coverpoint, or cross) at which instance options can be specified. All instance options can be specified at the covergroup level. Except for the weight, goal, comment, and per_instance options, all other options set at the covergroup syntactic level act as a default value for the corresponding option of all coverpoints and crosses in the covergroup. Individual coverpoint or crosses can overwrite these default values. When set at the covergroup level, the weight, goal, comment, and per_instance options do not act as default values to the lower syntactic levels.

Table 20-2: Coverage options per-syntactic level

Option name | Allowed in Syntactic Level |  |
 | covergroup | coverpoint | cross
name | Yes | No | No
weight | Yes | Yes | Yes
goal | Yes | Yes | Yes
comment | Yes | Yes | Yes
al_least | Yes (default for coverpoints & crosses) | Yes | Yes
detect_overlap | Yes (default for coverpoints) | Yes | No
auto_bin_max | Yes (default for coverpoints) | Yes | No
cross_auto_bin_max | Yes (default for crosses) | No | Yes
cross_num_print_missing | Yes (default for crosses) | No | Yes
per_instance | Yes | No | No
Group

第二十章 覆盖

主题
主题 | 描述
20.6.1 Covergroup Type Options | The following table lists options that describe a particular feature (or property) of the covergroup type as a whole. They are analogous to static data members of classes. Table 20-3: Coverage group type (static) options
链接
第二十章 覆盖, 主题


20.6.1 Covergroup Type Options

链接
20.6 Specifying coverage options
SystemVerilog 3.1a语言参考手册
20.6.1 Covergroup Type Options
20.6 Specifying coverage options

The following table lists options that describe a particular feature (or property) of the covergroup type as a whole. They are analogous to static data members of classes.

Table 20-3: Coverage group type (static) options

Option name | Default | Description
weight=constant_number | 1 | If set at the covergroup syntactic level, it specifies the weight of this covergroup for computing the overall cumulative (or type) coverage of the saved database. If set at the coverpoint (or cross) syntactic level, it specifies the weight of a coverpoint (or cross) for computing the cumulative (or type) coverage of the enclosing covergroup.
goal=constant_number | 90 | Specifies the target goal for a covergroup type, or a coverpoint or cross of a covergroup type.
comment=string_literal | "" | A comment that appears with the covergroup type, or a coverpoint or cross of the covergroup type. The comment is saved in the coverage database and included in the coverage report.
strobe=constant_number | 0 | If set to 1, all samples happen at the end of the time slot, like the $strobe system task.

The covergroup type options mentioned above can be set in the covergroup definition. The syntax for setting these options in the covergroup definition is:

Copy Code
type_option.option_name = expression ;

The identifier type_option is a built-in member of any coverage group (see Section 20.9 for a description).

Different instances of a covergroup cannot assign different values to type options. This is syntactically disallowed, since these options can only be initialized via constant expressions. Here is an example:

Copy Code
covergroup g1 (int w, string instComment) @(posedge clk) ;
    // track coverage information for each instance of g1 in addition
    // to the cumulative coverage information for covergroup type g1
    option.per_instance = 1;
    type_option.comment = "Coverage model for features foo and bar";
    type_option.strobe = 1; // sample at the end of the time slot

    // comment for each instance of this covergroup
    option.comment = instComment;

    a : coverpoint a_var
   {
        // Use weight 2 to compute the coverage of each instance
        option.weight = 2;

        // Use weight 3 to compute the cumulative (type) coverage for g1
        type_option.weight = 3;
        // NOTE: type_option.weight = w would cause syntax error.
    }

    b : coverpoint b_var
    {
        // Use weight w to compute the coverage of each instance
        option.weight = w;

        // Use weight 5 to compute the cumulative (type) coverage of g1
        type_option.weight = 5;
    }
endgroup

In the above example the coverage for each instance of g1 is computed as:

Copy Code
(((instance coverage of “a”) * 2) + ((instance coverage of “b”) * w)) / ( 2 + w)

On the other hand the coverage for covergroup type “g1” is computed as:

Copy Code
( ((overall type coverage of “a”) * 3) + ((overall type coverage of “b”) * 5) ) / (3 + 5).

Type options can be set procedurally at any time during simulation. The syntax is:

Copy Code
coverage_type_option_assignment ::=   // not in Annex A
    covergroup_name::type_option.option_name=expression;
  | covergroup_name::covergroup_item_identifier::type_option.option_name=expression;

Syntax 20-6—Coverage type option assignment syntax (not in Annex A)

Here is an example:

Copy Code
covergroup gc @(posedge clk) ;
    a : coverpoint a_var;
    b : coverpoint b_var;
endgroup
...
gc::type_option.comment = "Here is a comment for covergroup g1";
// Set the weight for coverpoint "a" of covergroup g1
gc::a::type_option.weight = 3;
gc g1 = new;

The following table summarizes the syntactical level (covergroup, coverpoint, or cross) in which type options can be specified. When set at the covergroup level, the type options do not act as defaults for lower syntactic levels.

Table 20-4: Coverage type-options

Option name | Allowed Syntactic Level |  |
 | covergroup | coverpoint | cross
weight | Yes | Yes | Yes
goal | Yes | Yes | Yes
comment | Yes | Yes | Yes
strobe | Yes | No | No
Group

20.6 Specifying coverage options

链接
20.6 Specifying coverage options


20.7 Predefined coverage methods

链接
第二十章 覆盖
SystemVerilog 3.1a语言参考手册
20.7 Predefined coverage methods
第二十章 覆盖

The following coverage methods are provided for the covergroup. These methods can be invoked procedurally at any time.

Table 20-5: Predefined coverage methods

Method (function) | Can be called on |  |  | Description
 | covergroup | coverpoint | cross |
void sample() | Yes | No | No | Triggers sampling of the covergroup
real get_coverage() | Yes | Yes | Yes | Calculates type coverage number (0...100)
real get_inst_coverage() | Yes | Yes | Yes | Calculates the coverage number (0...100)
void set_inst_name(string) | Yes | No | No | Sets the instance name to the given string
void start() | Yes | Yes | Yes | Starts collecting coverage information
void stop() | Yes | Yes | Yes | Stops collecting coverage information
real query() | Yes | Yes | Yes | Returns the cumulative coverage information (for the coverage group type as a whole)
real inst_query() | Yes | Yes | Yes | Returns the per-instance coverage information for this instance
Group

第二十章 覆盖

链接
第二十章 覆盖


20.8 Predefined coverage system tasks and functions

链接
第二十章 覆盖
SystemVerilog 3.1a语言参考手册
20.8 Predefined coverage system tasks and functions
第二十章 覆盖

SystemVerilog provides the following system tasks and functions to help manage coverage data collection.

$set_coverage_db_name ( name ) — Sets the filename of the coverage database into which coverage information is saved at the end of a simulation run.

$load_coverage_db ( name ) — Load from the given filename the cumulative coverage information for all coverage group types.

$get_coverage ( ) — Returns as a real number in the range 0 to 100 the overall coverage of all coverage group types. This number is computed as described above.

Group

第二十章 覆盖

链接
第二十章 覆盖


20.9 Organization of option and type_option members

链接
第二十章 覆盖
SystemVerilog 3.1a语言参考手册
20.9 Organization of option and type_option members
第二十章 覆盖

The type and type_option members of a covergroup, coverpoint, and cross items are implicitly declared structures with the following composition:

Copy Code
struct // covergroup option declaration
{
    string name ;
    int weight ;
    int goal ;
    string comment ;
    int at_least ;
    int auto_bin_max ;
    int cross_auto_bin_max ;
    int cross_num_print_missing ;
    bit detect_overlap ;
    bit per_instance ;
} option;

struct // coverpoint option declaration
{
    int weight ;
    int goal ;
    string comment ;
    int at_least ;
    int auto_bin_max ;
    bit detect_overlap ;
} option;

struct // cross option declaration
{
    int weight ;
    int goal ;
    string comment ;
    int at_least ;
    int cross_auto_bin_max ;
    int cross_num_print_missing ;
} option;

struct // covergroup type_option declaration
{
    int weight ;
    int goal ;
    string comment ;
    bit strobe ;
} type_option;

struct // coverpoint and cross type_option declaration
{
    int weight ;
    int goal ;
    string comment ;
} type_option;
Group

第二十章 覆盖

链接
第二十章 覆盖


第二十一章 参数

链接
主题
SystemVerilog 3.1a语言参考手册
第二十一章 参数
主题
主题
主题
描述
21.1 简介（一般信息）
Verilog-2001提供了三种结构来定义编译时常量：parameter、localparam和specparam语句。

SystemVerilog提供了四种方法来设置设计中的参数常量的值。每一个参数在声明时必须指定一个缺省值。我们可以使用下列方法之一来改变每一个模块实例的缺省参数值：
  • 隐含的内联参数重定义（例如：foo #(value, value) u1(...);）
  • 显式的内联参数重定义（例如：#(.name(value), .name(value)) u1 (...); ）
  • defparam语句，使用层次化路径名来重新定义每一个参数
21.2 参数声明语法
链接
主题


21.1 简介（一般信息）

链接
第二十一章 参数, 主题
SystemVerilog 3.1a语言参考手册
21.1 简介（一般信息）
第二十一章 参数 | 主题

Verilog-2001提供了三种结构来定义编译时常量：parameter、localparam和specparam语句。

SystemVerilog提供了四种方法来设置设计中的参数常量的值。每一个参数在声明时必须指定一个缺省值。我们可以使用下列方法之一来改变每一个模块实例的缺省参数值：

  • 隐含的内联参数重定义（例如：foo #(value, value) u1(...);）
  • 显式的内联参数重定义（例如：#(.name(value), .name(value)) u1 (...); ）
  • defparam语句，使用层次化路径名来重新定义每一个参数

Group

第二十一章 参数

主题
主题 | 描述
21.1.1 defparam语句的删除 | defparam语句可能会从SystemVerilog语言的未来版本中删除，参见26.2节。
链接
第二十一章 参数, 主题


21.1.1 defparam语句的删除

链接
21.1 简介（一般信息）
SystemVerilog 3.1a语言参考手册
21.1.1 defparam语句的删除
21.1 简介（一般信息）

defparam语句可能会从SystemVerilog语言的未来版本中删除，参见26.2节。

Group

21.1 简介（一般信息）

链接
21.1 简介（一般信息）


21.2 参数声明语法

链接
第二十一章 参数
SystemVerilog 3.1a语言参考手册
21.2 参数声明语法
第二十一章 参数
Copy Code
local_parameter_declaration ::=           // 引用自附录A.2.1.1
    localparam data_type_or_implicit list_of_param_assignments;

parameter_declaration ::=
    parameter data_type_or_implicit list_of_param_assignments
  | parameter type list_of_type_assignments

specparam_declaration ::=
    specparam [packed_dimension] list_of_specparam_assignments;

data_type_or_implicit ::=                // 引用自附录A.2.2.1
    data_type
  | [signing] {packed_dimension}

list_of_param_assignments ::= param_assignment {, param_assignment} // 引用自附录A.2.3

list_of_specparam_assignments ::= specparam_assignment {, specparam_assignment}

list_of_type_assignments ::= type_assignment {, type_assignment}

param_assignment ::=                    // 引用自附录A.2.4
    parameter_identifier {unpacked_dimension} = constant_param_expression

specparam_assignment ::=
    specparam_identifier = constant_mintypmax_expression
  | pulse_control_specparam

type_assignment ::= type_identifier = data_type

parameter_port_list ::=                // 引用自附录A.1.4
    #(list_of_param_assignments {, parameter_port_declaration})
  | #(parameter_port_declaration {, parameter_port_declaration})

parameter_port_declaration ::=
    parameter_declaration
  | data_type list_of_param_assignments
  | type list_of_type_assignments

语法 21-1 — 参数声明语法（摘录自附录A）

A module, interface, program or class can have parameters, which are set during elaboration and are constant during simulation. They are defined with data types and default values. With SystemVerilog, if no data type is supplied, parameters default to type logic of arbitrary size for Verilog-2001 compatibility and interoperability. SystemVerilog adds the ability for a parameter to also specify a data type, allowing modules or instances to have data whose type is set for each instance.

Copy Code
module ma #(parameter p1 = 1, parameter type p2 = shortint)
          (input logic [p1:0] i, output logic [p1:0] o);
    p2 j = 0; // type of j is set by a parameter, (shortint unless redefined)

    always @(i) begin
        o = i;
        j++;
    end
endmodule

module mb;
    logic [3:0] i,o;
    ma #(.p1(3), .p2(int)) u1(i,o); //redefines p2 to a type of int
endmodule

SystemVerilog adds the ability for local parameters to be declared in a generate block. Local parameters can also be declared in a package or in a compilation unit scope. In these contexts, the parameter keyword can be used as a synonym for the localparam keyword.

$ can be assigned to parameters of integer types. A parameter to which $ is assigned shall only be used wherever $ can be specified as a literal constant.

For example, $ represents unbounded range specification, where the upper index can be any integer.

Copy Code
parameter r2 = $;

property inq1(r1,r2);
    @(posedge clk) a ##[r1:r2] b ##1 c |=> d;
endproperty

assert inq1(3);

To support whether a constant is $, a system function is provided to test whether a constant is a $. The syntax of the system function is

Copy Code
$isunbounded(const_expression);

$isunbounded returns true if const_expression is unbounded. Typically, $isunbounded would be used as a condition in the generate statement.

The example below illustrates the benefit of using $ in writing properties concisely where the range is parameterized. The checker in the example ensures that a bus driven by signal en remains 0, i.e, quiet for the specified minimum (min_quiet) and maximum (max_quiet) quiet time.

Note that function $isunbounded is used for checking the validity of the actual arguments.

Copy Code
interface quiet_time_checker #(parameter min_quiet = 0,
                               parameter max_quiet = 0)
                              (input logic clk, reset_n, [1:0]en);
    generate
        if ( max_quiet == 0) begin
            property quiet_time;
                @(posedge clk) reset_n |-> ($countones(en) == 1);
            endproperty
            a1: assert property (quiet_time);
        end
        else begin
            property quiet_time;
                @(posedge clk)
                    (reset_n && ($past(en) != 0) && en == 0)
                    |->(en == 0)[*min_quiet:max_quiet]
                ##1 ($countones(en) == 1);
            endproperty
            a1: assert property (quiet_time);
        end

        if ((min_quiet == 0) && ($isunbounded(max_quiet))
            $display(warning_msg);
    endgenerate
endinterface

quiet_time_checker #(0, 0) quiet_never (clk,1,enables);
quiet_time_checker #(2, 4) quiet_in_window (clk,1,enables);
quiet_time_checker #(0, $) quiet_any (clk,1,enables);

Another example below illustrates that by testing for $, a property can be configured according to the requirements. When parameter max_cks is unbounded, it is not required to test for expr to become false.

Copy Code
interface width_checker #(parameter min_cks = 1, parameter max_cks = 1)
                         (input logic clk, reset_n, expr);
    generate begin
        if ($isunbounded(max_cks)) begin
            property width;
                @(posedge clk)
                    (reset_n && $rose(expr)) |-> (expr [* min_cks]);
            endproperty

            a2: assert property (width);
        end
        else begin
            property assert_width_p;
                @(posedge clk)
                    (reset_n && $rose(expr)) |-> (expr[* min_cks:max_cks])
                    ##1 (!expr);
            endproperty

            a2: assert property (width);
        end
    endgenerate
endinterface

width_checker #(3, $) max_width_unspecified (clk,1,enables);
width_checker #(2, 4) width_specified (clk,1,enables);

SystemVerilog also adds the ability to omit the parameter keyword in a parameter port list.

Copy Code
class vector #(size = 1);
    logic [size-1:0] v;
endclass

typedef vector#(16) word;

interface simple_bus #(AWIDTH = 64, type T = word) (input bit clk) ;
endinterface

In a list of parameters, a parameter can depend on earlier parameters. In the following declaration, the default value of the second parameter depends on the value of the first parameter. The third parameter is a type, and the fourth parameter is a value of that type.

Copy Code
module mc #(int N = 5, M = N*16, type T = int, T x = 0)
           ( ... );
    ...
endmodule
Group

第二十一章 参数

链接
第二十一章 参数


第二十二章 配置库

链接
主题
SystemVerilog 3.1a语言参考手册
第二十二章 配置库
主题
主题
主题 | 描述
22.1 简介（一般信息） | Verilog-2001提供了指定设计配置的能力，它指定了模块实例与特定Verilog HDL源代码之间的绑定信息。配置使用库。一个库是模块、原语、及其它配置的集合。分离的库映射文件指定了包含在库中的单元的源代码位置。库映射文件的名字典型情况下指定成仿真器或其它读入Verilog源代码的软件工具的调用选项。 SystemVerilog为Verilog配置加入了对接口的支持。
22.2 库 | 一个库是许多单元的命名集合。一个单元可以是一个模块、宏模块、原语、接口、程序、包或配置。一个配置是源代码与设计中的每一个实例之间的绑定规范。
链接
主题


22.1 简介（一般信息）

链接
第二十二章 配置库
SystemVerilog 3.1a语言参考手册
22.1 简介（一般信息）
第二十二章 配置库

Verilog-2001提供了指定设计配置的能力，它指定了模块实例与特定Verilog HDL源代码之间的绑定信息。配置使用库。一个库是模块、原语、及其它配置的集合。分离的库映射文件指定了包含在库中的单元的源代码位置。库映射文件的名字典型情况下指定成仿真器或其它读入Verilog源代码的软件工具的调用选项。

SystemVerilog为Verilog配置加入了对接口的支持。

Group

第二十二章 配置库

链接
第二十二章 配置库


22.2 库

链接
第二十二章 配置库
SystemVerilog 3.1a语言参考手册
22.2 库
第二十二章 配置库

一个库是许多单元的命名集合。一个单元可以是一个模块、宏模块、原语、接口、程序、包或配置。一个配置是源代码与设计中的每一个实例之间的绑定规范。

Group

第二十二章 配置库

链接
第二十二章 配置库


第二十三章 系统任务与系统函数

链接
主题
SystemVerilog 3.1a语言参考手册
第二十三章 系统任务与系统函数
主题
主题
主题
描述
23.1 简介（一般信息）
SystemVerilog加入了几个将在下面几节中描述的系统任务和系统函数。

另外，SystemVerilog扩展了几个Verilog-2001系统任务的行为，这些扩展将在23.14节中描述。
23.2 确立时的typeof函数
23.3 typename函数
23.4 表达式尺寸系统函数
23.5 范围系统函数
23.6 Shortreal转换
Verilog 2001 defines a real data type, and the system functions $realtobits and $bitstoreal to permit exact bit pattern transfers between a real and a 64 bit vector. SystemVerilog adds the shortreal type, and in a parallel manner, $shortrealtobits and $bitstoshortreal are defined to permit exact bit transfers between a shortreal and a 32 bit vector.
23.7 数组查询系统函数
23.8 断言严重性系统任务
23.9 断言控制系统任务
23.10 断言系统函数
23.11 随机数系统函数
To supplement the Verilog $random system function, SystemVerilog provides three special system functions for generating pseudorandom numbers, $urandom, $urandom_range and $srandom. These system functions are presented in Section 12.12.
23.12 程序控制
In addition to the normal simulation control tasks ($stop and $finish), a program can use the $exit control task. When all programs exit, the simulation finishes and an implicit call to $finish is made. The usage of $exit is presented in Section 16.6 on program blocks.
23.13 覆盖系统函数
SystemVerilog has several built-in system functions for obtaining test coverage information: $coverage_control, $coverage_get_max, $coverage_get, $coverage_merge and $coverage_save. The coverage system functions are described in Section 29.2.
23.14 对Verilog-2001系统任务的增强
SystemVerilog adds system tasks and system functions as described in the following sections. In addition, SystemVerilog extends the behavior of the following:
  • %u and %z format specifiers:
    • For packed data, %u and %z are defined to operate as though the operation were applied to the equivalent vector.
    • For unpacked struct data, %u and %z are defined to apply as though the operation were performed on each member in declaration order.
    • For unpacked union data, %u and %z are defined to apply as though the operation were performed on the first member in declaration order.
    • %u and %z are not defined... more
23.15 $readmemb与$readmemh
23.16 $writememb and $writememh
SystemVerilog introduces system tasks $writememb and $writememh:
23.17 File format considerations for multi-dimensional unpacked arrays
In SystemVerilog, $readmemb, $readmemh, $writememb and $writememh can work with multi-dimensional unpacked arrays.

The file contents are organized in row-major order, with each dimension’s entries ranging from low to high address. This is backward compatible with plain Verilog memories.

In this organization, the lowest dimension (i.e. the right-most dimension in the array declaration) varies the most rapidly. There is a hierarchical sense to the file data. The higher dimensions contain words of lowerdimension data, sorted in row-major order. Each successive lower dimension is entirely enclosed as part of higher dimension words.

As an example of file format organization, here is... more
23.18 System task arguments for multi-dimensional unpacked arrays
The $readmemb, $readmemh, $writememb, and $writememh signatures are shown below:
链接
主题


23.1 简介（一般信息）

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.1 简介（一般信息）
第二十三章 系统任务与系统函数

SystemVerilog加入了几个将在下面几节中描述的系统任务和系统函数。

另外，SystemVerilog扩展了几个Verilog-2001系统任务的行为，这些扩展将在23.14节中描述。

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.2 确立时的typeof函数

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.2 确立时的typeof函数
第二十三章 系统任务与系统函数
Copy Code
typeof_function ::=           // 没有包含在附录A中
    $typeof(expression)
  | $typeof(data_type)

语法 23-1 — typeof函数语法（没有包含在附录A中）

$typeof系统函数返回它的自变量的数据类型。$typeof系统函数返回的数据类型可以用来赋值或覆盖一个类型参数，或者在确立过程中与另外一个$typeof系统函数返回的数据类型进行比较。

在调用时，如果将表达式作为它的自变量，那么$typeof返回一个代表表达式自决类型结果的类型。表达式的返回类型在确立时确定，但永远不会对其求值。表达式不应包含任何层次化的标识符或对动态对象元素的引用。在所有的关联文中，$typeof与它的自变量一起可以使用在要求确立时常量的任何地方。

当使用在比较表达式中的时候，如果操作数是类型等价的（参见5.8节中有关类型等价的内容），那么等式(==)或条件等式(===)的结果为“真”。

例如：

Copy Code
bit [12:0] A_bus, B_bus;
parameter type bus_t = $typeof(A_bus);

generate
    case ($typeof(but_t))
        $typeof(bit[12:0]): addfixed_int #(bus_t) (A_bus,B_bus);
        $typeof(real): add_float #($typeof(A_bus)) (A_bus,B_bus);
    endcase
endgenerate

对用户来讲，$typeof返回的真实值是不可见的并且是未定义的。

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.3 typename函数

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.3 typename函数
第二十三章 系统任务与系统函数
Copy Code
typename_function ::=        // 没有包含在附录A中
    $typename(expression)
  | $typename(data_type)

语法 23-2 — typename函数语法（没有包含在附录A中）

$typename系统函数返回一个代表其自变量的解析类型的字符串。

The return string is constructed in the following steps:

  1. A typedef that creates an equivalent type is resolved back to built-in or user defined types.
  2. The default signing is removed, even if present explicitly in the source
  3. System generated names are created for anonymous structs, unions and enums.
  4. A ‘$’ is used as the placeholder for the name of an anonymous unpacked array.
  5. Actual encoded values are appended with numeration named constants.
  6. User defined type names are prefixed with their defining package or scope namespace.
  7. Array ranges are represented as unsized decimal numbers.
  8. Whitespace in the source is removed and a single space is added to separate identifiers and keywords from each other.
This process is similar to the way that type equality is computed, except that array ranges and built-in equivalent types are not normalized in the generated string. Thus $typename can be used in string comparisons for stricter type-checking of arrays than $typeof.

When called with an expression as its argument, $typename returns a string that represents the self-determined type result of the expression. The expression's return type is determined during elaboration but never evaluated. When used as an elaboration time constant, the expression shall not contain any hierarchical identifiers or references to elements of dynamic objects.

Copy Code
// source code // $typename would return
typedef bit node; // "bit"
node signed [2:0] X; // "bit signed[2:0]"
int signed Y; // "int"

package A;
    enum {A,B,C=99} X; // "enum{A=32’d0,B=32’d1,C=’32bX}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
Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.4 表达式尺寸系统函数

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.4 表达式尺寸系统函数
第二十三章 系统任务与系统函数
Copy Code
size_function ::=        // 没有包含在附录A中
    $bits(expression)
  | $bits(type_identifier)

语法23-3 — 尺寸函数语法（没有包含在附录A中）

$bits系统函数返回将一个表达式作为位流保存时所需要的位数。参见3.16节，一个有效类型定义的位流强制类型转换。一个四态值作为一位计数。对于下面的声明：

Copy Code
logic [31:0] foo;

那么$bits(foo)应该返回32，尽管软件实现会采用多于32位的存储空间来代表四态值。对于下面的声明：

Copy Code
typedef struct {
    logic valid;
    bit [8:1] data;
} MyType;

表达式$bits(MyType) 应返回9，也就是类型为MyType的变量所需要的数据位的数目。当用于固定尺寸类型的时候，$bits函数可以作为一个确立时常量使用。 因此，它可以用在其它类型或变量的声明中。

Copy Code
typedef bit[$bits(MyType):1] MyBits; // 与typedef bit [9:1] MyBits;相同
MyBits b;

变量b可以用来保留类型为MyType的变量的位模式而不会丢失任何信息。当作用于一个当前为空的动态尺寸类型的时候，$bits系统函数返回0。将$bits系统函数直接与动态尺寸类型标识符一起使用是错误的。

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.5 范围系统函数

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.5 范围系统函数
第二十三章 系统任务与系统函数
Copy Code
range_function ::=    // 没有包含在附录A中
    $isunbounded(constant_expression)

语法 23-4 — 范围函数语法（没有包含在附录A中）

如果$isunbounded系统函数的自变量是$，那么它返回“真”。对于下面的声明：

Copy Code
parameter int foo = $;

$isunbounded应返回“真”。

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.6 Shortreal转换

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.6 Shortreal转换
第二十三章 系统任务与系统函数

Verilog 2001 defines a real data type, and the system functions $realtobits and $bitstoreal to permit exact bit pattern transfers between a real and a 64 bit vector. SystemVerilog adds the shortreal type, and in a parallel manner, $shortrealtobits and $bitstoshortreal are defined to permit exact bit transfers between a shortreal and a 32 bit vector.

Copy Code
[31:0] $shortrealtobits(shortreal_val);
shortreal $bitstoshortreal(bit_val);

$shortrealtobits converts from a shortreal number to the 32-bit representation (vector) of that shortreal number. $bitstoshortreal is the reverse of $shortrealtobits; it converts from the bit pattern to a shortreal number.

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.7 数组查询系统函数

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.7 数组查询系统函数
第二十三章 系统任务与系统函数
Copy Code
array_query_function ::=                  // not in Annex A
    array_dimension_function(array_identifier, dimension_expression)
  | array_dimension_function(type_identifier[, dimension_expression])
  | $dimensions(array_identifier)
  | $dimensions(type_identifier)

array_dimension_function ::=
    $left
  | $right
  | $low
  | $high
  | $increment
  | $size

dimension_expression ::= expression

Syntax 23-5—Array querying function syntax (not in Annex A)

SystemVerilog provides system functions to return information about a particular dimension of an array variable or type. The return type is integer, and the default for the optional dimension expression is 1. The array dimension can specify any fixed sized index (packed or unpacked), or any dynamically sized index (dynamic, associative, or queue).

  • $left shall return the left bound (msb) of the dimension
  • $right shall return the right bound (lsb) of the dimension
  • $low shall return the minimum of $left and $right of the dimension
  • $high shall return the maximum of $left and $right of the dimension
  • $increment shall return 1 if $left is greater than or equal to $right, and -1 if $left is less than $right
  • $size shall return the number of elements in the dimension, which is equivalent to $high - $low + 1
  • $dimensions shall return the number of dimensions in the array, or 0 for a singular object
The dimensions of an array shall be numbered as follows: The slowest varying dimension (packed or unpacked) is dimension 1. Successively faster varying dimensions have sequentially higher dimension numbers. Intermediate type definitions are expanded first before numbering the dimensions.

For example:

Copy Code
//     Dimension numbers
//    3    4       1    2
reg [3:0][2:1] n [1:5][2:8];
typedef reg [3:0][2:1] packed_reg;
packed_reg n[1:5][2:8]; // same dimensions as in the lines above

For a fixed sized integer type (integer, shortint, longint, and byte), dimension 1 is pre-defined. For an integer N declared without a range specifier, its bounds are assumed to be [$bits(N)-1:0].

If an out-of-range dimension is specified, these functions shall return a ’x.

When used on a dynamic array or queue dimension, these functions return information about the current state of the array. If the dimension is currently empty, these functions shall return a ’x. It is an error to use these functions directly on a dynamically sized type identifier.

Use on associative array dimensions is restricted to index types with integral values. With integral indexes, these functions shall return:

  • $left shall return 0
  • $right shall return the highest possible index value
  • $low shall return the lowest currently allocated index value
  • $high shall return the largest currently allocated index value
  • $increment shall return -1
  • $size shall return the number of elements currently allocated
If the array identifier is a fixed sized array, these query functions can be used as a constant function and passed as a parameter before elaboration. These query functions can also be used on fixed sized type identifiers in which case it is always treated as a constant function.

Given the declaration below:

Copy Code
typedef logic [16:1] Word;
Word Ram[0:9];

The following system functions return 16:

Copy Code
$size(Word)
$size(Ram,2)
Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.8 断言严重性系统任务

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.8 断言严重性系统任务
第二十三章 系统任务与系统函数
Copy Code
assert_severity_task ::=   // not in Annex A
    fatal_message_task
  | nonfatal_message_task

fatal_message_task ::= $fatal[(finish_number[, message_argument{, message_argument}])];

nonfatal_message_task ::= severity_task[([message_argument{, message_argument]}])];

severity_task ::= $error | $warning | $info

finish_number ::= 0 | 1 | 2

message_argument ::= string | expression

Syntax 23-6—Assertion severity system task syntax (not in Annex A)

SystemVerilog assertions have a severity level associated with any assertion failures detected. By default, the severity of an assertion failure is “error”. The severity levels can be specified by including one of the following severity system tasks in the assertion fail statement:

  • $fatal shall generate a run-time fatal assertion error, which terminates the simulation with an error code. The first argument passed to $fatal shall be consistent with the corresponding argument to the Verilog $finish system task, which sets the level of diagnostic information reported by the tool. Calling $fatal results in an implicit call to $finish.
  • $error shall be a run-time error.
  • $warning shall be a run-time warning, which can be suppressed in a tool-specific manner.
  • $info shall indicate that the assertion failure carries no specific severity.
All of these severity system tasks shall print a tool-specific message, indicating the severity of the failure, and specific information about the failure, which shall include the following information:
  • The file name and line number of the assertion statement,
  • The hierarchical name of the assertion, if it is labeled, or the scope of the assertion if it is not labeled.
For simulation tools, these tasks shall also report the simulation run-time at which the severity system task is

called.

Each of the severity tasks can include optional user-defined information to be reported. The user-defined message shall use the same syntax as the Verilog $display system task, and can include any number of arguments.

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.9 断言控制系统任务

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.9 断言控制系统任务
第二十三章 系统任务与系统函数
Copy Code
assert_control_task ::=    // not in Annex A
    assert_task[(levels[, list_of_modules_or_assertions])];

assert_task ::=
    $asserton
  | $assertoff
  | $assertkill

list_of_modules_or_assertions ::=
    module_or_assertion{, module_or_assertion}

module_or_assertion ::=
    module_identifier
  | assertion_identifier
  | hierarchical_identifier

Syntax 23-7—Assertion control syntax (not in Annex A)

SystemVerilog provides three system tasks to control assertions.

  • $assertoff shall stop the checking of all specified assertions until a subsequent $asserton. An assertion that is already executing, including execution of the pass or fail statement, is not affected
  • $assertkill shall abort execution of any currently executing specified assertions and then stop the checking of all specified assertions until a subsequent $asserton.
  • $asserton shall re-enable the execution of all specified assertions

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.10 断言系统函数

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.10 断言系统函数
第二十三章 系统任务与系统函数
Copy Code
assert_boolean_functions ::=    // not in Annex A
    assert_function(expression);

assert_function ::=
    $onehot
  | $onehot0
  | $isunknown

Syntax 23-8—Assertion system function syntax (not in Annex A)

Assertions are commonly used to evaluate certain specific characteristics of a design implementation, such as whether a particular signal is “one-hot”. The following system functions are included to facilitate such common assertion functionality:

  • $onehot returns true if one and only one bit of expression is high.
  • $onehot0 returns true if at most one bit of expression is high.
  • $isunknown returns true if any bit of the expression is X or Z. This is equivalent to ^expression === ’bx.
All of the above system functions shall have a return type of bit. A return value of 1’b1 shall indicate true, and a return value of 1’b0 shall indicate false.

A function is provided to return sampled value of an expression.

Copy Code
$sampled ( expression [, clocking_event] )

Three functions are provided for assertions to detect changes in values between two adjacent clock ticks.

Copy Code
$rose ( expression [, clocking_event] )
$fell ( expression [, clocking_event] )
$stable ( expression [, clocking_event] )

The past values can be accessed with the $past function.

Copy Code
$past ( expression [, number_of_ticks] [, expression2] [, clocking_event] )

$sampled, $rose, $fell, $stable and $past are discussed in Section 17.7.3.

The number of 1s in a bit vector expression can be determined with the $countones function.

Copy Code
$countones ( expression )

$countones is discussed in Section 17.10.

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.11 随机数系统函数

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.11 随机数系统函数
第二十三章 系统任务与系统函数

To supplement the Verilog $random system function, SystemVerilog provides three special system functions for generating pseudorandom numbers, $urandom, $urandom_range and $srandom. These system functions are presented in Section 12.12.

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.12 程序控制

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.12 程序控制
第二十三章 系统任务与系统函数

In addition to the normal simulation control tasks ($stop and $finish), a program can use the $exit control task. When all programs exit, the simulation finishes and an implicit call to $finish is made. The usage of $exit is presented in Section 16.6 on program blocks.

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.13 覆盖系统函数

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.13 覆盖系统函数
第二十三章 系统任务与系统函数

SystemVerilog has several built-in system functions for obtaining test coverage information: $coverage_control, $coverage_get_max, $coverage_get, $coverage_merge and $coverage_save. The coverage system functions are described in Section 29.2.

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.14 对Verilog-2001系统任务的增强

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.14 对Verilog-2001系统任务的增强
第二十三章 系统任务与系统函数

SystemVerilog adds system tasks and system functions as described in the following sections. In addition, SystemVerilog extends the behavior of the following:

  • %u and %z format specifiers:
    • For packed data, %u and %z are defined to operate as though the operation were applied to the equivalent vector.
    • For unpacked struct data, %u and %z are defined to apply as though the operation were performed on each member in declaration order.
    • For unpacked union data, %u and %z are defined to apply as though the operation were performed on the first member in declaration order.
    • %u and %z are not defined on unpacked arrays.
    • The count of data items read by a %u or %z for an aggregate type is always either 1 or 0; the individual members are not counted separately.
  • $fread
$fread has two variants—a register variant and a set of three memory variants.

The register variant,

Copy Code
$fread(myreg, fd);

  • is defined to be the one applied for all packed data.
  • For unpacked struct data, $fread is defined to apply as though the operation were performed on each member in declaration order.
  • For unpacked union data, $fread is defined to apply as though the operation were performed on the first member in declaration order.
  • For unpacked arrays, the original definition applies except that unpacked struct or union elements are read as described above.

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.15 $readmemb与$readmemh

链接
第二十三章 系统任务与系统函数, 主题
SystemVerilog 3.1a语言参考手册
23.15 $readmemb与$readmemh
第二十三章 系统任务与系统函数 | 主题
Group

第二十三章 系统任务与系统函数

主题
主题 | 描述
23.15.1 读取压缩的数据 | $readmemb and $readmemh are extended to unpacked arrays of packed data, associative arrays of packed data, and dynamic arrays of packed data. In such cases, the system tasks treat each packed element as the vector equivalent and perform the normal operation. When working with associative arrays, indexes must be of integral types.
23.15.2 读取两态类型 | $readmemb and $readmemh are extended to packed data of 2-state type, such as int or enumerated types. For 2-state integer types, reading proceeds the same as for conventional Verilog reg types (e.g. integer), with the exception that X or Z data is converted to 0. For enumerated types, the file data represents the ordinal value of the enumerated type. (See Section 3.10) If an enumeration ordinal is out of range for a given type, then an error shall be issued and no further reading shall take place.
链接
第二十三章 系统任务与系统函数, 主题


23.15.1 读取压缩的数据

链接
23.15 $readmemb与$readmemh
SystemVerilog 3.1a语言参考手册
23.15.1 读取压缩的数据
23.15 $readmemb与$readmemh

$readmemb and $readmemh are extended to unpacked arrays of packed data, associative arrays of packed data, and dynamic arrays of packed data. In such cases, the system tasks treat each packed element as the vector equivalent and perform the normal operation.

When working with associative arrays, indexes must be of integral types.

Group

23.15 $readmemb与$readmemh

链接
23.15 $readmemb与$readmemh


23.15.2 读取两态类型

链接
23.15 $readmemb与$readmemh
SystemVerilog 3.1a语言参考手册
23.15.2 读取两态类型
23.15 $readmemb与$readmemh

$readmemb and $readmemh are extended to packed data of 2-state type, such as int or enumerated types. For 2-state integer types, reading proceeds the same as for conventional Verilog reg types (e.g. integer), with the exception that X or Z data is converted to 0. For enumerated types, the file data represents the ordinal value of the enumerated type. (See Section 3.10) If an enumeration ordinal is out of range for a given type, then an error shall be issued and no further reading shall take place.

Group

23.15 $readmemb与$readmemh

链接
23.15 $readmemb与$readmemh


23.16 $writememb and $writememh

链接
第二十三章 系统任务与系统函数, 主题
SystemVerilog 3.1a语言参考手册
23.16 $writememb and $writememh
第二十三章 系统任务与系统函数 | 主题

SystemVerilog introduces system tasks $writememb and $writememh:

Copy Code
writemem_tasks ::=    // not in Annex A
    $writememb("file_name", memory_name[, start_addr[, finish_addr]]);
  | $writememh("file_name", memory_name[, start_addr[, finish_addr]]);

Syntax 23-9—writemem system task syntax (not in Annex A)

$writememb and $writememh are used to dump memory contents to files that are readable by $readmemb and $readmemh, respectively. If “file_name” exists at the time $writememb or $writememh is called, the file will be overwritten (.i.e. there is no append mode).

Group

第二十三章 系统任务与系统函数

主题
主题 | 描述
23.16.1 Writing packed data | writememb and $writememh treat packed data identically to readmemb and $readmemh. See Section 23.15.1
23.16.2 Writing 2-state types | $writememb and $writememh can write out data corresponding to unpacked arrays of 2-state types, such as int or enumerated types. For enumerated types, values in the file correspond to the ordinal values of the enumerated type. (See Section 3.10).
23.16.3 Writing addresses to output file | When $writememb and $writememh write out data corresponding to unpacked or dynamic arrays, address specifiers (@-words) shall not be written to the output file. When $writememb and $writememh write out data corresponding to associative arrays, address specifiers shall be written to the output file.
链接
第二十三章 系统任务与系统函数, 主题


23.16.1 Writing packed data

链接
23.16 $writememb and $writememh
SystemVerilog 3.1a语言参考手册
23.16.1 Writing packed data
23.16 $writememb and $writememh

writememb and $writememh treat packed data identically to readmemb and $readmemh. See Section 23.15.1

Group

23.16 $writememb and $writememh

链接
23.16 $writememb and $writememh


23.16.2 Writing 2-state types

链接
23.16 $writememb and $writememh
SystemVerilog 3.1a语言参考手册
23.16.2 Writing 2-state types
23.16 $writememb and $writememh

$writememb and $writememh can write out data corresponding to unpacked arrays of 2-state types, such as int or enumerated types. For enumerated types, values in the file correspond to the ordinal values of the enumerated type. (See Section 3.10).

Group

23.16 $writememb and $writememh

链接
23.16 $writememb and $writememh


23.16.3 Writing addresses to output file

链接
23.16 $writememb and $writememh
SystemVerilog 3.1a语言参考手册
23.16.3 Writing addresses to output file
23.16 $writememb and $writememh

When $writememb and $writememh write out data corresponding to unpacked or dynamic arrays, address specifiers (@-words) shall not be written to the output file.

When $writememb and $writememh write out data corresponding to associative arrays, address specifiers shall be written to the output file.

Group

23.16 $writememb and $writememh

链接
23.16 $writememb and $writememh


23.17 File format considerations for multi-dimensional unpacked arrays

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.17 File format considerations for multi-dimensional unpacked arrays
第二十三章 系统任务与系统函数

In SystemVerilog, $readmemb, $readmemh, $writememb and $writememh can work with multi-dimensional unpacked arrays.

The file contents are organized in row-major order, with each dimension’s entries ranging from low to high address. This is backward compatible with plain Verilog memories.

In this organization, the lowest dimension (i.e. the right-most dimension in the array declaration) varies the most rapidly. There is a hierarchical sense to the file data. The higher dimensions contain words of lowerdimension data, sorted in row-major order. Each successive lower dimension is entirely enclosed as part of higher dimension words.

As an example of file format organization, here is the layout of a file representing words for a memory declared:

Copy Code
reg [31:0] mem [0:2][0:4][5:8];

In the example word contents, wzyx,

  • z corresponds to words of the [0:2] dimension
  • y corresponds to words of the [0:4] dimension
  • x corresponds to words of the [5:8] dimension

Copy Code
w005 w006 w007 w008
w015 w016 w017 w018
w025 w026 w027 w028
w035 w036 w037 w038
w045 w046 w047 w048
w105 w106 w107 w108
w115 w116 w117 w118
w125 w126 w127 w128
w135 w136 w137 w138
w145 w146 w147 w148
w205 w206 w207 w208
w215 w216 w217 w218
w225 w226 w227 w228
w235 w236 w237 w238
w245 w246 w247 w248

Note that the diagram would be identical if one or more of the unpacked dimension declarations were reversed, as in:

Copy Code
reg [31:0] mem [2:0][0:4][8:5]

Address entries in the file exclusively address the highest dimension’s words. In the above case, address entries in the file could look something as follows:

Copy Code
@0 w005 w006 w007 w008
   w015 w016 w017 w018
   w025 w026 w027 w028
   w035 w036 w037 w038
   w045 w046 w047 w048
@1 w105 w106 w107 w108
   w115 w116 w117 w118
   w125 w126 w127 w128
   w135 w136 w137 w138
   w145 w146 w147 w148
@2 w205 w206 w207 w208
   w215 w216 w217 w218
   w225 w226 w227 w228
   w235 w236 w237 w238
   w245 w246 w247 w248

When $readmemh or $readmemb is given a file without address entries, all data is read assuming that each dimension has complete data. i.e. each word in each dimension will be initialized with the appropriate value from the file. If the file contains incomplete data, the read operation will stop at the last initialized word, and any remaining array words or sub words will be left unchanged.

When $readmemh or $readmemb is given a file with address entries, initialization of the specified highest dimension words is done. If the file contains insufficient words to completely fill a highest dimension word, then the remaining sub words are left unchanged.

When a memory contains multiple packed dimensions, the memory words in the pattern file are composed of the sum total of all bits in the packed dimensions. The layout of packed bits in packed dimensions is defined in Section 4.3.

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


23.18 System task arguments for multi-dimensional unpacked arrays

链接
第二十三章 系统任务与系统函数
SystemVerilog 3.1a语言参考手册
23.18 System task arguments for multi-dimensional unpacked arrays
第二十三章 系统任务与系统函数

The $readmemb, $readmemh, $writememb, and $writememh signatures are shown below:

Copy Code
$readmemb("file_name", memory_name[, start_addr[, finish_addr]]);
$readmemh("file_name", memory_name[, start_addr[, finish_addr]]);
$writememb("file_name", memory_name[, start_addr[, finish_addr]]);
$writememh("file_name", memory_name[, start_addr[, finish_addr]]);

memory_name can be an unpacked array, or a partially indexed multi-dimensional unpacked array that resolves to a lesser-dimensioned unpacked array.

Higher order dimensions must be specified with an index, rather than a complete or partial dimension range. The lowest dimension (i.e. the right-most specified dimension in the identifier) can be specified with slice syntax. See Section 4.4 for details on legal array indexing in SystemVerilog.

The start_addr and finish_addr arguments apply to the addresses of the unpacked array selected by memory_name. This address range represents the highest dimension of data in the file_name.

When slice syntax is used in the memory_name argument, any start_addr and finish_addr arguments must fall within the bounds of the slice’s range.

The direction of the highest dimension’s file entries is given by the relative magnitudes of start_addr and finish_addr, as is the case in 1364-2001.

Group

第二十三章 系统任务与系统函数

链接
第二十三章 系统任务与系统函数


第二十四章 VCD数据

第二十四章 VCD数据

SystemVerilog并没有扩展VCD格式。某些SystemVerilog数据类型能够通过伪装成一个Verilog数据类型被转储到一个标准的VCD文件。下面的表格列出了基本的SystemVerilog数据类型以及在VCD转储中与Verilog数据类型的映射。

表格24-1：VCD类型映射

SystemVerilog | Verilog | Size
bit | reg | Size of packed dimension
logic | reg | Size of packed dimension
int | integer | 32
shortint | integer | 16
longint | integer | 64
shortreal | real |
byte | reg | 8
enum | integer | 32

Packed arrays and structures are dumped as a single vector of reg. Multiple packed array dimensions are collapsed into a single dimension.

If an enum declaration specified a type, it is dumped as that type rather than the default shown above.

Unpacked structures appear as named fork...join blocks, and their member elements of the structure appear as the types above. Since named fork...join blocks with variable declarations are seldom used in testbenches and hardware models, this makes structures easy to distinguish from variables declared in begin...end blocks, which are more frequently used in testbenches and models.

As in Verilog 2001, unpacked arrays and automatic variables are not dumped.

Note that the current VCD format does not indicate whether a variable has been declared as signed or unsigned.


第二十五章 编译器指令

链接
主题
SystemVerilog 3.1a语言参考手册
第二十五章 编译器指令
主题
主题
主题 | 描述
25.1 简介（一般信息） | Verilog provides the ‘define text substitution macro compiler directive. A macro can contain arguments, whose values can be set for each instance of the macro. For example:
25.2 `define宏 | In Verilog, the `define macro text can include a backslash ( \ ) at the end of a line to show continuation on the next line. In SystemVerilog, the macro text can also include `", `\`" and ``. An `" overrides the usual lexical meaning of ", and indicates that the expansion should include an actual quotation mark. This allows string literals to be constructed from macro arguments. A `\`" indicates that the expansion should include the escape sequence \", e.g.
25.3 `include | The syntax of the ‘include compiler directive is:
链接
主题


25.1 简介（一般信息）

链接
第二十五章 编译器指令
SystemVerilog 3.1a语言参考手册
25.1 简介（一般信息）
第二十五章 编译器指令

Verilog provides the ‘define text substitution macro compiler directive. A macro can contain arguments, whose values can be set for each instance of the macro. For example:

Copy Code
‘define NAND(dval) nand #(dval)
‘NAND(3) i1 (y, a, b); //‘NAND(3) macro substitutes with: nand #(3)
‘NAND(3:4:5) i2 (o, c, d); //‘NAND(3:4:5) macro substitutes with: nand
#(3:4:5)

SystemVerilog enhances the capabilities of the ‘define compiler directive to support the construction of string literals and identifiers.

Verilog provides the `include file inclusion compiler directive. SystemVerilog enhances the capabilities to support standard include specification, and enhances the `include directive to accept a file name constructed with a macro.

Group

第二十五章 编译器指令

链接
第二十五章 编译器指令


25.2 `define宏

链接
第二十五章 编译器指令
SystemVerilog 3.1a语言参考手册
25.2 `define宏
第二十五章 编译器指令

In Verilog, the `define macro text can include a backslash ( \ ) at the end of a line to show continuation on the next line.

In SystemVerilog, the macro text can also include `", `\`" and ``.

An `" overrides the usual lexical meaning of ", and indicates that the expansion should include an actual quotation mark. This allows string literals to be constructed from macro arguments.

A `\`" indicates that the expansion should include the escape sequence \", e.g.

Copy Code
`define msg(x,y) `"x: `\`"y`\`"`"

This expands:

Copy Code
$display(`msg(left side,right side));

to:

Copy Code
$display("left side: \"right side\"");

A `` delimits lexical tokens without introducing white space, allowing identifiers to be constructed from arguments, e.g.

Copy Code
`define foo(f) f``_suffix

This expands:

Copy Code
‘foo(bar)

to:

Copy Code
bar_suffix

The ‘include directive can be followed by a macro, instead of a literal string:

Copy Code
‘define home(filename) ‘"/home/foo/filename‘"
‘include ‘home(myfile)
Group

第二十五章 编译器指令

链接
第二十五章 编译器指令


25.3 `include

链接
第二十五章 编译器指令
SystemVerilog 3.1a语言参考手册
25.3 `include
第二十五章 编译器指令

The syntax of the ‘include compiler directive is:

Copy Code
include_compiler_directive ::=
    `include "filename"
  | `include <filename>

When the filename is an absolute path, only that filename is included and only the double quote form of the ‘include can be used.

When the double quote ("filename") version is used, the behavior of ‘include is unchanged from IEEE Std. 1364-2001.

When the angle bracket (<filename>) notation is used, then only the vendor defined location containing files defined by the language standard is searched. Relative path names given inside the < > are interpreted relative to the vendor-defined location in all cases.

Group

第二十五章 编译器指令

链接
第二十五章 编译器指令


第二十六章 考虑从SystemVerilog中删除的功能

链接
主题
SystemVerilog 3.1a语言参考手册
第二十六章 考虑从SystemVerilog中删除的功能
主题
主题
主题 | 描述
26.1 简介（一般信息） | Certain Verilog language features can be simulation inefficient, easily abused, and the source of design problems. These features are being considered for removal from the SystemVerilog language, if there is an alternate method for these features. The Verilog language features that have been identified in this standard as ones which can be removed from Verilog are defparam and procedural assign/deassign.
26.2 defparam语句 | The SystemVerilog committee has determined, based on the solicitation of input from tool implementers and tools users, that the defparam method of specifying the value of a parameter can be a source of design errors, and can be an impediment to tool implementation. The defparam statement does not provide a capability that cannot be done by another method, which avoids these problems. Therefore, the committee has placed the defparam statement on a deprecation list. This means is that a future revision of the Verilog standard might not require support for this feature. This current standard still requires tools to support... more
26.3 过程赋值与解赋值语句 | The SystemVerilog committee has determined, based on the solicitation of input from tool implementers and tools users, that the procedural assign and deassign statements can be a source of design errors, and can be an impediment to tool implementation. The procedural assign/deassign statements do not provide a capability that cannot be done by another method, which avoids these problems. Therefore, the committee has placed the procedural assign/deassign statements on a deprecation list. This means that a future revision of the Verilog standard might not require support for theses statements. This current standard still requires tools to support the procedural assign/deassign... more
链接
主题


26.1 简介（一般信息）

链接
第二十六章 考虑从SystemVerilog中删除的功能
SystemVerilog 3.1a语言参考手册
26.1 简介（一般信息）
第二十六章 考虑从SystemVerilog中删除的功能

Certain Verilog language features can be simulation inefficient, easily abused, and the source of design problems. These features are being considered for removal from the SystemVerilog language, if there is an alternate method for these features.

The Verilog language features that have been identified in this standard as ones which can be removed from Verilog are defparam and procedural assign/deassign.

Group

第二十六章 考虑从SystemVerilog中删除的功能

链接
第二十六章 考虑从SystemVerilog中删除的功能


26.2 defparam语句

链接
第二十六章 考虑从SystemVerilog中删除的功能
SystemVerilog 3.1a语言参考手册
26.2 defparam语句
第二十六章 考虑从SystemVerilog中删除的功能

The SystemVerilog committee has determined, based on the solicitation of input from tool implementers and tools users, that the defparam method of specifying the value of a parameter can be a source of design errors, and can be an impediment to tool implementation. The defparam statement does not provide a capability that cannot be done by another method, which avoids these problems. Therefore, the committee has placed the defparam statement on a deprecation list. This means is that a future revision of the Verilog standard might not require support for this feature. This current standard still requires tools to support the defparam statement. However, users are strongly encouraged to migrate their code to use one of the alternate methods of parameter redefinition.

Prior to the acceptance of the Verilog-2001 Standard, it was common practice to change one or more parameters of instantiated modules using a separate defparam statement. Defparam statements can be a source of tool complexity and design problems.

A defparam statement can precede the instance to be modified, can follow the instance to be modified, can be at the end of the file that contains the instance to be modified, can be in a separate file from the instance to be modified, can modify parameters hierarchically that in turn must again be passed to other defparam statements to modify, and can modify the same parameter from two different defparam statements (with undefined results). Due to the many ways that a defparam can modify parameters, a Verilog compiler cannot insure the final parameter values for an instance until after all of the design files are compiled.

Prior to Verilog-2001, the only other method available to change the values of parameters on instantiated modules was to use implicit in-line parameter redefinition. This method uses #(parameter_value) as part of the module instantiation. Implicit in-line parameter redefinition syntax requires that all parameters up to and including the parameter to be changed must be placed in the correct order, and must be assigned values.

Verilog-2001 introduced explicit in-line parameter redefinition, in the form #(.parameter_name(value)), as part of the module instantiation. This method gives the capability to pass parameters by name in the instantiation, which supplies all of the necessary parameter information to the model in the instantiation itself.

The practice of using defparam statements is highly discouraged. Engineers are encouraged to take advantage of the Verilog-2001 explicit in-line parameter redefinition capability.

See Section 21 for more details on parameters.

Group

第二十六章 考虑从SystemVerilog中删除的功能

链接
第二十六章 考虑从SystemVerilog中删除的功能


26.3 过程赋值与解赋值语句

链接
第二十六章 考虑从SystemVerilog中删除的功能
SystemVerilog 3.1a语言参考手册
26.3 过程赋值与解赋值语句
第二十六章 考虑从SystemVerilog中删除的功能

The SystemVerilog committee has determined, based on the solicitation of input from tool implementers and tools users, that the procedural assign and deassign statements can be a source of design errors, and can be an impediment to tool implementation. The procedural assign/deassign statements do not provide a capability that cannot be done by another method, which avoids these problems. Therefore, the committee has placed the procedural assign/deassign statements on a deprecation list. This means that a future revision of the Verilog standard might not require support for theses statements. This current standard still requires tools to support the procedural assign/deassign statements. However, users are strongly encouraged to migrate their code to use one of the alternate methods of procedural or continuous assignments.

Verilog has two forms of the assign statement:

  • Continuous assignments, placed outside of any procedures
  • Procedural continuous assignments, placed within a procedure
Continuous assignment statements are a separate process that are active throughout simulation. The continuous assignment statement accurately represents combinational logic at an RTL level of modeling, and is frequently used.

Procedural continuous assignment statements become active when the assign statement is executed in the procedure. The process can be de-activated using a deassign statement. The procedural assign/deassign statements are seldom needed to model hardware behavior. In the unusual circumstances where the behavior of procedural continuous assignments are required, the same behavior can be modeled using the procedural force and release statements.

The fact that the assign statement to be used both outside and inside a procedure can cause confusion and errors in Verilog models. The practice of using the assign and deassign statements inside of procedural blocks is highly discouraged.

Group

第二十六章 考虑从SystemVerilog中删除的功能

链接
第二十六章 考虑从SystemVerilog中删除的功能


第二十七章 直接编程接口（DPI）

链接
主题
SystemVerilog 3.1a语言参考手册
第二十七章 直接编程接口（DPI）
主题

This chapter highlights the Direct Programming Interface and provides a detailed description of the SystemVerilog layer of the interface. The C layer is defined in Annex E.

主题
主题 | 描述
27.1 概述 | Direct Programming Interface (DPI) is an interface between SystemVerilog and a foreign programming language. It consists of two separate layers: the SystemVerilog layer and a foreign language layer. Both sides of DPI are fully isolated. Which programming language is actually used as the foreign language is transparent and irrelevant for the SystemVerilog side of this interface. Neither the SystemVerilog compiler nor the foreign language compiler is required to analyze the source code in the other’s language. Different programming languages can be used and supported with the same intact SystemVerilog layer. For now, however, SystemVerilog 3.1 defines a foreign language layer... more
27.2 Two layers of the DPI | DPI consists of two separate layers: the SystemVerilog layer and a foreign language layer. The SystemVerilog layer does not depend on which programming language is actually used as the foreign language. Although different programming languages can be supported and used with the intact SystemVerilog layer, SystemVerilog 3.1 defines a foreign language layer only for the C programming language. Nevertheless, SystemVerilog code shall look identical and its semantics shall be unchanged for any foreign language layer. Different foreign languages can require that the SystemVerilog implementation shall use the appropriate function call protocol, argument passing and linking mechanisms. This shall be, however,... more
27.3 Global name space of imported and exported functions | Every task or function imported to SystemVerilog must eventually resolve to a global symbol. Similarly, every task or function exported from SystemVerilog defines a global symbol. Thus the tasks and functions imported to and exported from SystemVerilog have their own global name space of linkage names, different from compilation- unit scope name space. Global names of imported and exported tasks and functions must be unique (no overloading is allowed ) and shall follow C conventions for naming; specifically, such names must start with a letter or underscore, and can be followed by alphanumeric characters or underscores. Exported and imported tasks... more
27.4 导入的任务和函数 | 导入函数的使用与SystemVerilog原生函数类似。
27.5 Calling imported functions | The usage of imported functions is identical as for native SystemVerilog functions., hence the usage and syntax for calling imported functions is identical as for native SystemVerilog functions. Specifically, arguments with default values can be omitted from the call; arguments can be passed by name, if all formal arguments are named.
27.6 Exported functions | DPI allows calling SystemVerilog functions from another language. However, such functions must adhere to the same restrictions on argument types and results as are imposed on imported functions. It is an error to export a function that does not satisfy such constraints. SystemVerilog functions that can be called from foreign code need to be specified in export declarations. Export declarations are allowed to occur only in the scope in which the function being exported is defined. Only one export declaration per function is allowed in a given scope. Note that class member functions cannot be exported, but all other SystemVerilog... more
27.7 Exported tasks | SystemVerilog allows tasks to be called from a foreign language, similar to functions. Such tasks are termed “exported tasks”. All aspects of exported functions described above in Section 27.6 apply to exported tasks. This includes legal declaration scopes as well as usage of the optional c_identifier. It is never legal to call an exported task from within an imported function. These semantics are identical to native SystemVerilog semantics, in which it is illegal for a function to perform a task enable. It is legal for an imported task to call an exported task only if the imported task is declared... more
27.8 Disabling DPI tasks and functions | It is possible for a disable statement to disable a block that is currently executing a mixed language call chain. When a DPI import task or function is disabled, the C code is required to follow a simple disable protocol. The protocol gives the C code the opportunity to perform any necessary resource cleanup, such as closing open file handles, closing open VPI handles, or freeing heap memory. An imported task or function is said to be in the disabled state when a disable statement somewhere in the design targets either it or a parent for disabling. Note that the... more
链接
主题


27.1 概述

链接
第二十七章 直接编程接口（DPI）, 主题
SystemVerilog 3.1a语言参考手册
27.1 概述
第二十七章 直接编程接口（DPI） | 主题

Direct Programming Interface (DPI) is an interface between SystemVerilog and a foreign programming language. It consists of two separate layers: the SystemVerilog layer and a foreign language layer. Both sides of DPI are fully isolated. Which programming language is actually used as the foreign language is transparent and irrelevant for the SystemVerilog side of this interface. Neither the SystemVerilog compiler nor the foreign language compiler is required to analyze the source code in the other’s language. Different programming languages can be used and supported with the same intact SystemVerilog layer. For now, however, SystemVerilog 3.1 defines a foreign language layer only for the C programming language. See Annex E for more details.

The motivation for this interface is two-fold. The methodological requirement is that the interface should allow a heterogeneous system to be built (a design or a testbench) in which some components can be written in a language (or more languages) other than SystemVerilog, hereinafter called the foreign language. On the other hand, there is also a practical need for an easy and efficient way to connect existing code, usually written in C or C++, without the knowledge and the overhead of PLI or VPI.

DPI follows the principle of a black box: the specification and the implementation of a component is clearly separated and the actual implementation is transparent to the rest of the system. Therefore, the actual programming language of the implementation is also transparent, though this standard defines only C linkage semantics. The separation between SystemVerilog code and the foreign language is based on using functions as the natural encapsulation unit in SystemVerilog. By and large, any function can be treated as a black box and implemented either in SystemVerilog or in the foreign language in a transparent way, without changing its calls.

Group

第二十七章 直接编程接口（DPI）

主题
主题 | 描述
27.1.1 Tasks and functions | DPI allows direct inter-language function calls between the languages on either side of the interface. Specifically, functions implemented in a foreign language can be called from SystemVerilog; such functions are referred to as imported functions. SystemVerilog functions that are to be called from a foreign code shall be specified in export declarations (see Section 27.6 for more details). DPI allows for passing SystemVerilog data between the two domains through function arguments and results. There is no intrinsic overhead in this interface. It is also possible to perform task enables across the language boundary. Foreign code can call SystemVerilog tasks, and... more
27.1.2 Data types | SystemVerilog data types are the sole data types that can cross the boundary between SystemVerilog and a foreign language in either direction (i.e., when an imported function is called from SystemVerilog code or an exported SystemVerilog function is called from a foreign code). It is not possible to import the data types or directly use the type syntax from another language. A rich subset of SystemVerilog data types is allowed for formal arguments of import and export functions, although with some restrictions and with some notational extensions. Function result types are restricted to small values, however (see Section 27.4.5). Formal... more
链接
第二十七章 直接编程接口（DPI）, 主题


27.1.1 Tasks and functions

链接
27.1 概述
SystemVerilog 3.1a语言参考手册
27.1.1 Tasks and functions
27.1 概述

DPI allows direct inter-language function calls between the languages on either side of the interface. Specifically, functions implemented in a foreign language can be called from SystemVerilog; such functions are referred to as imported functions. SystemVerilog functions that are to be called from a foreign code shall be specified in export declarations (see Section 27.6 for more details). DPI allows for passing SystemVerilog data between the two domains through function arguments and results. There is no intrinsic overhead in this interface.

It is also possible to perform task enables across the language boundary. Foreign code can call SystemVerilog tasks, and native Verilog code can call imported tasks. An imported task has the same semantics as a native Verilog task: It never returns a value, and it can block and consume simulation time.

All functions used in DPI are assumed to complete their execution instantly and consume 0 (zero) simulation time, just as normal SystemVerilog functions. DPI provides no means of synchronization other than by data exchange and explicit transfer of control.

Every imported task and function needs to be declared. A declaration of an imported task or function is referred to as an import declaration. Import declarations are very similar to SystemVerilog task and function declarations. Import declarations can occur anywhere where SystemVerilog task and function definitions are permitted. An import declaration is considered to be a definition of a SystemVerilog task or function with a foreign language implementation. The same foreign task or function can be used to implement multiple SystemVerilog tasks and functions (this can be a useful way of providing differing default argument values for the same basic task or function), but a given SystemVerilog name can only be defined once per scope. Imported task and functions can have zero or more formal input, output, and inout arguments. Imported tasks always return a void value, and thus can only be used in statement context. Imported functions can return a result or be defined as void functions.

DPI is based entirely upon SystemVerilog constructs. The usage of imported functions is identical as for native

SystemVerilog functions. With few exceptions imported functions and native functions are mutually

exchangeable. Calls of imported functions are indistinguishable from calls of SystemVerilog functions. This

facilitates ease-of-use and minimizes the learning curve. Similar interchangeable semantics exist between

native SystemVerilog tasks and imported tasks.

Group

27.1 概述

链接
27.1 概述


27.1.2 Data types

链接
27.1 概述, 主题
SystemVerilog 3.1a语言参考手册
27.1.2 Data types
27.1 概述 | 主题

SystemVerilog data types are the sole data types that can cross the boundary between SystemVerilog and a foreign language in either direction (i.e., when an imported function is called from SystemVerilog code or an exported SystemVerilog function is called from a foreign code). It is not possible to import the data types or directly use the type syntax from another language. A rich subset of SystemVerilog data types is allowed for formal arguments of import and export functions, although with some restrictions and with some notational extensions. Function result types are restricted to small values, however (see Section 27.4.5).

Formal arguments of an imported function can be specified as open arrays. A formal argument is an open array when a range of one or more of its dimensions, packed or unpacked, is unspecified. An open array is like a multi-dimensional dynamic array formal in both packed and unpacked dimensions, and is thus denoted using the same syntax as dynamic arrays, using [] to denote an open dimension. This is solely a relaxation of the argument-matching rules. An actual argument shall match the formal one regardless of the range(s) for its corresponding dimension(s), which facilitates writing generalized code that can handle SystemVerilog arrays of different sizes. See Section 27.4.6.1.

Group

27.1 概述

主题
主题 | 描述
27.1.2.1 Data representation | DPI does not add any constraints on how SystemVerilog-specific data types are actually implemented. Optimal representation can be platform dependent. The layout of 2- or 4-state packed structures and arrays is implementation- and platform-dependent. The implementation (representation and layout) of 4-state values, structures, and arrays is irrelevant for SystemVerilog semantics, and can only impact the foreign side of the interface.
链接
27.1 概述, 主题


27.1.2.1 Data representation

链接
27.1.2 Data types
SystemVerilog 3.1a语言参考手册
27.1.2.1 Data representation
27.1.2 Data types

DPI does not add any constraints on how SystemVerilog-specific data types are actually implemented. Optimal representation can be platform dependent. The layout of 2- or 4-state packed structures and arrays is implementation- and platform-dependent.

The implementation (representation and layout) of 4-state values, structures, and arrays is irrelevant for SystemVerilog semantics, and can only impact the foreign side of the interface.

Group

27.1.2 Data types

链接
27.1.2 Data types


27.2 Two layers of the DPI

链接
第二十七章 直接编程接口（DPI）, 主题
SystemVerilog 3.1a语言参考手册
27.2 Two layers of the DPI
第二十七章 直接编程接口（DPI） | 主题

DPI consists of two separate layers: the SystemVerilog layer and a foreign language layer. The SystemVerilog layer does not depend on which programming language is actually used as the foreign language. Although different programming languages can be supported and used with the intact SystemVerilog layer, SystemVerilog 3.1 defines a foreign language layer only for the C programming language. Nevertheless, SystemVerilog code shall look identical and its semantics shall be unchanged for any foreign language layer. Different foreign languages can require that the SystemVerilog implementation shall use the appropriate function call protocol, argument passing and linking mechanisms. This shall be, however, transparent to SystemVerilog users. SystemVerilog 3.1 requires only that its implementation shall support C protocols and linkage.

Group

第二十七章 直接编程接口（DPI）

主题
主题 | 描述
27.2.1 DPI SystemVerilog layer | The SystemVerilog side of DPI does not depend on the foreign programming language. In particular, the actual function call protocol and argument passing mechanisms used in the foreign language are transparent and irrelevant to SystemVerilog. SystemVerilog code shall look identical regardless of what code the foreign side of the interface is using. The semantics of the SystemVerilog side of the interface is independent from the foreign side of the interface. This chapter does not constitute a complete interface specification. It only describes the functionality, semantics and syntax of the SystemVerilog layer of the interface. The other half of the interface,... more
27.2.2 DPI foreign language layer | The foreign language layer of the interface (which is transparent to SystemVerilog) shall specify how actual arguments are passed, how they can be accessed from the foreign code, how SystemVerilog-specific data types (such as logic and packed) are represented, and how to translate them to and from some predefined C-like types. The data types allowed for formal arguments and results of imported functions or exported functions are generally SystemVerilog types (with some restrictions and with notational extensions for open arrays). The user is responsible for specifying in their foreign code the native types equivalent to the SystemVerilog types used in... more
链接
第二十七章 直接编程接口（DPI）, 主题


27.2.1 DPI SystemVerilog layer

链接
27.2 Two layers of the DPI
SystemVerilog 3.1a语言参考手册
27.2.1 DPI SystemVerilog layer
27.2 Two layers of the DPI

The SystemVerilog side of DPI does not depend on the foreign programming language. In particular, the actual function call protocol and argument passing mechanisms used in the foreign language are transparent and irrelevant to SystemVerilog. SystemVerilog code shall look identical regardless of what code the foreign side of the interface is using. The semantics of the SystemVerilog side of the interface is independent from the foreign side of the interface.

This chapter does not constitute a complete interface specification. It only describes the functionality, semantics and syntax of the SystemVerilog layer of the interface. The other half of the interface, the foreign language layer, defines the actual argument passing mechanism and the methods to access (read/write) formal arguments from the foreign code. See Annex E for more details.

Group

27.2 Two layers of the DPI

链接
27.2 Two layers of the DPI


27.2.2 DPI foreign language layer

链接
27.2 Two layers of the DPI
SystemVerilog 3.1a语言参考手册
27.2.2 DPI foreign language layer
27.2 Two layers of the DPI

The foreign language layer of the interface (which is transparent to SystemVerilog) shall specify how actual arguments are passed, how they can be accessed from the foreign code, how SystemVerilog-specific data types (such as logic and packed) are represented, and how to translate them to and from some predefined C-like types.

The data types allowed for formal arguments and results of imported functions or exported functions are generally SystemVerilog types (with some restrictions and with notational extensions for open arrays). The user is responsible for specifying in their foreign code the native types equivalent to the SystemVerilog types used in imported declarations or export declarations. Software tools, like a SystemVerilog compiler, can facilitate the mapping of SystemVerilog types onto foreign native types by generating the appropriate function headers.

The SystemVerilog compiler or simulator shall generate and/or use the function call protocol and argument passing mechanisms required for the intended foreign language layer. The same SystemVerilog code (compiled accordingly) shall be usable with different foreign language layers, regardless of the data access method assumed in a specific layer. Annex F defines DPI foreign language layer for the C programming language.

Group

27.2 Two layers of the DPI

链接
27.2 Two layers of the DPI


27.3 Global name space of imported and exported functions

链接
第二十七章 直接编程接口（DPI）
SystemVerilog 3.1a语言参考手册
27.3 Global name space of imported and exported functions
第二十七章 直接编程接口（DPI）

Every task or function imported to SystemVerilog must eventually resolve to a global symbol. Similarly, every task or function exported from SystemVerilog defines a global symbol. Thus the tasks and functions imported to and exported from SystemVerilog have their own global name space of linkage names, different from compilation- unit scope name space. Global names of imported and exported tasks and functions must be unique (no overloading is allowed ) and shall follow C conventions for naming; specifically, such names must start with a letter or underscore, and can be followed by alphanumeric characters or underscores. Exported and imported tasks and functions, however, can be declared with local SystemVerilog names. Import and export declarations allow users to specify a global name for a function in addition to its declared name. Should a global name clash with a SystemVerilog keyword or a reserved name, it shall take the form of an escaped identifier. The leading backslash ( \ ) character and the trailing white space shall be stripped off by the SystemVerilog tool to create the linkage identifier. Note that after this stripping, the linkage identifier so formed must comply with the normal rules for C identifier construction. If a global name is not explicitly given, it shall be the same as the SystemVerilog task or function name. For example:

Copy Code
export "DPI" foo_plus = function \foo+ ; // "foo+" exported as "foo_plus"
export "DPI" function foo; // "foo" exported under its own name
import "DPI" init_1 = function void \init[1] (); // "init_1" is a linkage name
import "DPI" \begin = function void \init[2] (); // "begin" is a linkage name

The same global task or function can be referred to in multiple import declarations in different scopes or/and with different SystemVerilog names, see Section 27.4.4.

Multiple export declarations are allowed with the same c_identifier, explicit or implicit, as long as they are in different scopes and have the same type signature (as defined in Section 27.4.4 for imported tasks and functions). Multiple export declarations with the same c_identifier in the same scope are forbidden.

Group

第二十七章 直接编程接口（DPI）

链接
第二十七章 直接编程接口（DPI）


27.4 导入的任务和函数

链接
第二十七章 直接编程接口（DPI）, 主题
SystemVerilog 3.1a语言参考手册
27.4 导入的任务和函数
第二十七章 直接编程接口（DPI） | 主题

导入函数的使用与SystemVerilog原生函数类似。

Group

第二十七章 直接编程接口（DPI）

主题
主题
描述
27.4.1 Required properties of imported tasks and functions — semantic constraints
This section defines the semantic constraints imposed on imported tasks or functions. Some semantic restrictions are shared by all imported tasks or functions. Other restrictions depend on whether the special properties pure (see Section 27.4.2) or context (see Section 27.4.3) are specified for an imported task or function. A SystemVerilog compiler is not able to verify that those restrictions are observed and if those restrictions are not satisfied, the effects of such imported task or function calls can be unpredictable.
27.4.2 Pure functions
A pure function call can be safely eliminated if its result is not needed or if the previous result for the same values of input arguments is available somehow and can be reused without needing to recalculate. Only nonvoid functions with no output or inout arguments can be specified as pure. Functions specified as pure shall have no side effects whatsoever; their results need to depend solely on the values of their input arguments. Calls to such functions can be removed by SystemVerilog compiler optimizations or replaced with the values previously computed for the same values of the input arguments.... more
27.4.3 Context tasks and functions
Some DPI imported tasks or functions require that the context of their call is known. It takes special instrumentation of their call instances to provide such context; for example, an internal variable referring to the “current instance” might need to be set. To avoid any unnecessary overhead, imported task or function calls in SystemVerilog code are not instrumented unless the imported task or function is specified as context.

All DPI exported tasks or functions require that the context of their call is known. This occurs since SystemVerilog task or function declarations always occur in instantiable scopes, hence allowing a multiplicity... more
27.4.4 Import declarations
Each imported task or function shall be declared. Such declaration are referred to as import declarations. The syntax of an import declaration is similar to the syntax of SystemVerilog task or function prototypes (see Section 10.5).

Imported tasks or functions are similar to SystemVerilog tasks or functions. Imported tasks or functions can have zero or more formal input, output, and inout arguments. Imported functions can return a result or be defined as void functions. Imported tasks never return a result, and thus are always declared in foreign code as void functions.
27.4.5 Function result
Function result types are restricted to small values. The following SystemVerilog data types are allowed for imported function results:
  • void, byte, shortint, int, longint, real, shortreal, chandle, and string
  • packed bit arrays up to 32 bits and all types that are eventually equivalent to packed bit arrays up to 32 bits
  • scalar values of type bit and logic
The same restrictions apply for the result types of exported functions.
27.4.6 形式参数的类型
A rich subset of SystemVerilog data types is allowed for formal arguments of import and export tasks or functions. Generally, C compatible types, packed types and user defined types built of types from these two categories can be used for formal arguments of DPI tasks or functions. The set of permitted types is defined inductively.

The following SystemVerilog types are the only permitted types for formal arguments of import and export tasks or functions:
  • void, byte, shortint, int, longint, real, shortreal, chandle, and string
  • scalar values of type bit and logic
  • packed one dimensional arrays of type bit and logic... more
链接
第二十七章 直接编程接口（DPI）, 主题


27.4.1 Required properties of imported tasks and functions — semantic constraints

链接
27.4 导入的任务和函数, 主题
SystemVerilog 3.1a语言参考手册
27.4.1 Required properties of imported tasks and functions — semantic constraints
27.4 导入的任务和函数 | 主题

This section defines the semantic constraints imposed on imported tasks or functions. Some semantic restrictions are shared by all imported tasks or functions. Other restrictions depend on whether the special properties pure (see Section 27.4.2) or context (see Section 27.4.3) are specified for an imported task or function. A SystemVerilog compiler is not able to verify that those restrictions are observed and if those restrictions are not satisfied, the effects of such imported task or function calls can be unpredictable.

Group

27.4 导入的任务和函数

主题
主题 | 描述
27.4.1.1 Instant completion of imported functions | Imported functions shall complete their execution instantly and consume zero-simulation time, similarly to native functions. Note that imported tasks can consume time, similar to native SystemVerilog tasks.
27.4.1.2 input, output and inout arguments | Imported functions can have input, output and inout arguments. The formal input arguments shall not be modified. If such arguments are changed within a function, the changes shall not be visible outside the function; the actual arguments shall not be changed. The imported function shall not assume anything about the initial values of formal output arguments. The initial values of output arguments are undetermined and implementation-dependent. The imported function can access the initial value of a formal inout argument. Changes that the imported function makes to a formal inout argument shall be visible outside the function.
27.4.1.3 Special properties pure and context | Special properties can be specified for an imported task or function: as pure or as context (see also Section 27.4.2 or 27.4.3 ). A function whose result depends solely on the values of its input arguments and with no side effects can be specified as pure. This can usually allow for more optimizations and thus can result in improved simulation performance. Section 27.4.2 details the rules that must be obeyed by pure functions. An imported task can never be declared pure. An imported task or function that is intended to call exported tasks or functions or to access SystemVerilog data... more
27.4.1.4 Memory management | The memory spaces owned and allocated by the foreign code and SystemVerilog code are disjoined. Each side is responsible for its own allocated memory. Specifically, an imported function shall not free the memory allocated by SystemVerilog code (or the SystemVerilog compiler) nor expect SystemVerilog code to free the memory allocated by the foreign code (or the foreign compiler). This does not exclude scenarios where foreign code allocates a block of memory, then passes a handle (i.e., a pointer) to that block to SystemVerilog code, which in turn calls an imported function (e.g. C standard function free) which directly or indirectly... more
27.4.1.5 Reentrancy of imported tasks | Since imported tasks can block (consume time), it is possible for an imported task’s C code to be simultaneously active in multiple execution threads. Standard reentrancy considerations must be made by the C programmer. Some examples of such considerations include safe use of static variables, and ensuring that only thread-safe C standard library calls (MT safe) are used.
27.4.1.6 C++ exceptions | It is possible to implement DPI imported tasks and functions using C++, as long as C linkage conventions are observed at the language boundary. If C++ is used, exceptions must not propagate out of any imported task or function. Undefined behavior will result if an exception crosses the language boundary from C++ into SystemVerilog.
链接
27.4 导入的任务和函数, 主题


27.4.1.1 Instant completion of imported functions

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints
SystemVerilog 3.1a语言参考手册
27.4.1.1 Instant completion of imported functions
27.4.1 Required properties of imported tasks and functions — semantic constraints

Imported functions shall complete their execution instantly and consume zero-simulation time, similarly to native functions.

Note that imported tasks can consume time, similar to native SystemVerilog tasks.

Group

27.4.1 Required properties of imported tasks and functions — semantic constraints

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints


27.4.1.2 input, output and inout arguments

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints
SystemVerilog 3.1a语言参考手册
27.4.1.2 input, output and inout arguments
27.4.1 Required properties of imported tasks and functions — semantic constraints

Imported functions can have input, output and inout arguments. The formal input arguments shall not be modified. If such arguments are changed within a function, the changes shall not be visible outside the function; the actual arguments shall not be changed.

The imported function shall not assume anything about the initial values of formal output arguments. The initial values of output arguments are undetermined and implementation-dependent.

The imported function can access the initial value of a formal inout argument. Changes that the imported function makes to a formal inout argument shall be visible outside the function.

Group

27.4.1 Required properties of imported tasks and functions — semantic constraints

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints


27.4.1.3 Special properties pure and context

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints
SystemVerilog 3.1a语言参考手册
27.4.1.3 Special properties pure and context
27.4.1 Required properties of imported tasks and functions — semantic constraints

Special properties can be specified for an imported task or function: as pure or as context (see also Section 27.4.2 or 27.4.3 ).

A function whose result depends solely on the values of its input arguments and with no side effects can be specified as pure. This can usually allow for more optimizations and thus can result in improved simulation performance. Section 27.4.2 details the rules that must be obeyed by pure functions. An imported task can never be declared pure.

An imported task or function that is intended to call exported tasks or functions or to access SystemVerilog data objects other then its actual arguments (e.g. via VPI or PLI calls) must be specified as context. Calls of context tasks and functions are specially instrumented and can impair SystemVerilog compiler optimizations; therefore simulation performance can decrease if the context property is specified when not necessary. A task or function not specified as context shall not read or write any data objects from SystemVerilog other then its actual arguments. For tasks or functions not specified as context, the effects of calling PLI, VPI, or exported SystemVerilog tasks or functions can be unpredictable and can lead to unexpected behavior; such calls can even crash. Section 27.4.3 details the restrictions that must be obeyed by non-context tasks or functions.

If neither the pure nor the context attribute is used on an imported task or function, the task or function shall not access SystemVerilog data objects, however it can perform side-effects such as writing to a file or manipulating a global variable.

Group

27.4.1 Required properties of imported tasks and functions — semantic constraints

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints


27.4.1.4 Memory management

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints
SystemVerilog 3.1a语言参考手册
27.4.1.4 Memory management
27.4.1 Required properties of imported tasks and functions — semantic constraints

The memory spaces owned and allocated by the foreign code and SystemVerilog code are disjoined. Each side is responsible for its own allocated memory. Specifically, an imported function shall not free the memory allocated by SystemVerilog code (or the SystemVerilog compiler) nor expect SystemVerilog code to free the memory allocated by the foreign code (or the foreign compiler). This does not exclude scenarios where foreign code allocates a block of memory, then passes a handle (i.e., a pointer) to that block to SystemVerilog code, which in turn calls an imported function (e.g. C standard function free) which directly or indirectly frees that block.

NOTE—In this last scenario, a block of memory is allocated and freed in the foreign code, even when the standard functions malloc and free are called directly from SystemVerilog code.

Group

27.4.1 Required properties of imported tasks and functions — semantic constraints

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints


27.4.1.5 Reentrancy of imported tasks

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints
SystemVerilog 3.1a语言参考手册
27.4.1.5 Reentrancy of imported tasks
27.4.1 Required properties of imported tasks and functions — semantic constraints

Since imported tasks can block (consume time), it is possible for an imported task’s C code to be simultaneously active in multiple execution threads. Standard reentrancy considerations must be made by the C programmer. Some examples of such considerations include safe use of static variables, and ensuring that only thread-safe C standard library calls (MT safe) are used.

Group

27.4.1 Required properties of imported tasks and functions — semantic constraints

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints


27.4.1.6 C++ exceptions

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints
SystemVerilog 3.1a语言参考手册
27.4.1.6 C++ exceptions
27.4.1 Required properties of imported tasks and functions — semantic constraints

It is possible to implement DPI imported tasks and functions using C++, as long as C linkage conventions are observed at the language boundary. If C++ is used, exceptions must not propagate out of any imported task or function. Undefined behavior will result if an exception crosses the language boundary from C++ into SystemVerilog.

Group

27.4.1 Required properties of imported tasks and functions — semantic constraints

链接
27.4.1 Required properties of imported tasks and functions — semantic constraints


27.4.2 Pure functions

链接
27.4 导入的任务和函数
SystemVerilog 3.1a语言参考手册
27.4.2 Pure functions
27.4 导入的任务和函数

A pure function call can be safely eliminated if its result is not needed or if the previous result for the same values of input arguments is available somehow and can be reused without needing to recalculate. Only nonvoid functions with no output or inout arguments can be specified as pure. Functions specified as pure shall have no side effects whatsoever; their results need to depend solely on the values of their input arguments. Calls to such functions can be removed by SystemVerilog compiler optimizations or replaced with the values previously computed for the same values of the input arguments.

Specifically, a pure function is assumed not to directly or indirectly (i.e., by calling other functions):

  • perform any file operations
  • read or write anything in the broadest possible meaning, includes i/o, environment variables, objects from the operating system or from the program or other processes, shared memory, sockets, etc.
  • access any persistent data, like global or static variables.
If a pure function does not obey the above restrictions, SystemVerilog compiler optimizations can lead to unexpected behavior, due to eliminated calls or incorrect results being used.

Group

27.4 导入的任务和函数

链接
27.4 导入的任务和函数


27.4.3 Context tasks and functions

链接
27.4 导入的任务和函数
SystemVerilog 3.1a语言参考手册
27.4.3 Context tasks and functions
27.4 导入的任务和函数

Some DPI imported tasks or functions require that the context of their call is known. It takes special instrumentation of their call instances to provide such context; for example, an internal variable referring to the “current instance” might need to be set. To avoid any unnecessary overhead, imported task or function calls in SystemVerilog code are not instrumented unless the imported task or function is specified as context.

All DPI exported tasks or functions require that the context of their call is known. This occurs since SystemVerilog task or function declarations always occur in instantiable scopes, hence allowing a multiplicity of unique task or function instances.

For the sake of simulation performance, an imported task or function call shall not block SystemVerilog compiler optimizations. An imported task or function not specified as context shall not access any data objects from SystemVerilog other than its actual arguments. Only the actual arguments can be affected (read or written) by its call. Therefore, a call of a non-context task or function is not a barrier for optimizations. A context imported task or function, however, can access (read or write) any SystemVerilog data objects by calling PLI/VPI, or by calling an export task or function. Therefore, a call to a context task or function is a barrier for SystemVerilog compiler optimizations.

Only calls of context imported tasks or functions are properly instrumented and cause conservative optimizations; therefore, only those tasks or functions can safely call all tasks or functions from other APIs, including PLI and VPI functions or exported SystemVerilog tasks or functions. For imported tasks or functions not specified as context, the effects of calling PLI or VPI functions or SystemVerilog tasks or functions can be unpredictable and such calls can crash if the callee requires a context that has not been properly set. However note that declaring an import context task or function does not automatically make any other simulator interface automatically available. For VPI access (or any other interface access) to be possible, the appropriate implementation defined mechanism must still be used to enable these interface(s). Note also that DPI calls do not automatically create or provide any handles or any special environment that can be needed by those other interfaces. It is the user’s responsibility to create, manage or otherwise manipulate the required handles/ environment(s) needed by the other interfaces.

Context imported tasks or functions are always implicitly supplied a scope representing the fully qualified instance name within which the import declaration was present. This scope defines which exported SystemVerilog tasks or functions can be called directly from the imported task or function; only tasks or functions defined and exported from the same scope as the import can be called directly. To call any other exported SystemVerilog tasks or functions, the imported task or function shall first have to modify its current scope, in essence performing the foreign language equivalent of a SystemVerilog hierarchical task or function call.

Special DPI utility functions exist that allow imported task or functions to retrieve and operate on their scope. See Annex E for more details.

Group

27.4 导入的任务和函数

链接
27.4 导入的任务和函数


27.4.4 Import declarations

链接
27.4 导入的任务和函数
SystemVerilog 3.1a语言参考手册
27.4.4 Import declarations
27.4 导入的任务和函数

Each imported task or function shall be declared. Such declaration are referred to as import declarations. The syntax of an import declaration is similar to the syntax of SystemVerilog task or function prototypes (see Section 10.5).

Imported tasks or functions are similar to SystemVerilog tasks or functions. Imported tasks or functions can have zero or more formal input, output, and inout arguments. Imported functions can return a result or be defined as void functions. Imported tasks never return a result, and thus are always declared in foreign code as void functions.

Copy Code
dpi_import_export ::=    // from Annex A.2.6
    import "DPI" [dpi_function_import_property] [c_identifier =] dpi_function_proto;
  | import "DPI" [dpi_task_import_property] [c_identifier =] dpi_task_proto;
  | export "DPI" [c_identifier =] function function_identifier;
  | export "DPI" [c_identifier =] task task_identifier;

dpi_function_import_property ::= context | pure

dpi_task_import_property ::= context

dpi_function_proto8,9 ::= function_prototype

dpi_task_proto9 ::= task_prototype

function_prototype ::= function function_data_type function_identifier([tf_port_list])

task_prototype ::= task task_identifier([tf_port_list])   // from Annex A.2.7

NOTES:            // from Annex A.10
8) dpi_function_proto return types are restricted to small values, as per 27.4.5.
9) Formals of dpi_function_proto and dpi_task_proto cannot use pass by reference mode
   and class types cannot be passed at all; for the complete set of restrictions see
   27.4.6.

Syntax 27-1—DPI import declaration syntax (excerpt from Annex A)

An import declaration specifies the task or function name, function result type, and types and directions of formal arguments. It can also provide optional default values for formal arguments. Formal argument names are optional unless argument passing by name is needed. An import declaration can also specify an optional task or function property. Imported functions can have the properties context or pure; imported tasks can have the property context.

Note that an import declaration is equivalent to defining a task or function of that name in the SystemVerilog scope in which the import declaration occurs, and thus multiple imports of the same task or function name into the same scope are forbidden. Note that this declaration scope is particularly important in the case of imported context tasks or functions, see Section 27.4.3; for non-context imported tasks or functions the declaration scope has no other implications other than defining the visibility of the task or function.

c_identifier provides the linkage name for this task or function in the foreign language. If not provided, this defaults to the same identifier as the SystemVerilog task or function name. In either case, this linkage name must conform to C identifier syntax. An error shall occur if the c_identifier, either directly or indirectly, does not conform to these rules.

For any given c_identifier (whether explicitly defined with c_identifier=, or automatically determined from the task or function name), all declarations, regardless of scope, must have exactly the same type signature. The signature includes the return type and the number, order, direction and types of each and every argument. Type includes dimensions and bounds of any arrays or array dimensions. Signature also includes the pure/context qualifiers that can be associated with an extern definition.

Note that multiple declarations of the same imported or exported task or function in different scopes can vary argument names and default values, provided the type compatibility constraints are met.

A formal argument name is required to separate the packed and the unpacked dimensions of an array.

The qualifier ref cannot be used in import declarations. The actual implementation of argument passing depends solely on the foreign language layer and its implementation and shall be transparent to the SystemVerilog side of the interface.

The following are examples of external declarations.

Copy Code
import "DPI" function void myInit();
// from standard math library
import "DPI" pure function real sin(real);
// from standard C library: memory management
import "DPI" function chandle malloc(int size); // standard C function
import "DPI" function void free(chandle ptr); // standard C function
// abstract data structure: queue
import "DPI" function chandle newQueue(input string name_of_queue);
// Note the following import uses the same foreign function for
// implementation as the prior import, but has different SystemVerilog name
// and provides a default value for the argument.
import "DPI" newQueue=function chandle newAnonQueue(input string s=null);
import "DPI" function chandle newElem(bit [15:0]);
import "DPI" function void enqueue(chandle queue, chandle elem);
import "DPI" function chandle dequeue(chandle queue);
// miscellanea
import "DPI" function bit [15:0] getStimulus();
import "DPI” context function void processTransaction(chandle elem,
output logic [64:1] arr [0:63]);
import "DPI" task checkResults(input string s, bit [511:0] packet);
Group

27.4 导入的任务和函数

链接
27.4 导入的任务和函数


27.4.5 Function result

链接
27.4 导入的任务和函数
SystemVerilog 3.1a语言参考手册
27.4.5 Function result
27.4 导入的任务和函数

Function result types are restricted to small values. The following SystemVerilog data types are allowed for imported function results:

  • void, byte, shortint, int, longint, real, shortreal, chandle, and string
  • packed bit arrays up to 32 bits and all types that are eventually equivalent to packed bit arrays up to 32 bits
  • scalar values of type bit and logic
The same restrictions apply for the result types of exported functions.

Group

27.4 导入的任务和函数

链接
27.4 导入的任务和函数


27.4.6 形式参数的类型

链接
27.4 导入的任务和函数, 主题
SystemVerilog 3.1a语言参考手册
27.4.6 形式参数的类型
27.4 导入的任务和函数 | 主题

A rich subset of SystemVerilog data types is allowed for formal arguments of import and export tasks or functions. Generally, C compatible types, packed types and user defined types built of types from these two categories can be used for formal arguments of DPI tasks or functions. The set of permitted types is defined inductively.

The following SystemVerilog types are the only permitted types for formal arguments of import and export tasks or functions:

  • void, byte, shortint, int, longint, real, shortreal, chandle, and string
  • scalar values of type bit and logic
  • packed one dimensional arrays of type bit and logic
Note however, that every packed type, whatever is its structure, is eventually equivalent to a packed one dimensional array. Therefore practically all packed types are supported, although their internal structure (individual fields of structs, multiple dimensions of arrays) shall be transparent and irrelevant.
  • enumeration types interpreted as the type associated with that enumeration
  • types constructed from the supported types with the help of the constructs:
    • struct
    • unpacked array
    • typedef
The following caveats apply for the types permitted in DPI:
  • Enumerated data types are not supported directly. Instead, an enumerated data type is interpreted as the type associated with that enumerated type.
  • SystemVerilog does not specify the actual memory representation of packed structures or any arrays, packed or unpacked. Unpacked structures have an implementation-dependent packing, normally matching the C compiler.
  • The actual memory representation of SystemVerilog data types is transparent for SystemVerilog semantics and irrelevant for SystemVerilog code. It can be relevant for the foreign language code on the other side of the interface, however; a particular representation of the SystemVerilog data types can be assumed. This shall not restrict the types of formal arguments of imported tasks or functions, with the exception of unpacked arrays. SystemVerilog implementation can restrict which SystemVerilog unpacked arrays are passed as actual arguments for a formal argument which is a sized array, although they can be always passed for an unsized (i.e., open) array. Therefore, the correctness of an actual argument might be implementation-dependent. Nevertheless, an open array provides an implementation-independent solution.

Group

27.4 导入的任务和函数

主题
主题 | 描述
27.4.6.1 开放数组 | The size of the packed dimension, the unpacked dimension, or both dimensions can remain unspecified; such cases are referred to as open arrays (or unsized arrays). Open arrays allow the use of generic code to handle different sizes. Formal arguments of imported functions can be specified as open arrays. (Exported SystemVerilog functions cannot have formal arguments specified as open arrays.) A formal argument is an open array when a range of one or more of its dimensions is unspecified (denoted by using square brackets ([])). This is solely a relaxation of the argument-matching rules. An actual argument shall match the... more
链接
27.4 导入的任务和函数, 主题


27.4.6.1 开放数组

链接
27.4.6 形式参数的类型
SystemVerilog 3.1a语言参考手册
27.4.6.1 开放数组
27.4.6 形式参数的类型

The size of the packed dimension, the unpacked dimension, or both dimensions can remain unspecified; such cases are referred to as open arrays (or unsized arrays). Open arrays allow the use of generic code to handle different sizes.

Formal arguments of imported functions can be specified as open arrays. (Exported SystemVerilog functions cannot have formal arguments specified as open arrays.) A formal argument is an open array when a range of one or more of its dimensions is unspecified (denoted by using square brackets ([])). This is solely a relaxation of the argument-matching rules. An actual argument shall match the formal one regardless of the range(s) for its corresponding dimension(s), which facilitates writing generalized code that can handle SystemVerilog arrays of different sizes.

Although the packed part of an array can have an arbitrary number of dimensions, in the case of open arrays only a single dimension is allowed for the packed part. This is not very restrictive, however, since any packed type is eventually equivalent to one-dimensional packed array. The number of unpacked dimensions is not restricted.

If a formal argument is specified as an open array with a range of its packed or one or more of its unpacked dimensions unspecified, then the actual argument shall match the formal one—regardless of its dimensions and sizes of its linearized packed or unpacked dimensions corresponding to an unspecified range of the formal argument, respectively.

Here are examples of types of formal arguments (empty square brackets [] denote open array):

Copy Code
logic
bit [8:1]
bit[]
bit [7:0] array8x10 [1:10] // array8x10 is a formal arg name
logic [31:0] array32xN [] // array32xN is a formal arg name
logic [] arrayNx3 [3:1] // arrayNx3 is a formal arg name
bit [] arrayNxN [] // arrayNxN is a formal arg name

Example of complete import declarations:

Copy Code
import "DPI" function void foo(input logic [127:0]);
import "DPI" function void boo(logic [127:0] i []); // open array of 128-bit

The following example shows the use of open arrays for different sizes of actual arguments:

Copy Code
typedef struct {int i; ... } MyType;
import "DPI" function void foo(input MyType i [][]);
/* 2-dimensional unsized unpacked array of MyType */
MyType a_10x5 [11:20][6:2];
MyType a_64x8 [64:1][-1:-8];
foo(a_10x5);
foo(a_64x8);
Group

27.4.6 形式参数的类型

链接
27.4.6 形式参数的类型


27.5 Calling imported functions

链接
第二十七章 直接编程接口（DPI）, 主题
SystemVerilog 3.1a语言参考手册
27.5 Calling imported functions
第二十七章 直接编程接口（DPI） | 主题

The usage of imported functions is identical as for native SystemVerilog functions., hence the usage and syntax for calling imported functions is identical as for native SystemVerilog functions. Specifically, arguments with default values can be omitted from the call; arguments can be passed by name, if all formal arguments are named.

Group

第二十七章 直接编程接口（DPI）

主题
主题 | 描述
27.5.1 Argument passing | Argument passing for imported functions is ruled by the WYSIWYG principle: What You Specify Is What You Get, see Section 27.5.1.1. The evaluation order of formal arguments follows general SystemVerilog rules. Argument compatibility and coercion rules are the same as for native SystemVerilog functions. If a coercion is needed, a temporary variable is created and passed as the actual argument. For input and inout arguments, the temporary variable is initialized with the value of actual argument with the appropriate coercion; for output or inout arguments, the value of the temporary variable is assigned to the actual argument with the appropriate... more
27.5.2 Value changes for output and inout arguments | The SystemVerilog simulator is responsible for handling value changes for output and inout arguments. Such changes shall be detected and handled after control returns from imported functions to SystemVerilog code. For output and inout arguments, the value propagation (i.e., value change events) happens as if an actual argument was assigned a formal argument immediately after control returns from imported functions. If there is more than one argument, the order of such assignments and the related value change propagation follows general SystemVerilog rules.
链接
第二十七章 直接编程接口（DPI）, 主题


27.5.1 Argument passing

链接
27.5 Calling imported functions, 主题
SystemVerilog 3.1a语言参考手册
27.5.1 Argument passing
27.5 Calling imported functions | 主题

Argument passing for imported functions is ruled by the WYSIWYG principle: What You Specify Is What You Get, see Section 27.5.1.1. The evaluation order of formal arguments follows general SystemVerilog rules.

Argument compatibility and coercion rules are the same as for native SystemVerilog functions. If a coercion is needed, a temporary variable is created and passed as the actual argument. For input and inout arguments, the temporary variable is initialized with the value of actual argument with the appropriate coercion; for output or inout arguments, the value of the temporary variable is assigned to the actual argument with the appropriate conversion. The assignments between a temporary and the actual argument follow general SystemVerilog rules for assignments and automatic coercion.

On the SystemVerilog side of the interface, the values of actual arguments for formal input arguments of imported functions shall not be affected by the callee; the initial values of formal output arguments of imported functions are unspecified (and can be implementation-dependent), and the necessary coercions, if any, are applied as for assignments. imported functions shall not modify the values of their input arguments.

For the SystemVerilog side of the interface, the semantics of arguments passing is as if input arguments are passed by copy-in, output arguments are passed by copy-out, and inout arguments were passed by copy-in, copy-out. The terms copy-in and copy-out do not impose the actual implementation; they refer only to “hypothetical assignment”.

The actual implementation of argument passing is transparent to the SystemVerilog side of the interface. In particular, it is transparent to SystemVerilog whether an argument is actually passed by value or by reference. The actual argument passing mechanism is defined in the foreign language layer. See Annex E for more details.

Group

27.5 Calling imported functions

主题
主题 | 描述
27.5.1.1 “What You Specify Is What You Get” principle | The principle “What You Specify Is What You Get” guarantees the types of formal arguments of imported functions — an actual argument is guaranteed to be of the type specified for the formal argument, with the exception of open arrays (for which unspecified ranges are statically unknown). Formal arguments, other than open arrays, are fully defined by import declaration; they shall have ranges of packed or unpacked arrays exactly as specified in the import declaration. Only the declaration site of the imported function is relevant for such formal arguments. Another way to state this is that no compiler (either C... more
链接
27.5 Calling imported functions, 主题


27.5.1.1 “What You Specify Is What You Get” principle

链接
27.5.1 Argument passing
SystemVerilog 3.1a语言参考手册
27.5.1.1 “What You Specify Is What You Get” principle
27.5.1 Argument passing

The principle “What You Specify Is What You Get” guarantees the types of formal arguments of imported functions — an actual argument is guaranteed to be of the type specified for the formal argument, with the exception of open arrays (for which unspecified ranges are statically unknown). Formal arguments, other than open arrays, are fully defined by import declaration; they shall have ranges of packed or unpacked arrays exactly as specified in the import declaration. Only the declaration site of the imported function is relevant for such formal arguments.

Another way to state this is that no compiler (either C or SystemVerilog) can make argument coercions between a caller’s declared formal and the callee’s declared formals. this is because the callee’s formal arguments are declared in a different language than the caller’s formal arguments; hence here is no visible relationship between the two sets of formals. Users are expected to understand all argument relationships and provide properly matched types on both sides of the interface.

Formal arguments defined as open arrays have the size and ranges of the corresponding actual arguments, i.e., have the ranges of packed or unpacked arrays exactly as that of the actual argument. The unsized ranges of open arrays are determined at a call site; the rest of type information is specified at the import declaration.

So, if a formal argument is declared as bit [15:8] b [], then it is the import declaration which specifies the formal argument is an unpacked array of packed bit array with bounds 15 to 8, while the actual argument used at a particular call site defines the bounds for the unpacked part for that call.

Group

27.5.1 Argument passing

链接
27.5.1 Argument passing


27.5.2 Value changes for output and inout arguments

链接
27.5 Calling imported functions
SystemVerilog 3.1a语言参考手册
27.5.2 Value changes for output and inout arguments
27.5 Calling imported functions

The SystemVerilog simulator is responsible for handling value changes for output and inout arguments. Such changes shall be detected and handled after control returns from imported functions to SystemVerilog code.

For output and inout arguments, the value propagation (i.e., value change events) happens as if an actual argument was assigned a formal argument immediately after control returns from imported functions. If there is more than one argument, the order of such assignments and the related value change propagation follows general SystemVerilog rules.

Group

27.5 Calling imported functions

链接
27.5 Calling imported functions


27.6 Exported functions

链接
第二十七章 直接编程接口（DPI）
SystemVerilog 3.1a语言参考手册
27.6 Exported functions
第二十七章 直接编程接口（DPI）

DPI allows calling SystemVerilog functions from another language. However, such functions must adhere to the same restrictions on argument types and results as are imposed on imported functions. It is an error to export a function that does not satisfy such constraints.

SystemVerilog functions that can be called from foreign code need to be specified in export declarations. Export declarations are allowed to occur only in the scope in which the function being exported is defined. Only one export declaration per function is allowed in a given scope.

Note that class member functions cannot be exported, but all other SystemVerilog functions can be exported.

Similar to import declarations, export declarations can define an optional c_identifier to be used in the foreign language when calling an exported function.

Copy Code
dpi_import_export ::=     // from Annex A.2.6
    | export "DPI" [c_identifier =] function function_identifier;

Syntax 27-2—DPI export declaration syntax (excerpt from Annex A)

c_identifier is optional here. It defaults to function_identifier. For rules describing c_identifier, see Section 27.3. Note that all export functions are always context functions. No two functions in the same SystemVerilog scope can be exported with the same explicit or implicit c_identifier. The export declaration and the definition of the corresponding SystemVerilog function can occur in any order. Only one export declaration is permitted per SystemVerilog function.

Group

第二十七章 直接编程接口（DPI）

链接
第二十七章 直接编程接口（DPI）


27.7 Exported tasks

链接
第二十七章 直接编程接口（DPI）
SystemVerilog 3.1a语言参考手册
27.7 Exported tasks
第二十七章 直接编程接口（DPI）

SystemVerilog allows tasks to be called from a foreign language, similar to functions. Such tasks are termed “exported tasks”.

All aspects of exported functions described above in Section 27.6 apply to exported tasks. This includes legal declaration scopes as well as usage of the optional c_identifier.

It is never legal to call an exported task from within an imported function. These semantics are identical to native SystemVerilog semantics, in which it is illegal for a function to perform a task enable.

It is legal for an imported task to call an exported task only if the imported task is declared with the context property. Section 27.4.3 (Context tasks and functions) for more details.

One difference between exported tasks and exported functions is that SystemVerilog tasks do not have return value types. The return value of an exported task is an int value which indicates if a disable is active or not on the current execution thread.

Similarly, imported tasks return an int value which is used to indicate that the imported task has acknowledged a disable. See Section 27.8 for more detail on disables in DPI.

Group

第二十七章 直接编程接口（DPI）

链接
第二十七章 直接编程接口（DPI）


27.8 Disabling DPI tasks and functions

链接
第二十七章 直接编程接口（DPI）
SystemVerilog 3.1a语言参考手册
27.8 Disabling DPI tasks and functions
第二十七章 直接编程接口（DPI）

It is possible for a disable statement to disable a block that is currently executing a mixed language call chain. When a DPI import task or function is disabled, the C code is required to follow a simple disable protocol. The protocol gives the C code the opportunity to perform any necessary resource cleanup, such as closing open file handles, closing open VPI handles, or freeing heap memory.

An imported task or function is said to be in the disabled state when a disable statement somewhere in the design targets either it or a parent for disabling. Note that the only way for an imported task or function to enter the disabled state is immediately after the return of a call to an exported task or function. An important aspect of the protocol is that disabled import tasks and functions must programmatically acknowledge that they have been disabled. A task or function can determine that it is in the disabled state by calling the API function svIsDisabledState().

The protocol is composed of the following items:

  1. When an exported task returns due to a disable, it must return a value of 1. Otherwise it must return 0.
  2. When an imported task returns due to a disable, it must return a value of 1. Otherwise it must return 0.
  3. Before an imported function returns due to a disable, it must call the API function svAckDisabledState().
  4. Once an imported task or function enters the disabled state, it is illegal for the current function invocation to make any further calls to exported tasks or functions.
Items 2, 3, and 4 are mandatory behavior for imported DPI tasks and functions. It is the responsibility of the DPI programmer to correctly implement the behavior.

Item 1 is guaranteed by SystemVerilog simulators. In addition, simulators must implement checks to ensure that items 2, 3, and 4 are correctly followed by imported tasks and functions. If any protocol item is not correctly followed, a fatal simulation error is issued.

Note that if an exported task itself is the target of a disable, its parent imported task is not considered to be in the disabled state when the exported task returns. In such cases the exported task shall return value 0, and calls to svIsDisabledState() shall return 0 as well.

When a DPI imported task or function returns due to a disable, the values of its output and inout parameters are undefined. Similarly, function return values are undefined when an imported function returns due to a disable. C programmers can return values from disabled functions, and C programmers can write values into the locations of output and inout parameters of imported tasks or functions. However, SystemVerilog simulators are not obligated to propagate any such values to the calling SystemVerilog code if a disable is in effect.

Group

第二十七章 直接编程接口（DPI）

链接
第二十七章 直接编程接口（DPI）


第二十八章 SystemVerilog断言API

链接
主题
SystemVerilog 3.1a语言参考手册
第二十八章 SystemVerilog断言API
主题

本章定义了SystemVerilog中的断言应用程序编程接口（API）。

主题
主题
描述
28.1 需求
SystemVerilog提供了断言的能力以便提供下列功能：
  • 一个用户的C语言代码与断言事件相互作用。
  • 编写第三方的断言“波形”转储工具。
  • 编写第三方的断言覆盖工具。
  • 编写第三方的断言调试工具。
28.2 Extensions to VPI enumerations
These extensions shall be appended to the contents of the vpi_user.h file, described in IEEE Std. 1364-2001, Annex G. The numbers in the range 700 - 799 are reserved for the assertion portion of the VPI.
28.3 Static information
This section defines how to obtain assertion handles and other static assertion information.
28.4 Dynamic information
This section defines how to place assertion system and assertion callbacks.
28.5 Control functions
This section defines how to obtain assertion system control and assertion control information.
链接
主题


28.1 需求

链接
第二十八章 SystemVerilog断言API, 主题
SystemVerilog 3.1a语言参考手册
28.1 需求
第二十八章 SystemVerilog断言API | 主题

SystemVerilog提供了断言的能力以便提供下列功能：

  • 一个用户的C语言代码与断言事件相互作用。
  • 编写第三方的断言“波形”转储工具。
  • 编写第三方的断言覆盖工具。
  • 编写第三方的断言调试工具。

Group

第二十八章 SystemVerilog断言API

主题
主题
描述
28.1.1 命名约定
All elements added by this interface shall conform to the Verilog Procedural Interface (VPI) interface naming conventions.
  • All names are prefixed by vpi.
  • All type names shall start with vpi, followed by initially capitalized words with no separators, e.g., vpiAssertCheck.
  • All callback names shall start with cb, followed by initially capitalized words with no separators, e.g., cbAssertionStart.
  • All function names shall start with vpi_, followed by all lowercase words separated by underscores (_), e.g., vpi_get_assert_info().
链接
第二十八章 SystemVerilog断言API, 主题


28.1.1 命名约定

链接
28.1 需求
SystemVerilog 3.1a语言参考手册
28.1.1 命名约定
28.1 需求

All elements added by this interface shall conform to the Verilog Procedural Interface (VPI) interface naming conventions.

  • All names are prefixed by vpi.
  • All type names shall start with vpi, followed by initially capitalized words with no separators, e.g., vpiAssertCheck.
  • All callback names shall start with cb, followed by initially capitalized words with no separators, e.g., cbAssertionStart.
  • All function names shall start with vpi_, followed by all lowercase words separated by underscores (_), e.g., vpi_get_assert_info().

Group

28.1 需求

链接
28.1 需求


28.2 Extensions to VPI enumerations

链接
第二十八章 SystemVerilog断言API, 主题
SystemVerilog 3.1a语言参考手册
28.2 Extensions to VPI enumerations
第二十八章 SystemVerilog断言API | 主题

These extensions shall be appended to the contents of the vpi_user.h file, described in IEEE Std. 1364-2001, Annex G. The numbers in the range 700 - 799 are reserved for the assertion portion of the VPI.

Group

第二十八章 SystemVerilog断言API

主题
主题 | 描述
28.2.1 Object types | This section lists the object type VPI calls. The VPI reserved range for these calls is 700 - 729.
28.2.2 Object properties | This section lists the object property VPI calls. The VPI reserved range for these calls is 700 - 729.
28.2.3 Callbacks | This section lists the system callbacks. The VPI reserved range for these calls is 700 - 719. 1) Assertion
28.2.4 Control constants | This section lists the system control constant callbacks. The VPI reserved range for these calls is 730 - 759. 1) Assertion
链接
第二十八章 SystemVerilog断言API, 主题


28.2.1 Object types

链接
28.2 Extensions to VPI enumerations
SystemVerilog 3.1a语言参考手册
28.2.1 Object types
28.2 Extensions to VPI enumerations

This section lists the object type VPI calls. The VPI reserved range for these calls is 700 - 729.

Copy Code
#define vpiAssertion 700 /* assertion */
Group

28.2 Extensions to VPI enumerations

链接
28.2 Extensions to VPI enumerations


28.2.2 Object properties

链接
28.2 Extensions to VPI enumerations
SystemVerilog 3.1a语言参考手册
28.2.2 Object properties
28.2 Extensions to VPI enumerations

This section lists the object property VPI calls. The VPI reserved range for these calls is 700 - 729.

Copy Code
/* Assertion types */
#define vpiSequenceType 701
#define vpiAssertType 702
#define vpiCoverType 703
#define vpiPropertyType 704
#define vpiImmediateAssertType705
Group

28.2 Extensions to VPI enumerations

链接
28.2 Extensions to VPI enumerations


28.2.3 Callbacks

链接
28.2 Extensions to VPI enumerations
SystemVerilog 3.1a语言参考手册
28.2.3 Callbacks
28.2 Extensions to VPI enumerations

This section lists the system callbacks. The VPI reserved range for these calls is 700 - 719.

1) Assertion

Copy Code
#define cbAssertionStart       700
#define cbAssertionSuccess     701
#define cbAssertionFailure     702
#define cbAssertionStepSuccess 703
#define cbAssertionStepFailure 704
#define cbAssertionDisable     705
#define cbAssertionEnable      706
#define cbAssertionReset       707
#define cbAssertionKill        708

2) “Assertion system”

Copy Code
#define cbAssertionSysInitialized  709
#define cbAssertionSysStart        710
#define cbAssertionSysStop         711
#define cbAssertionSysEnd          712
#define cbAssertionSysReset        713
Group

28.2 Extensions to VPI enumerations

链接
28.2 Extensions to VPI enumerations


28.2.4 Control constants

链接
28.2 Extensions to VPI enumerations
SystemVerilog 3.1a语言参考手册
28.2.4 Control constants
28.2 Extensions to VPI enumerations

This section lists the system control constant callbacks. The VPI reserved range for these calls is 730 - 759.

1) Assertion

Copy Code
#define vpiAssertionDisable     730
#define vpiAssertionEnable      731
#define vpiAssertionReset       732
#define vpiAssertionKill        733
#define vpiAssertionEnableStep  734
#define vpiAssertionDisableStep 735

2) Assertion stepping

Copy Code
#define vpiAssertionClockSteps  736

3) “Assertion system”

Copy Code
#define vpiAssertionSysStart    737
#define vpiAssertionSysStop     738
#define vpiAssertionSysEnd      739
#define vpiAssertionSysReset    740
Group

28.2 Extensions to VPI enumerations

链接
28.2 Extensions to VPI enumerations


28.3 Static information

链接
第二十八章 SystemVerilog断言API, 主题
SystemVerilog 3.1a语言参考手册
28.3 Static information
第二十八章 SystemVerilog断言API | 主题

This section defines how to obtain assertion handles and other static assertion information.

Group

第二十八章 SystemVerilog断言API

主题
主题
描述
28.3.1 Obtaining assertion handles
SystemVerilog extends the VPI module iterator model (i.e., the instance) to encompass assertions, as shown in Figure 28-1.

The following steps highlight how to obtain the assertion handles for named assertions.

Figure 28-1 — Encompassing assertions

Note: Iteration on assertions from interfaces is not shown in Figure 28-1 since the interface object type is not currently defined in VPI. However the assertion API permits iteration on assertions from interface instance handles and obtaining static information on assertions used in interfaces (see Section 28.3.2.1).
1) Iterate all assertions in the design: use a NULL reference handle (ref) to vpi_iterate(), e.g.,

28.3.2 Obtaining static assertion information
The following information about an assertion is considered to be static.
  • Assertion name
  • Instance in which the assertion occurs
  • Module definition containing the assertion
  • Assertion type
    1. Sequence
    2. Assert
    3. Cover
    4. Property
    5. ImmediateAssert
  • Assertion source information: the file, line, and column where the assertion is defined.
  • Assertion clocking block/expression
链接
第二十八章 SystemVerilog断言API, 主题


28.3.1 Obtaining assertion handles

链接
28.3 Static information
SystemVerilog 3.1a语言参考手册
28.3.1 Obtaining assertion handles
28.3 Static information

SystemVerilog extends the VPI module iterator model (i.e., the instance) to encompass assertions, as shown in Figure 28-1.

The following steps highlight how to obtain the assertion handles for named assertions.

Figure 28-1 — Encompassing assertions

Note: Iteration on assertions from interfaces is not shown in Figure 28-1 since the interface object type is not currently defined in VPI. However the assertion API permits iteration on assertions from interface instance handles and obtaining static information on assertions used in interfaces (see Section 28.3.2.1).

1) Iterate all assertions in the design: use a NULL reference handle (ref) to vpi_iterate(), e.g.,

Copy Code
itr = vpi_iterate(vpiAssertion, NULL);

while (assertion = vpi_scan(itr)) {
    /* process assertion */
}

2) Iterate all assertions in an instance: pass the appropriate instance handle as a reference handle to vpi_iterate(), e.g.,

Copy Code
itr = vpi_iterate(vpiAssertion, instanceHandle);
while (assertion = vpi_scan(itr)) {
    /* process assertion */
}

3) Obtain the assertion by name: extend vpi_handle_by_name to also search for assertion names in the appropriate scope(s), e.g.,

Copy Code
vpiHandle = vpi_handle_by_name(assertName, scope)

4) To obtain an assertion of a specific type, e.g. cover assertions, the following approach should be used:

Copy Code
vpiHandle assertion;

itr = vpi_iterate(vpiAssertionType, NULL);

while (assertion = vpi_scan(itr)) {
    if (vpi_get(vpiAssertionType, assertion) == vpiCoverType) {
        /* process cover type assertion */
    }
}

NOTES

  1. As with all VPI handles, assertion handles are handles to a specific instance of a specific assertion.
  2. Unnamed assertions cannot be found by name.

Group

28.3 Static information

链接
28.3 Static information


28.3.2 Obtaining static assertion information

链接
28.3 Static information, 主题
SystemVerilog 3.1a语言参考手册
28.3.2 Obtaining static assertion information
28.3 Static information | 主题

The following information about an assertion is considered to be static.

  • Assertion name
  • Instance in which the assertion occurs
  • Module definition containing the assertion
  • Assertion type
    1. Sequence
    2. Assert
    3. Cover
    4. Property
    5. ImmediateAssert
  • Assertion source information: the file, line, and column where the assertion is defined.
  • Assertion clocking block/expression

Group

28.3 Static information

主题
主题 | 描述
28.3.2.1 Using vpi_get_assertion_info | Static information can be obtained directly from an assertion handle by using vpi_get_assertion_info(), as shown below.
28.3.2.2 Extending vpi_get() and vpi_get_str() | In addition to vpi_get_assertion_info, the following existing VPI functions are also extended:
链接
28.3 Static information, 主题


28.3.2.1 Using vpi_get_assertion_info

链接
28.3.2 Obtaining static assertion information
SystemVerilog 3.1a语言参考手册
28.3.2.1 Using vpi_get_assertion_info
28.3.2 Obtaining static assertion information

Static information can be obtained directly from an assertion handle by using vpi_get_assertion_info(), as shown below.

Copy Code
typedef struct t_vpi_source_info {
    PLI_BYTE8 *fileName;
    PLI_INT32 startLine;
    PLI_INT32 startColumn;
    PLI_INT32 endLine;
    PLI_INT32 endColumn;
} s_vpi_source_info, *p_vpi_source_info;

typedef struct t_vpi_assertion_info {
    PLI_BYTE8 *assertName; /* name of assertion */
    vpiHandle instance; /* instance containing assertion */
    PLI_BYTE8 defname; /* name of module/interface containing assertion */
    vpiHandle clock; /* clocking expression */
    PLI_INT32 assertionType; /* vpiSequenceType, vpiAssertType, vpiCoverType,*/
                             /* vpiPropertyType, vpiImmediateAssertType */
    s_vpi_source_info sourceInfo;
} s_vpi_assertion_info, *p_vpi_assertion_info;

PLI_INT32 vpi_get_assertion_info (assert_handle, p_vpi_assertion_info);

This call obtains all the static information associated with an assertion.

The inputs are a valid handle to an assertion and a pointer to an existing s_vpi_assertion_info data structure. On success, the function returns TRUE and the s_vpi_assertion_info data structure is filled in as appropriate. On failure, the function returns FALSE and the contents of the assertion data structure are unpredictable.

Assertions can occur in modules and interfaces: for assertions defined in modules, the instance field in the s_vpi_assertion_info structure shall contain the handle to the appropriate module or interface instance. Note that VPI does not currently define the information model for interfaces and therefore the interface instance handle shall be implementation dependent. The clock field of that structure contains a handle to the event expression representing the clock for the assertion, as determined by Section 17.14.

NOTE: a single call returns all the information for efficiency reasons.

Group

28.3.2 Obtaining static assertion information

链接
28.3.2 Obtaining static assertion information


28.3.2.2 Extending vpi_get() and vpi_get_str()

链接
28.3.2 Obtaining static assertion information
SystemVerilog 3.1a语言参考手册
28.3.2.2 Extending vpi_get() and vpi_get_str()
28.3.2 Obtaining static assertion information

In addition to vpi_get_assertion_info, the following existing VPI functions are also extended:

Copy Code
vpi_get(), vpi_get_str()

vpi_get() can be used to query the following VPI property from a handle to an assertion:

Copy Code
vpiAssertionDirective
returns one of vpiSequenceType, vpiAssertType, vpiCoverType, vpiPropertyType, vpiImmediateAssertType.
vpiLineNo
returns the line number where the assertion is declared.

vpi_get_str() can be used to obtain the following VPI properties from an assertion handle:

Copy Code
vpiFileName
returns the filename of the source file where the assertion was declared.
vpiName
returns the name of the assertion.
vpiFullName
returns the fully qualified name of the assertion.
Group

28.3.2 Obtaining static assertion information

链接
28.3.2 Obtaining static assertion information


28.4 Dynamic information

链接
第二十八章 SystemVerilog断言API, 主题
SystemVerilog 3.1a语言参考手册
28.4 Dynamic information
第二十八章 SystemVerilog断言API | 主题

This section defines how to place assertion system and assertion callbacks.

Group

第二十八章 SystemVerilog断言API

主题
主题 | 描述
28.4.1 Placing assertion system callbacks | Use vpi_register_cb(), setting the cb_rtn element to the function to be invoked and the reason element of the s_cb_data structure to one of the following values, to place an assertion system callback.
28.4.2 Placing assertions callbacks | Use vpi_register_assertion_cb() to place an assertion callback; the prototype is:
链接
第二十八章 SystemVerilog断言API, 主题


28.4.1 Placing assertion system callbacks

链接
28.4 Dynamic information
SystemVerilog 3.1a语言参考手册
28.4.1 Placing assertion system callbacks
28.4 Dynamic information

Use vpi_register_cb(), setting the cb_rtn element to the function to be invoked and the reason element of the s_cb_data structure to one of the following values, to place an assertion system callback.

Copy Code
cbAssertionSysInitialized
occurs after the system has initialized. No assertion-specific actions can be performed until this callback
completes. The assertion system can initialize before cbStartOfSimulation does or afterwards.

cbAssertionSysStart
the assertion system has become active and starts processing assertion attempts. This always occur after
cbAssertionSysInitialized. By default, the assertion system is “started” on simulation startup, but
the user can delay this by using assertion system control actions.

cbAssertionSysStop
the assertion system has been temporarily suspended. While stopped no assertion attempts are processed
and no assertion-related callbacks occur. The assertion system can be stopped and resumed an arbitrary
number of times during a single simulation run.

cbAssertionSysEnd
occurs when all assertions have completed and no new attempts shall start. Once this callback occurs no
more assertion-related callbacks shall occur and assertion-related actions shall have no further effect. This
typically occurs after the end of simulation.

cbAssertionSysReset
occurs when the assertion system is reset, e.g., due to a system control action.

The callback routine invoked follows the normal VPI callback prototype and is passed an s_cb_data containing the callback reason and any user data provided to the vpi_register_cb() call.

Group

28.4 Dynamic information

链接
28.4 Dynamic information


28.4.2 Placing assertions callbacks

链接
28.4 Dynamic information
SystemVerilog 3.1a语言参考手册
28.4.2 Placing assertions callbacks
28.4 Dynamic information

Use vpi_register_assertion_cb() to place an assertion callback; the prototype is:

Copy Code
/* typedef for vpi_register_assertion_cb callback function */
typedef PLI_INT32 (vpi_assertion_callback_func)(
    PLI_INT32 reason, /* callback reason */
    p_vpi_time cb_time, /* callback time */
    vpiHandle assertion, /* handle to assertion */
    p_vpi_attempt_info info, /* attempt related information */
    PLI_BYTE8 *user_data /* user data entered upon registration */
);

vpiHandle vpi_register_assertion_cb(
    vpiHandle assertion, /* handle to assertion */
    PLI_INT32 reason, /* reason for which callbacks needed */
    vpi_assertion_callback_func *cb_rtn,
    PLI_BYTE8 *user_data /* user data to be supplied to cb */
);

typedef struct t_vpi_assertion_step_info {
    PLI_INT32 matched_expression_count;
    vpiHandle *matched_exprs; /* array of expressions */
    p_vpi_source_info *exprs_source_info; /* array of source info */
    PLI_INT32 stateFrom, stateTo;/* identify transition */
} s_vpi_assertion_step_info, *p_vpi_assertion_step_info;

typedef struct t_vpi_attempt_info {
    union {
        vpiHandle failExpr;
        p_vpi_assertion_step_info step;
    } detail;
    s_vpi_time attemptStartTime; /* Time attempt triggered */
} s_vpi_attempt_info, *p_vpi_attempt_info;

where reason is any of the following.

Copy Code
cbAssertionStart
an assertion attempt has started. For most assertions one attempt starts each and every clock tick.

cbAssertionSuccess
when an assertion attempt reaches a success state.

cbAssertionFailure
when an assertion attempt fails to reach a success state.

cbAssertionStepSuccess
progress one step an attempt. By default, step callbacks are not enabled on any assertions; they are
enabled on a per-assertion/per-attempt basis (see Section 28.5.2), rather than on a per-assertion basis.

cbAssertionStepFailure
failure to progress by one step along an attempt. By default, step callbacks are not enabled on any assertions;
they are enabled on a per-assertion/per-attempt basis (see Section 28.5.2), rather than on a perassertion
basis.

cbAssertionDisable
whenever the assertion is disabled (e.g., as a result of a control action).

cbAssertionEnable
whenever the assertion is enabled.

cbAssertionReset
whenever the assertion is reset.

cbAssertionKill
when an attempt is killed (e.g., as a result of a control action).

These callbacks are specific to a given assertion; placing such a callback on one assertion does not cause the callback to trigger on an event occurring on a different assertion. If the callback is successfully placed, a handle to the callback is returned. This handle can be used to remove the callback via vpi_remove_cb(). If there were errors on placing the callback, a NULL handle is returned. As with all other calls, invoking this function with invalid arguments has unpredictable effects.

Once the callback is placed, the user-supplied function shall be called each time the specified event occurs on the given assertion. The callback shall continue to be called whenever the event occurs until the callback is removed.

The callback function shall be supplied the following arguments:

  1. the reason for the callback
  2. a pointer to the time of the callback
  3. the handle for the assertion
  4. a pointer to an attempt information structure
  5. a reference to the user data supplied when the callback was registered.
The t_vpi_attempt_info attempt information structure contains details relevant to the specific event that occurred.
  • On disable, enable, reset and kill callbacks, the returned p_vpi_attempt_info info pointer is NULL and no attempt information is available.
  • On start and success callbacks, only the attemptStartTime field is valid.
  • On a cbAssertionFailure callback, the attemptStartTime and detail.failExpr fields are valid.
  • On a step callback, the attemptStartTime and detail.step fields are valid.
On a step callback, the detail describes the set of expressions matched in satisfying a step along the assertion, along with the corresponding source references. In addition, the step also identifies the source and destination “states” needed to uniquely identify the path being taken through the assertion. State ids are just integers, with 0 identifying the origin state, 1 identifying an accepting state, and any other number representing some intermediate point in the assertion. It is possible for the number of expressions in a step to be 0 (zero), which represents an unconditional transition. In the case of a failing transition, the information provided is just as that for a successful one, but the last expression in the array represents the expression where the transition failed.

NOTES

1—In a failing transition, there shall always be at least one element in the expression array.

2—Placing a step callback results in the same callback function being invoked for both success and failure steps.

3—The content of the cb_time field depends on the reason identified by the reason field, as follows:

  • cbAssertionStart — cb_time is the time when the assertion attempt has been started.
  • cbAssertionSuccess, cbAssertionFailure — cb_time is the time when the assertion succeeded/failed.
  • cbAssertionStepSuccess, cbAssertionStepFailure — cb_time is the time when the assertion attempt step succeeded/failed.
  • cbAssertionDisable, cbAssertionEnable, cbAssertionReset, cbAssertionKill — cb_time is the time when the assertion attempt was disabled/enabled/reset/killed.
4—In contrast to cb_time, the content of attemptStartTime is always the start time of the actual attempt of an assertion. It can be used as an unique ID that distinguishes the attempts of any given assertion.

Group

28.4 Dynamic information

链接
28.4 Dynamic information


28.5 Control functions

链接
第二十八章 SystemVerilog断言API, 主题
SystemVerilog 3.1a语言参考手册
28.5 Control functions
第二十八章 SystemVerilog断言API | 主题

This section defines how to obtain assertion system control and assertion control information.

Group

第二十八章 SystemVerilog断言API

主题
主题 | 描述
28.5.1 Assertion system control | Use vpi_control(), with one of the following operators and no other arguments, to obtain assertion system control information. Usage example: vpi_control(vpiAssertionSysReset) vpiAssertionSysReset discards all attempts in progress for all assertions and restore the entire assertion system to its initial state. Any pre-existing vpiAssertionStepSuccess and vpiAssertionStepFailure callbacks shall be removed; all other assertion callbacks shall remain. Usage example: vpi_control(vpiAssertionSysStop) vpiAssertionSysStop considers all attempts in progress as unterminated and disable any further assertions from being started. This control has no effect on pre-existing assertion callbacks. Usage example: vpi_control(vpiAssertionSysStart) vpiAssertionSysStart restarts the assertion system after it was stopped (e.g., due to vpiAssertionSysStop). Once... more
28.5.2 Assertion control | Use vpi_control(), with one of the following operators, to obtain assertion control information. — For the following operators, the second argument shall be a valid assertion handle. Usage example: vpi_control(vpiAssertionReset, assertionHandle) vpiAssertionReset discards all current attempts in progress for this assertion and resets this assertion to its initial state. Usage example: vpi_control(vpiAssertionDisable, assertionHandle) vpiAssertionDisable disables the starting of any new attempts for this assertion. This has no effect on any existing attempts. or if the assertion already disabled. By default, all assertions are enabled. Usage example: vpi_control(vpiAssertionEnable, assertionHandle) vpiAssertionEnable enables starting new attempts for this assertion. This has no effect... more
链接
第二十八章 SystemVerilog断言API, 主题


28.5.1 Assertion system control

链接
28.5 Control functions
SystemVerilog 3.1a语言参考手册
28.5.1 Assertion system control
28.5 Control functions

Use vpi_control(), with one of the following operators and no other arguments, to obtain assertion system control information.

Usage example: vpi_control(vpiAssertionSysReset)

vpiAssertionSysReset

discards all attempts in progress for all assertions and restore the entire assertion system to its initial state. Any pre-existing vpiAssertionStepSuccess and vpiAssertionStepFailure callbacks shall be removed; all other assertion callbacks shall remain.

Usage example: vpi_control(vpiAssertionSysStop)

vpiAssertionSysStop

considers all attempts in progress as unterminated and disable any further assertions from being started. This control has no effect on pre-existing assertion callbacks.

Usage example: vpi_control(vpiAssertionSysStart)

vpiAssertionSysStart

restarts the assertion system after it was stopped (e.g., due to vpiAssertionSysStop). Once started, attempts shall resume on all assertions. This control has no effect on prior assertion callbacks.

Usage example: vpi_control(vpiAssertionSysEnd)

vpiAssertionSysEnd

discard all attempts in progress and disables any further assertions from starting. All assertion callbacks currently installed shall be removed. Note that once this control is issued, no further assertion related actions shall be permitted.

Group

28.5 Control functions

链接
28.5 Control functions


28.5.2 Assertion control

链接
28.5 Control functions
SystemVerilog 3.1a语言参考手册
28.5.2 Assertion control
28.5 Control functions

Use vpi_control(), with one of the following operators, to obtain assertion control information.

— For the following operators, the second argument shall be a valid assertion handle.

Usage example: vpi_control(vpiAssertionReset, assertionHandle)

vpiAssertionReset

discards all current attempts in progress for this assertion and resets this assertion to its initial state.

Usage example: vpi_control(vpiAssertionDisable, assertionHandle)

vpiAssertionDisable

disables the starting of any new attempts for this assertion. This has no effect on any existing attempts. or if the assertion already disabled. By default, all assertions are enabled.

Usage example: vpi_control(vpiAssertionEnable, assertionHandle)

vpiAssertionEnable

enables starting new attempts for this assertion. This has no effect if assertion already enabled or on any existing attempts.

— For the following operators, the second argument shall be a valid assertion handle and the third argument shall be an attempt start-time (as a pointer to a correctly initialized s_vpi_time structure).

Usage example: vpi_control(vpiAssertionKill, assertionHandle, attemptStartTime)

vpiAssertionKill

discards the given attempts, but leaves the assertion enabled and does not reset any state used by this assertion (e.g., past() sampling).

Usage example: vpi_control(vpiAssertionDisableStep, assertionHandle, attemptStartTime)

vpiAssertionDisableStep

disables step callbacks for this assertion. This has no effect if stepping not enabled or it is already disabled.

— For the following operator, the second argument shall be a valid assertion handle, the third argument shall be an attempt start-time (as a pointer to a correctly initialized s_vpi_time structure) and the fourth argument shall be a step control constant.

Usage example: vpi_control(vpiAssertionEnableStep, assertionHandle, attemptStartTime, vpiAssertionClockSteps)

vpiAssertionEnableStep

enables step callbacks to occur for this assertion attempt. By default, stepping is disabled for all assertions. This call has no effect if stepping is already enabled for this assertion and attempt, other than possibly changing the stepping mode for the attempt if the attempt has not occurred yet. The stepping mode of any particular attempt cannot be modified after the assertion attempt in question has started.

NOTE—In this release, the only step control constant available is vpiAssertionClockSteps, indicating callbacks on a per assertion/clock-tick basis. The assertion clock is the event expression supplied as the clocking expression to the assertion declaration. The assertion shall “advance” whenever this event occurs and, when stepping is enabled, such events shall also cause step callbacks to occur.

Group

28.5 Control functions

链接
28.5 Control functions


第二十九章 SystemVerilog覆盖API

链接
主题
SystemVerilog 3.1a语言参考手册
第二十九章 SystemVerilog覆盖API
主题
主题
主题
描述
29.1 需求
This chapter defines the Coverage Application Programming Interface (API) in SystemVerilog.
29.2 SystemVerilog real-time coverage access
This section describes the mechanisms in SystemVerilog through which SystemVerilog code can query and control coverage information. Coverage information is provided to SystemVerilog by means of a number of built-in system functions (described in Section 29.2.2) using a number of predefined constants (described in Section 29.2.1) to describe the types of coverage and the control actions to be performed.
29.3 FSM recognition
Coverage tools need to have automatic recognition of many of the common FSM coding idioms in Verilog/ SystemVerilog. This standard does not attempt to describe or require any specific automatic FSM recognition mechanisms. However, the standard does prescribe a means by which non-automatic FSM extraction occurs. The presence of any of these standard FSM description additions shall override the tool’s default extraction mechanism.

Identification of an FSM consists of identifying the following items:
  1. the state register (or expression)
  2. the next state register (this is optional)
  3. the legal states.
29.4 VPI coverage extensions
链接
主题


29.1 需求

链接
第二十九章 SystemVerilog覆盖API, 主题
SystemVerilog 3.1a语言参考手册
29.1 需求
第二十九章 SystemVerilog覆盖API | 主题

This chapter defines the Coverage Application Programming Interface (API) in SystemVerilog.

Group

第二十九章 SystemVerilog覆盖API

主题
主题
描述
29.1.1 SystemVerilog API
The following criteria are used within this API.
1) This API shall be similar for all coverages
There are a wide number of coverage types available, with possibly different sets offered by different vendors. Maintaining a common interface across all the different types enhances portability and ease of use.
2) At a minimum, the following types of coverage shall be supported:
a) statement coverage
b) toggle coverage
c) fsm coverage
i) fsm states
ii) fsm transitions
c) assertion coverage
3) Coverage APIs shall be extensible in a transparent manner, i.e., adding a new coverage type shall not break any existing... more
29.1.2 Naming conventions
All elements added by this interface shall conform to the Verilog Procedural Interface (VPI) interface naming conventions.
  • All names are prefixed by vpi.
  • All type names shall start with vpi, followed by initially capitalized words with no separators, e.g., vpiCoverageStmt.
  • All callback names shall start with cb, followed by initially capitalized words with no separators, e.g., cbAssertionStart.
  • All function names shall start with vpi_, followed by all lowercase words separated by underscores (_), e.g., vpi_control().
29.1.3 Nomenclature
The following terms are used in this standard.
Statement coverage — whether a statement has been executed or not, where statement is anything defined as a statement in the LRM. Covered means it executed at least once. Some implementations also permit querying the execution count. The granularity of statement coverage can be per-statement or per-statement block (however defined).
FSM coverage — the number of states in a finite state machine (FSM) that this simulation reached. This standard does not require FSM automatic extraction, but a standard mechanism to force specific extraction is available via pragmas.
Toggle coverage — for each... more
链接
第二十九章 SystemVerilog覆盖API, 主题


29.1.1 SystemVerilog API

链接
29.1 需求
SystemVerilog 3.1a语言参考手册
29.1.1 SystemVerilog API
29.1 需求

The following criteria are used within this API.

1) This API shall be similar for all coverages

There are a wide number of coverage types available, with possibly different sets offered by different vendors. Maintaining a common interface across all the different types enhances portability and ease of use.

2) At a minimum, the following types of coverage shall be supported:

a) statement coverage

b) toggle coverage

c) fsm coverage

i) fsm states

ii) fsm transitions

c) assertion coverage

3) Coverage APIs shall be extensible in a transparent manner, i.e., adding a new coverage type shall not break any existing coverage usage.

4) This API shall provide means to obtain coverage information from specific sub-hierarchies of the design without requiring the user to enumerate all instances in those hierarchies.

Group

29.1 需求

链接
29.1 需求


29.1.2 Naming conventions

链接
29.1 需求
SystemVerilog 3.1a语言参考手册
29.1.2 Naming conventions
29.1 需求

All elements added by this interface shall conform to the Verilog Procedural Interface (VPI) interface naming conventions.

  • All names are prefixed by vpi.
  • All type names shall start with vpi, followed by initially capitalized words with no separators, e.g., vpiCoverageStmt.
  • All callback names shall start with cb, followed by initially capitalized words with no separators, e.g., cbAssertionStart.
  • All function names shall start with vpi_, followed by all lowercase words separated by underscores (_), e.g., vpi_control().

Group

29.1 需求

链接
29.1 需求


29.1.3 Nomenclature

链接
29.1 需求
SystemVerilog 3.1a语言参考手册
29.1.3 Nomenclature
29.1 需求

The following terms are used in this standard.

Statement coverage — whether a statement has been executed or not, where statement is anything defined as a statement in the LRM. Covered means it executed at least once. Some implementations also permit querying the execution count. The granularity of statement coverage can be per-statement or per-statement block (however defined).

FSM coverage — the number of states in a finite state machine (FSM) that this simulation reached. This standard does not require FSM automatic extraction, but a standard mechanism to force specific extraction is available via pragmas.

Toggle coverage — for each bit of every signal (wire and register), whether that bit has both a 0 value and a 1 value. Full coverage means both are seen; otherwise, some implementations can query for partial coverage. Some implementations also permit querying the toggle count of each bit.

Assertion coverage — for each assertion, whether it has had at least one success. Implementations permit querying for further details, such as attempt counts, success counts, failure counts and failure coverage.

These terms define the “primitives” for each coverage type. Over instances or blocks, the coverage number is merely the sum of all contained primitives in that instance or block.

Group

29.1 需求

链接
29.1 需求


29.2 SystemVerilog real-time coverage access

链接
第二十九章 SystemVerilog覆盖API, 主题
SystemVerilog 3.1a语言参考手册
29.2 SystemVerilog real-time coverage access
第二十九章 SystemVerilog覆盖API | 主题

This section describes the mechanisms in SystemVerilog through which SystemVerilog code can query and control coverage information. Coverage information is provided to SystemVerilog by means of a number of built-in system functions (described in Section 29.2.2) using a number of predefined constants (described in Section 29.2.1) to describe the types of coverage and the control actions to be performed.

Group

第二十九章 SystemVerilog覆盖API

主题
主题 | 描述
29.2.1 Predefined coverage constants in SystemVerilog | The following predefined ‘defines represent basic real-time coverage capabilities accessible directly from SystemVerilog. — Coverage control
29.2.2 Built-in coverage access system functions |
链接
第二十九章 SystemVerilog覆盖API, 主题


29.2.1 Predefined coverage constants in SystemVerilog

链接
29.2 SystemVerilog real-time coverage access
SystemVerilog 3.1a语言参考手册
29.2.1 Predefined coverage constants in SystemVerilog
29.2 SystemVerilog real-time coverage access

The following predefined ‘defines represent basic real-time coverage capabilities accessible directly from SystemVerilog.

— Coverage control

Copy Code
‘define SV_COV_START 0
‘define SV_COV_STOP 1
‘define SV_COV_RESET 2
‘define SV_COV_CHECK 3

— Scope definition (hierarchy traversal/accumulation type)

Copy Code
‘define SV_COV_MODULE 10
‘define SV_COV_HIER 11

— Coverage type identification

Copy Code
‘define SV_COV_ASSERTION 20
‘define SV_COV_FSM_STATE 21
‘define SV_COV_STATEMENT 22
‘define SV_COV_TOGGLE 23

— Status results

Copy Code
‘define SV_COV_OVERFLOW -2
‘define SV_COV_ERROR -1
‘define SV_COV_NOCOV 0
‘define SV_COV_OK 1
‘define SV_COV_PARTIAL 2
Group

29.2 SystemVerilog real-time coverage access

链接
29.2 SystemVerilog real-time coverage access


29.2.2 Built-in coverage access system functions

链接
29.2 SystemVerilog real-time coverage access, 主题
SystemVerilog 3.1a语言参考手册
29.2.2 Built-in coverage access system functions
29.2 SystemVerilog real-time coverage access | 主题
Group

29.2 SystemVerilog real-time coverage access

主题
主题 | 描述
29.2.2.1 $coverage_control |
29.2.2.2 $coverage_get_max |
29.2.2.3 $coverage_get |
29.2.2.4 $coverage_merge |
29.2.2.5 $coverage_save |
链接
29.2 SystemVerilog real-time coverage access, 主题


29.2.2.1 $coverage_control

链接
29.2.2 Built-in coverage access system functions
SystemVerilog 3.1a语言参考手册
29.2.2.1 $coverage_control
29.2.2 Built-in coverage access system functions
Copy Code
$coverage_control(control_constant,
                  coverage_type,
                  scope_def,
                  modules_or_instance)

This function is used to control or query coverage availability in the specified portion of the hierarchy. The following control options are available:

‘SV_COV_START

If possible, starts collecting coverage information in the specified hierarchy. No effect if coverage is already being collected. Note that coverage is automatically started at the beginning of simulation for all portions of the hierarchy enabled for coverage.

‘SV_COV_STOP

Stops collecting coverage information in the specified hierarchy. No effect if coverage is not being collected.

‘SV_COV_RESET

Resets all available coverage information in the specified hierarchy. No effect if coverage not available.

‘SV_COV_CHECK

Checks if coverage information can be obtained from the specified hierarchy. Note the possibility of having coverage information does imply that coverage is being collected, as the coverage could have been stopped.

The return value is a ‘define name, with the value indicating the success of the action.

‘SV_COV_OK

On a check operation denotes that coverage is fully available in the specified hierarchy. For all other operations, represents successful and complete execution of the desired operation.

‘SV_COV_ERROR

On all operations means that the control operation failed without any effect, typically due to errors in arguments, such as a non-existing module.

‘SV_COV_NOCOV

On a check or start operation, denotes that coverage is not available at any point in the specified hierarchy.

‘SV_COV_PARTIAL

On a check or start operation, denotes that coverage is only partially available in the specified hierarchy.

The table below describes the possible return values for each of the coverage control options:

Table 29-1: Coverage control return values

 | ‘SV_COV_OK | ‘SV_COV_ERROR | ‘SV_COV_NOCOV | ‘SV_COV_PARTIAL
‘SV_COV_START | success | bad args | no coverage | partial coverage
‘SV_COV_STOP | success | bad args | - | -
‘SV_COV_RESET | success | bad args | - | -
‘SV_COV_CHECK | full coverage | bad args | no coverage | partial coverage

Starting, stopping, or resetting coverage multiple times in succession for the same instance(s) has no further effect if coverage has already been started, stopped, or reset for that/those instance(s).

The hierarchy(ies) being controlled or queried are specified as follows.

‘SV_MODULE_COV, "unique module def name"

provides coverage of all instances of the given module (the unique module name is a string), excluding any child instances in the instances of the given module. The module definition name can use special notation to describe nested module definitions.

‘SV_COV_HIER, "module name"

provides coverage of all instances of the given module, including all the hierarchy below.

‘SV_MODULE_COV, instance_name

provides coverage of the one named instance. The instance is specified as a normal Verilog hierarchical path.

‘SV_COV_HIER, instance_name

provides coverage of the named instance, plus all the hierarchy below it.

All the permutations are summarized in Table 29-2.

Table 29-2: Instance coverage permutations

Control/query | “Definition name” | instance.name
‘SV_COV_MODULE | The sum of coverage for all instances of the named module, excluding any hierarchy below those instances. | Coverage for just the named instance, excluding any hierarchy in instances below that instance.
‘SV_COV_HIER | The sum of coverage for all instances of the named module, including all coverage for all hierarchy below those instances. | Coverage for the named instance and any hierarchy below it.

NOTE—Definition names are represented as strings, whereas instance names are referenced by hierarchical paths. A hierarchical path need not include any . if the path refers to an instance in the current context (i.e., normal Verilog hierarchical path rules apply).

Example 29-1 — Hierarchical instance example

If coverage is enabled on all instances shown in Example 29-1 —, then:

$coverage_control(‘SV_COV_CHECK, ‘SV_COV_TOGGLE, ‘SV_COV_HIER, $root)

checks all instances to verify they have coverage and, in this case, returns ‘SV_COV_OK.

$coverage_control(‘SV_COV_RESET, ‘SV_COV_TOGGLE, ‘SV_COV_MODULE, "DUT")

resets coverage collection on both instances of the DUT, specifically, $root.tb.unit1 and

$root.tb.unit2, but leaves coverage unaffected in all other instances.

$coverage_control(‘SV_COV_RESET, ‘SV_COV_TOGGLE, ‘SV_COV_MODULE,

$root.tb.unit1)

resets coverage of only the instance $root.tb.unit1, leaving all other instances unaffected.

$coverage_control(‘SV_COV_STOP, ‘SV_COV_TOGGLE, ‘SV_COV_HIER,

$root.tb.unit1)

resets coverage of the instance $root.tb.unit1 and also reset coverage for all instances below it, specifically

$root.tb.unit1.comp and $root.tb.unit1.ctrl.

$coverage_control(‘SV_COV_START, ‘SV_COV_TOGGLE, ‘SV_COV_HIER, "DUT")

starts coverage on all instances of the module DUT and of all hierarchy(ies) below those instances. In this design, coverage is started for the instances $root.tb.unit1, $root.tb.unit1.comp, $root.tb.unit1.ctrl, $root.tb.unit2, $root.tb.unit2.comp, and $root.tb.unit2.ctrl.

Group

29.2.2 Built-in coverage access system functions

链接
29.2.2 Built-in coverage access system functions


29.2.2.2 $coverage_get_max

链接
29.2.2 Built-in coverage access system functions
SystemVerilog 3.1a语言参考手册
29.2.2.2 $coverage_get_max
29.2.2 Built-in coverage access system functions
Copy Code
$coverage_get_max(coverage_type, scope_def, modules_or_instance)

This function obtains the value representing 100% coverage for the specified coverage type over the specified portion of the hierarchy. This value shall remain constant across the duration of the simulation.

NOTE—This value is proportional to the design size and structure, so it also needs to be constant through multiple independent simulations and compilations of the same design, assuming any compilation options do not modify the coverage support or design structure.

The return value is an integer, with the following meanings.

Copy Code
-2 (‘SV_COV_OVERFLOW)
the value exceeds a number that can be represented as an integer.

-1 (‘SV_COV_ERROR)
an error occurred (typically due to using incorrect arguments).

0 (‘SV_COV_NOCOV)
no coverage is available for that coverage type on that/those hierarchy(ies).

+pos_num
the maximum coverage number (where pos_num > 0), which is the sum of all coverable items of that type over the given hierarchy(ies).

The scope of this function is specified as per $coverage_control (see Section 29.2.2.1).

Group

29.2.2 Built-in coverage access system functions

链接
29.2.2 Built-in coverage access system functions


29.2.2.3 $coverage_get

链接
29.2.2 Built-in coverage access system functions
SystemVerilog 3.1a语言参考手册
29.2.2.3 $coverage_get
29.2.2 Built-in coverage access system functions
Copy Code
$coverage_get(coverage_type, scope_def, modules_or_instance)

This function obtains the current coverage value for the given coverage type over the given portion of the hierarchy. This number can be converted to a coverage percentage by use of the equation:

The return value follows the same pattern as $coverage_get_max (see Section 29.2.2.2), but with pos_num representing the current coverage level, i.e., the number of the coverable items that have been covered in this/these hierarchy(ies).

The scope of this function is specified as per $coverage_control (see Section 29.2.2.1).

The return value is an integer, with the following meanings.

Copy Code
-2 (‘SV_COV_OVERFLOW)
the value exceeds a number that can be represented as an integer.

-1 (‘SV_COV_ERROR)
an error occurred (typically due to using incorrect arguments).

0 (‘SV_COV_NOCOV)
no coverage is available for that coverage type on that/those hierarchy(ies).

+pos_num
the maximum coverage number (where pos_num > 0), which is the sum of all coverable
items of that type over the given hierarchy(ies).
Group

29.2.2 Built-in coverage access system functions

链接
29.2.2 Built-in coverage access system functions


29.2.2.4 $coverage_merge

链接
29.2.2 Built-in coverage access system functions
SystemVerilog 3.1a语言参考手册
29.2.2.4 $coverage_merge
29.2.2 Built-in coverage access system functions
Copy Code
$coverage_merge(coverage_type, "name")

This function loads and merges coverage data for the specified coverage into the simulator. name is an arbitrary string used by the tool, in an implementation-specific way, to locate the appropriate coverage database, i.e., tools are allowed to store coverage files any place they want with any extension they want as long as the user can retrieve the information by asking for a specific saved name from that coverage database. If name does not exist or does not correspond to a coverage database from the same design, an error shall occur. If an error occurs during loading, the coverage numbers generated by this simulation might not be meaningful.

The return values from this function are:

Copy Code
‘SV_COV_OK
the coverage data has been found and merged.

‘SV_COV_NOCOV
the coverage data has been found, but did not contain the coverage type requested.

‘SV_COV_ERROR
the coverage data was not found or it did not correspond to this design, or another
error.
Group

29.2.2 Built-in coverage access system functions

链接
29.2.2 Built-in coverage access system functions


29.2.2.5 $coverage_save

链接
29.2.2 Built-in coverage access system functions
SystemVerilog 3.1a语言参考手册
29.2.2.5 $coverage_save
29.2.2 Built-in coverage access system functions
Copy Code
$coverage_save(coverage_type, "name")

This function saves the current state of coverage to the tool’s coverage database and associates it with the given name. This name will be mapped in an implementation-specific way into some file or set of files in the coverage database. Data saved to the database shall be retrieved later by using $coverage_merge and supplying the same name. Saving coverage shall not have any effect on the state of coverage in this simulation.

The return values from this function are:

Copy Code
‘SV_COV_OK
the coverage data was successfully saved.

‘SV_COV_NOCOV
no such coverage is available in this design (nothing was saved).

‘SV_COV_ERROR
some error occurred during the save. If an error occurs, the tool shall automatically
remove the coverage database entry for name to preserve the coverage database
integrity. It is not an error to overwrite a previously existing name.

NOTES

  1. The coverage database format is implementation-dependent.
  2. Mapping of names to actual directories/files is implementation-dependent. There is no requirement that a coverage name map to any specific set of files or directories.

Group

29.2.2 Built-in coverage access system functions

链接
29.2.2 Built-in coverage access system functions


29.3 FSM recognition

链接
第二十九章 SystemVerilog覆盖API, 主题
SystemVerilog 3.1a语言参考手册
29.3 FSM recognition
第二十九章 SystemVerilog覆盖API | 主题

Coverage tools need to have automatic recognition of many of the common FSM coding idioms in Verilog/ SystemVerilog. This standard does not attempt to describe or require any specific automatic FSM recognition mechanisms. However, the standard does prescribe a means by which non-automatic FSM extraction occurs. The presence of any of these standard FSM description additions shall override the tool’s default extraction mechanism.

Identification of an FSM consists of identifying the following items:

  1. the state register (or expression)
  2. the next state register (this is optional)
  3. the legal states.

Group

第二十九章 SystemVerilog覆盖API

主题
主题 | 描述
29.3.1 Specifying the signal that holds the current state | Use the following pragma to identify the vector signal that holds the current state of the FSM:
29.3.2 Specifying the part-select that holds the current state | A part-select of a vector signal can be used to hold the current state of the FSM. When a coverage tool displays or reports FSM coverage data, it names the FSM after the signal that holds the current state. If a part-select holds the current state in the user’s FSM, the user needs to also specify a name for the FSM for the coverage tool to use. The FSM name is not the same as the enumeration name. Specify the part-select by using the following pragma:
29.3.3 Specifying the concatenation that holds the current state | Like specifying a part-select, a concatenation of signals can be specified to hold the current state (when including an FSM name and an enumeration name):
29.3.4 Specifying the signal that holds the next state | The signal that holds the next state of the FSM can also be specified with the pragma that specifies the enumeration name:
29.3.5 Specifying the current and next state signals in the same declaration | The tool assumes the first signal following the pragma holds the current state and the next signal holds the next state when a pragma is used for specifying the enumeration name in a declaration of multiple signals, e.g.,
29.3.6 Specifying the possible states of the FSM | The possible states of the FSM can also be specified with a pragma that includes the enumeration name:
29.3.7 Pragmas in one-line comments | These pragmas work in both block comments, between the /* and */ character strings, and one-line comments, following the // character string, e.g.,
29.3.8 Example | Example 29-2 — FSM specified with pragmas
链接
第二十九章 SystemVerilog覆盖API, 主题


29.3.1 Specifying the signal that holds the current state

链接
29.3 FSM recognition
SystemVerilog 3.1a语言参考手册
29.3.1 Specifying the signal that holds the current state
29.3 FSM recognition

Use the following pragma to identify the vector signal that holds the current state of the FSM:

Copy Code
/* tool state_vector signal_name */

where tool and state_vector are required keywords. This pragma needs to be specified inside the module definition where the signal is declared.

Another pragma is also required, to specify an enumeration name for the FSM. This enumeration name is also specified for the next state and any possible states, associating them with each other as part of the same FSM.

There are two ways to do this:

  • Use the same pragma:

Copy Code
/* tool state_vector signal_name enum enumeration_name */

  • Use a separate pragma in the signal’s declaration:

Copy Code
/* tool state_vector signal_name */
reg [7:0] /* tool enum enumeration_name */ signal_name;

In either case, enum is a required keyword; if using a separate pragma, tool is also a required keyword and the pragma needs to be specified immediately after the bit-range of the signal.

Group

29.3 FSM recognition

链接
29.3 FSM recognition


29.3.2 Specifying the part-select that holds the current state

链接
29.3 FSM recognition
SystemVerilog 3.1a语言参考手册
29.3.2 Specifying the part-select that holds the current state
29.3 FSM recognition

A part-select of a vector signal can be used to hold the current state of the FSM. When a coverage tool displays or reports FSM coverage data, it names the FSM after the signal that holds the current state. If a part-select holds the current state in the user’s FSM, the user needs to also specify a name for the FSM for the coverage tool to use. The FSM name is not the same as the enumeration name.

Specify the part-select by using the following pragma:

Copy Code
/* tool state_vector signal_name[n:n] FSM_name enum enumeration_name */
Group

29.3 FSM recognition

链接
29.3 FSM recognition


29.3.3 Specifying the concatenation that holds the current state

链接
29.3 FSM recognition
SystemVerilog 3.1a语言参考手册
29.3.3 Specifying the concatenation that holds the current state
29.3 FSM recognition

Like specifying a part-select, a concatenation of signals can be specified to hold the current state (when including an FSM name and an enumeration name):

Copy Code
/* tool state_vector {signal_name , signal_name, ...} FSM_name enum
enumeration_name */

The concatenation is composed of all the signals specified. Bit-selects or part-selects of signals cannot be used in the concatenation.

Group

29.3 FSM recognition

链接
29.3 FSM recognition


29.3.4 Specifying the signal that holds the next state

链接
29.3 FSM recognition
SystemVerilog 3.1a语言参考手册
29.3.4 Specifying the signal that holds the next state
29.3 FSM recognition

The signal that holds the next state of the FSM can also be specified with the pragma that specifies the enumeration name:

Copy Code
reg [7:0] /* tool enum enumeration_name */
signal_name

This pragma can be omitted if, and only if, the FSM does not have a signal for the next state.

Group

29.3 FSM recognition

链接
29.3 FSM recognition


29.3.5 Specifying the current and next state signals in the same declaration

链接
29.3 FSM recognition
SystemVerilog 3.1a语言参考手册
29.3.5 Specifying the current and next state signals in the same declaration
29.3 FSM recognition

The tool assumes the first signal following the pragma holds the current state and the next signal holds the next state when a pragma is used for specifying the enumeration name in a declaration of multiple signals, e.g.,

Copy Code
/* tool state_vector cs */
reg [1:0] /* tool enum myFSM */ cs, ns, nonstate;

In this example, the tool assumes signal cs holds the current state and signal ns holds the next state. It assumes nothing about signal nonstate.

Group

29.3 FSM recognition

链接
29.3 FSM recognition


29.3.6 Specifying the possible states of the FSM

链接
29.3 FSM recognition
SystemVerilog 3.1a语言参考手册
29.3.6 Specifying the possible states of the FSM
29.3 FSM recognition

The possible states of the FSM can also be specified with a pragma that includes the enumeration name:

Copy Code
parameter /* tool enum enumeration_name */
S0 = 0,
s1 = 1,
s2 = 2,
s3 = 3;

Put this pragma immediately after the keyword parameter, unless a bit-width for the parameters is used, in which case, specify the pragma immediately after the bit-width:

Copy Code
parameter [1:0] /* tool enum enumeration_name */
S0 = 0,
s1 = 1,
s2 = 2,
s3 = 3;
Group

29.3 FSM recognition

链接
29.3 FSM recognition


29.3.7 Pragmas in one-line comments

链接
29.3 FSM recognition
SystemVerilog 3.1a语言参考手册
29.3.7 Pragmas in one-line comments
29.3 FSM recognition

These pragmas work in both block comments, between the /* and */ character strings, and one-line comments, following the // character string, e.g.,

Copy Code
parameter [1:0] // tool enum enumeration_name
S0 = 0,
s1 = 1,
s2 = 2,
s3 = 3;
Group

29.3 FSM recognition

链接
29.3 FSM recognition


29.3.8 Example

链接
29.3 FSM recognition
SystemVerilog 3.1a语言参考手册
29.3.8 Example
29.3 FSM recognition

Example 29-2 — FSM specified with pragmas

Group

29.3 FSM recognition

链接
29.3 FSM recognition


29.4 VPI coverage extensions

链接
第二十九章 SystemVerilog覆盖API, 主题
SystemVerilog 3.1a语言参考手册
29.4 VPI coverage extensions
第二十九章 SystemVerilog覆盖API | 主题
Group

第二十九章 SystemVerilog覆盖API

主题
主题 | 描述
29.4.1 VPI entity/relation diagrams related to coverage |
29.4.2 Extensions to VPI enumerations | — Coverage control
29.4.3 Obtaining coverage information | To obtain coverage information, the vpi_get() function is extended with additional VPI properties that can be obtained from existing handles:
29.4.4 Controlling coverage |
链接
第二十九章 SystemVerilog覆盖API, 主题


29.4.1 VPI entity/relation diagrams related to coverage

链接
29.4 VPI coverage extensions
SystemVerilog 3.1a语言参考手册
29.4.1 VPI entity/relation diagrams related to coverage
29.4 VPI coverage extensions
Group

29.4 VPI coverage extensions

链接
29.4 VPI coverage extensions


29.4.2 Extensions to VPI enumerations

链接
29.4 VPI coverage extensions
SystemVerilog 3.1a语言参考手册
29.4.2 Extensions to VPI enumerations
29.4 VPI coverage extensions

— Coverage control

Copy Code
#define vpiCoverageStart
#define vpiCoverageStop
#define vpiCoverageReset
#define vpiCoverageCheck
#define vpiCoverageMerge
#define vpiCoverageSave

— VPI properties

1) Coverage type properties

Copy Code
#define vpiAssertCoverage
#define vpiFsmStateCoverage
#define vpiStatementCoverage
#define vpiToggleCoverage

2) Coverage status properties

Copy Code
#define vpiCovered
#define vpiCoverMax
#define vpiCoveredCount

3) Assertion-specific coverage status properties

Copy Code
#define vpiAssertAttemptCovered
#define vpiAssertSuccessCovered
#define vpiAssertFailureCovered

4) FSM-specific methods

Copy Code
#define vpiFsmStates
#define vpiFsmStateExpression

— FSM handle types (vpi types)

Copy Code
#define vpiFsm
#define vpiFsmHandle
Group

29.4 VPI coverage extensions

链接
29.4 VPI coverage extensions


29.4.3 Obtaining coverage information

链接
29.4 VPI coverage extensions
SystemVerilog 3.1a语言参考手册
29.4.3 Obtaining coverage information
29.4 VPI coverage extensions

To obtain coverage information, the vpi_get() function is extended with additional VPI properties that can be obtained from existing handles:

Copy Code
vpi_get(<coverageType>, instance_handle)

Returns the number of covered items of the given coverage type in the given instance. Coverage type is one of the coverage type properties described in Section 29.4.2. For example, given coverage type vpiStatement- Coverage, this call would return the number of covered statements in the instance pointed by instance_handle.

Copy Code
vpi_get(vpiCovered, assertion_handle)
vpi_get(vpiCovered, statement_handle)
vpi_get(vpiCovered, signal_handle)
vpi_get(vpiCovered, fsm_handle)
vpi_get(vpiCovered, fsm_state_handle)

Returns whether the item referenced by the handle has been covered. For handles that can contain multiple coverable entities, such as statement, fsm and signal handles, the return value indicates how many of the entities have been covered.

— For assertion handle, the coverable entities are assertions

— For statement handle, the entities are statements

— For signal handle, the entities are individual signal bits

— For fsm handle, the entities are fsm states

For assertions, vpiCovered implies that the assertion has been attempted, has succeeded at least once and has never failed. More detailed coverage information can be obtained for assertions by the following queries:

Copy Code
vpi_get(vpiAssertAttemptCovered, assertion_handle)

Returns the number of times the assertion has been attempted.

Copy Code
vpi_get(vpiAssertSuccessCovered, assertion_handle)

Returns the number of times the assertion has succeeded non-vacuously or, if assertion handle corresponds to a cover sequence, the number of times the sequence has been matched. Refer to Section 17.11.1 and 17.13 for the definition of vacuity.

Copy Code
vpi_get(vpiAssertVacuousSuccessCovered, assertion_handle)

Returns the number of times the assertion has succeeded vacuously. Refer to Section 17.11.1 and 17.13 for the definition of vacuity.

Copy Code
vpi_get(vpiAssertFailureCovered, assertion_handle)

Returns the number of times the assertion has failed. For any assertion, the number of attempts that have not yet reached any conclusion (success or failure) can be derived from the formula:

Copy Code
in progress = attempts - (successes + vacuous success + failures)

The example below illustrates some of these queries:

Copy Code
module covtest;
    bit on = 1, off = 0;
    logic clk;

    initial begin
        clk = 0;
        forever begin
            #10;
            clk = ~clk;
        end
    end

    always @(false) begin
        anvr: assert(on ##1 on); // assertion will not be attempted
    end

    always @(posedge clk) begin
        aundf: assert (on ##[1:$] off); // assertion will not pass or fail
        afail: assert (on ##1 off); // assertion will always fail on 2nd tick
        apass: assert (on ##1 on); // assertion will succeed on each attempt
    end
endmodule

For this example, the assertions will have the following coverage results:

Table 29-3: Assertion coverage results

 | vpiCovered | vpiAssertAttempt- Covered | vpiAssertSuccess- Covered | vpiAssertFailure- Covered
anvr | false | false | false | false
aundf | false | true | false | false
afail | false | true | false | true
apass | true | true | true | false

The number of times an item has been covered can be obtained by the vpiCoveredCount property:

Copy Code
vpi_get(vpiCoveredCount, assertion_handle)
vpi_get(vpiCoveredCount, statement_handle)
vpi_get(vpiCoveredCount, signal_handle)
vpi_get(vpiCoveredCount, fsm_handle)
vpi_get(vpiCoveredCount, fsm_state_handle)

Returns the number of times each coverable entity referred by the handle has been covered. Note that this is only easily interpretable when the handle points to a unique coverable item (such as an individual statement); when handle points to an item containing multiple coverable entities (such as a handle to a block statement containing a number of statements), the result is the sum of coverage counts for each of the constituent entities.

Copy Code
vpi_get(vpiCoveredMax, assertion_handle)
vpi_get(vpiCoveredMax, statement_handle)
vpi_get(vpiCoveredMax, signal_handle)
vpi_get(vpiCoveredMax, fsm_handle)
vpi_get(vpiCoveredMax, fsm_state_handle)

Returns the number of coverable entities pointed by the handle. Note that this shall always return 1 (one) when applied to an assertion or FSM state handle.

Copy Code
vpi_iterate(vpiFsm, instance-handle)

Returns an iterator to all FSMs in an instance.

Copy Code
vpi_handle(vpiFsmStateExpression, fsm-handle)

Returns the handle to the signal or expression encoding the FSM state.

Copy Code
vpi_iterate(vpiFsmStates, fsm-handle)

Returns an iterator to all states of an FSM.

Copy Code
vpi_get_value(fsm_state_handle, state-handle)

Returns the value of an FSM state.

Group

29.4 VPI coverage extensions

链接
29.4 VPI coverage extensions


29.4.4 Controlling coverage

链接
29.4 VPI coverage extensions
SystemVerilog 3.1a语言参考手册
29.4.4 Controlling coverage
29.4 VPI coverage extensions
Copy Code
vpi_control(<coverageControl>, <coverageType>, instance_handle)
vpi_control(<coverageControl>, <coverageType>, assertion_handle)

Controls the collection of coverage on the given instance or assertion. Note that statement, toggle and FSM coverage are not individually controllable (i.e., they are controllable only at the instance level and not on a per statement/signal/FSM basis). The semantics and behavior are as per the $coverage_control system function (see Section 29.2.2.1). coverageControl is one vpiCoverageStart, vpiCoverageStop, vpiCoverageReset or vpiCoverageCheck, as defined in Section 29.4.2. coverageType is any one of the VPI coverage type properties (Section 29.4.2)

Copy Code
vpi_control(<coverageControl>, <coverageType>, name)

This saves or merges coverage into the current simulation. The semantics and behavior are specified as per the equivalent system functions $coverage_merge (see Section 29.2.2.4) and $coverage_save (see Section 29.2.2.5). coverageControl is one of vpiCoverageMerge or vpiCoverageSave, defined in Section 29.4.2.

Group

29.4 VPI coverage extensions

链接
29.4 VPI coverage extensions


第三十章 SystemVerilog数据读API

链接
主题
SystemVerilog 3.1a语言参考手册
第三十章 SystemVerilog数据读API
主题
主题
主题
描述
30.1 简介（一般信息）
This chapter extends the SystemVerilog VPI with read facilities so that the Verilog Procedural Interface (VPI) acts as an Application Programming Interface (API) for data access and tool interaction irrespective of whether the data is in memory or a persistent form such as a database, and also irrespective of the tool the user is interacting with.

SystemVerilog is both a design and verification language consequently its VPI has a wealth of design and verification data access mechanisms. This makes the VPI an ideal vehicle for tool integration in order to replace arcane, inefficient, and error-prone file-based data exchanges with a... more
30.2 需求
SystemVerilog adds several design and verification constructs including:
  • C data types such as int, struct, union, and enum.
  • Advanced built-in data types such as string.
  • User defined data types and corresponding methods.
  • Data types and facilities that enhance the creation and functionality of testbenches.
The access API shall be implemented by all tools as a minimal set for a standard means for user-tool or tooltool interaction that involves SystemVerilog object data querying (reading). In other words, there is no need for a simulator to be running for this API to be in effect; it is a set of API routines... more
30.3 Extensions to VPI enumerations
These extensions shall be appended to the contents of the vpi_user.h file, described in IEEE Std. 1364- 2001, Annex G. The numbers in the range 800 - 899 are reserved for the read data access portion of the VPI.
30.4 VPI object type additions
30.5 Object model diagrams
A traverse object of type vpiTrvsObj is related to its parent object; it is a means to access the value data of said object. An object can have several traverse objects each pointing and moving in a different way along the value data horizon. This is shown graphically in the model diagram below. The traversable class is a representational grouping consisting of any object that:
  • Has a name
  • Can take on a value accessible with vpi_get_value(), the value must be variable over time (i.e. necessitates creation of a traverse object to access the value over time).
The class includes nets,... more
30.6 Usage extensions to VPI routines
Several VPI routines, that have existed before SystemVerilog, have been extended in usage with the addition of new object types and/or properties. While the extensions are fairly obvious, they are emphasized here again to turn the reader’s attention to the extended usage.

Table 30-1: Usage extensions to Verilog 2001 VPI routines

30.7 VPI routines added in SystemVerilog
This section lists all the VPI routines added in SystemVerilog.

Table 30-2: VPI routines

Table 30-3: Reader VPI routines

30.8 Reading data
Reading data is performed in 3 steps:
  1. A design object must be selected for traverse access from a database (or from memory).
  2. Indicate the intent to access data. This is typically done by a vpi_load_init() call as a hint from the user to the tool on which areas of the design are going to be accessed. The tool shall then load the data in an invisible fashion to the user (for example, either right after the call, or at traverse handle creation, or usage). Alternatively, if the user wishes he can (also) choose to add a specific vpi_load() call (this... more
30.9 Optionally unloading the data
The implementation tool should handle unloading the unused data in a fashion invisible to the user. Managing the data caching and memory hierarchy is left to tool implementation but it should be noted that failure to unload can affect the tool performance and capacity.

The user can optionally choose to call vpi_unload() to unload the data from (active) memory if the user application is done with accessing the data.

Calling vpi_unload() before releasing (freeing) traverse (collection) handles that are manipulating the data using vpi_free_object() is not recommended practice by users; the behavior of traversal using existing handles is not defined... more
30.10 Reading data from multiple databases and/or different read library providers
The VPI routine vpi_load_extension() is used to load VPI extensions. Such extensions include reader libraries from such tools as waveform viewers. vpi_load_extension() shall return a pointer to a function pointer structure with the following definition.
30.11 VPI routines extended in SystemVerilog
Table 30-1 lists the usage extensions. They are repeated here the additional extended usage with traverse (collection) handles of vpi_get_time() for clarity.
30.12 VPI routines added in SystemVerilog
This section describes the additional VPI routines in detail.
链接
主题


30.1 简介（一般信息）

链接
第三十章 SystemVerilog数据读API
SystemVerilog 3.1a语言参考手册
30.1 简介（一般信息）
第三十章 SystemVerilog数据读API

This chapter extends the SystemVerilog VPI with read facilities so that the Verilog Procedural Interface (VPI) acts as an Application Programming Interface (API) for data access and tool interaction irrespective of whether the data is in memory or a persistent form such as a database, and also irrespective of the tool the user is interacting with.

SystemVerilog is both a design and verification language consequently its VPI has a wealth of design and verification data access mechanisms. This makes the VPI an ideal vehicle for tool integration in order to replace arcane, inefficient, and error-prone file-based data exchanges with a new mechanism for tool to tool, and user to tool interface. Moreover, a single access API eases the interoperability investments for vendors and users alike. Reducing interoperability barriers allows vendors to focus on tool implementation. Users, on the other hand, are able to create integrated design flows from a multitude of best-in-class offerings spanning the realms of design and verification such as simulators, debuggers, formal, coverage or test bench tools.

Group

第三十章 SystemVerilog数据读API

链接
第三十章 SystemVerilog数据读API


30.2 需求

链接
第三十章 SystemVerilog数据读API
SystemVerilog 3.1a语言参考手册
30.2 需求
第三十章 SystemVerilog数据读API

SystemVerilog adds several design and verification constructs including:

  • C data types such as int, struct, union, and enum.
  • Advanced built-in data types such as string.
  • User defined data types and corresponding methods.
  • Data types and facilities that enhance the creation and functionality of testbenches.
The access API shall be implemented by all tools as a minimal set for a standard means for user-tool or tooltool interaction that involves SystemVerilog object data querying (reading). In other words, there is no need for a simulator to be running for this API to be in effect; it is a set of API routines that can be used for any interaction for example between a user and a waveform tool to read the data stored in its database. This usage flow is shown in the figure below.

Figure 30-2 — Data read VPI usage model

The focus in the API is the user view of access. While the API does provide varied facilities to give the user the ability to effectively architect his or her application, it does not address the tool level efficiency concerns such as time-based incremental load of the data, and/or predicting or learning the user access. It is left up to implementers to make this as easy and seamless as possible on the user. To make this easy on tools, the API provides an initialization routine where the user specifies access type and design scope. The user should be primarily concerned with the API specified here, and efficiency issues are dealt with behind the scenes.

Group

第三十章 SystemVerilog数据读API

链接
第三十章 SystemVerilog数据读API


30.3 Extensions to VPI enumerations

链接
第三十章 SystemVerilog数据读API, 主题
SystemVerilog 3.1a语言参考手册
30.3 Extensions to VPI enumerations
第三十章 SystemVerilog数据读API | 主题

These extensions shall be appended to the contents of the vpi_user.h file, described in IEEE Std. 1364- 2001, Annex G. The numbers in the range 800 - 899 are reserved for the read data access portion of the VPI.

Group

第三十章 SystemVerilog数据读API

主题
主题 | 描述
30.3.1 Object types | All objects in VPI have a vpiType. This API adds a new object type for data traversal, and two other objects types for object collection and traverse object collection.
30.3.2 Object properties | This section lists the object property VPI calls.
30.3.3 System callbacks | The access API adds no new system callbacks. The reader routines (methods) can be called whenever the user application has control and wishes to access data.
链接
第三十章 SystemVerilog数据读API, 主题


30.3.1 Object types

链接
30.3 Extensions to VPI enumerations
SystemVerilog 3.1a语言参考手册
30.3.1 Object types
30.3 Extensions to VPI enumerations

All objects in VPI have a vpiType. This API adds a new object type for data traversal, and two other objects types for object collection and traverse object collection.

Copy Code
/* vpiHandle type for the data traverse object */
#define vpiTrvsObj 800 /* use in vpi_handle() */
#define vpiCollection 810 /* Collection of VPI handles */
#define vpiObjCollection 811 /* Collection of traversable
design objs */
#define vpiTrvsCollection 812 /* Collection of vpiTrvsObj’s */

The other object types that this API references, for example to get a value at a specific time, are all the valid types in the VPI that can be used as arguments in the VPI routines for logic and strength value processing such as vpi_get_value(<object_handle>, <value_pointer>). These types include:

  • Constants
  • Nets and net arrays
  • Regs and reg arrays
  • Variables
  • Memory
  • Parameters
  • Primitives
  • Assertions
In other words, any limitation in vpiType of vpi_get_value() shall also be reflected in this data access API.

Group

30.3 Extensions to VPI enumerations

链接
30.3 Extensions to VPI enumerations


30.3.2 Object properties

链接
30.3 Extensions to VPI enumerations, 主题
SystemVerilog 3.1a语言参考手册
30.3.2 Object properties
30.3 Extensions to VPI enumerations | 主题

This section lists the object property VPI calls.

Group

30.3 Extensions to VPI enumerations

主题
主题 | 描述
30.3.2.1 Static info |
30.3.2.2 Dynamic info |
链接
30.3 Extensions to VPI enumerations, 主题


30.3.2.1 Static info

链接
30.3.2 Object properties
SystemVerilog 3.1a语言参考手册
30.3.2.1 Static info
30.3.2 Object properties
Copy Code
/* Check */
/* use in vpi_get() */
#define vpiIsLoaded                 820 /* is loaded */
#define vpiHasDataVC                821 /* has at least one VC
                                           at some point in time
                                                in the database */
#define vpiHasVC                    822 /* has VC at specific
                                                          time */
#define vpiHasNoValue               823 /* has no value at
                                                 specific time */
#define vpiBelong                   824 /* belong to extension */
/* Access */
#define vpiAccessLimitedInteractive 830 /* interactive */
#define vpiAccessInteractive        831 /* interactive: history */
#define vpiAccessPostProcess        832 /* database */
/* Member of a collection */
#define vpiMember                   840 /* use in vpi_iterate() */
/* Iteration on instances for loaded */
#define vpiDataLoaded               850 /* use in vpi_iterate() */
Group

30.3.2 Object properties

链接
30.3.2 Object properties


30.3.2.2 Dynamic info

链接
30.3.2 Object properties, 主题
SystemVerilog 3.1a语言参考手册
30.3.2.2 Dynamic info
30.3.2 Object properties | 主题
Group

30.3.2 Object properties

主题
主题 | 描述
30.3.2.2.1 Control constants |
链接
30.3.2 Object properties, 主题


30.3.2.2.1 Control constants

链接
30.3.2.2 Dynamic info
SystemVerilog 3.1a语言参考手册
30.3.2.2.1 Control constants
30.3.2.2 Dynamic info
Copy Code
/* Control Traverse: use in vpi_goto() for a vpiTrvsObj type */
#define vpiMinTime 860 /* min time */
#define vpiMaxTime 864 /* max time */
#define vpiPrevVC 868
#define vpiNextVC 870
#define vpiTime 874 /* time jump */

These properties can also be used in vpi_get_time() to enhance the access efficiency. The routine vpi_get_time() with a traverse handle argument is extended with the additional ability to get the min, max, previous VC, and next VC times of the traverse handle; not just the current time of the handle. These same control constants can then be used for both access and for moving the traverse handle where the context (get or go to) can distinguish the intent.

Group

30.3.2.2 Dynamic info

链接
30.3.2.2 Dynamic info


30.3.3 System callbacks

链接
30.3 Extensions to VPI enumerations
SystemVerilog 3.1a语言参考手册
30.3.3 System callbacks
30.3 Extensions to VPI enumerations

The access API adds no new system callbacks. The reader routines (methods) can be called whenever the user application has control and wishes to access data.

Group

30.3 Extensions to VPI enumerations

链接
30.3 Extensions to VPI enumerations


30.4 VPI object type additions

链接
第三十章 SystemVerilog数据读API, 主题
SystemVerilog 3.1a语言参考手册
30.4 VPI object type additions
第三十章 SystemVerilog数据读API | 主题
Group

第三十章 SystemVerilog数据读API

主题
主题
描述
30.4.1 Traverse object
To access the value changes of an object over time, the notion of a Value Change (VC) traverse handle is added. A value change traverse object is used to traverse and access value changes not just for the current value (as calling vpi_get_time() or vpi_get_value() on the object handle would) but for any point in time: past, present, or future. To create a value change traverse handle the routine vpi_handle() is called with a vpiTrvsObj vpiType:
30.4.2 VPI collection
In order to read data efficiently, it can be necessary to specify a group of objects. For example, when traversing data a user might wish to specify a list of objects to be marked as targets of data traversal. To do this grouping requires the notion of a collection. A collection represents a user-defined collection of VPI handles. The collection is an ordered list of VPI handles. The vpiType of a collection handle can be vpiCollection, vpi-ObjCollection, or vpiTrvsCollection:
  • A collection of type vpiCollection is a general collection of VPI handles of objects of any type.
  • The collection object of... more
链接
第三十章 SystemVerilog数据读API, 主题


30.4.1 Traverse object

链接
30.4 VPI object type additions
SystemVerilog 3.1a语言参考手册
30.4.1 Traverse object
30.4 VPI object type additions

To access the value changes of an object over time, the notion of a Value Change (VC) traverse handle is added. A value change traverse object is used to traverse and access value changes not just for the current value (as calling vpi_get_time() or vpi_get_value() on the object handle would) but for any point in time: past, present, or future. To create a value change traverse handle the routine vpi_handle() is called with a vpiTrvsObj vpiType:

Copy Code
vpiHandle object_handle; /* design object */
vpiHandle trvsHndl = vpi_handle(/*vpiType*/vpiTrvsObj,
/*vpiHandle*/ object_handle);

A traverse object exists from the time it is created until its handle is released. It is the application’s responsibility to keep a handle to the created traverse object, and to release it when it is no longer needed.

Group

30.4 VPI object type additions

链接
30.4 VPI object type additions


30.4.2 VPI collection

链接
30.4 VPI object type additions, 主题
SystemVerilog 3.1a语言参考手册
30.4.2 VPI collection
30.4 VPI object type additions | 主题

In order to read data efficiently, it can be necessary to specify a group of objects. For example, when traversing data a user might wish to specify a list of objects to be marked as targets of data traversal. To do this grouping requires the notion of a collection. A collection represents a user-defined collection of VPI handles. The collection is an ordered list of VPI handles. The vpiType of a collection handle can be vpiCollection, vpi-ObjCollection, or vpiTrvsCollection:

  • A collection of type vpiCollection is a general collection of VPI handles of objects of any type.
  • The collection object of type vpiObjCollection represents a collection of VPI traversable objects in the design.
  • A vpiTrvsCollection is a collection of traverse objects of type vpiTrvsObj.
The usage here in the read API is of either:
  • Collections of traversable design objects: Used for example in vpi_handle() to create traverse handles for the collection. A collection of traversable design objects is of type vpiObjCollection (the elements can be any object type in the design except traverse objects of type vpiTrvsObj).
  • Collections of data traverse objects: Used for example in vpi_goto() to move the traverse handles of all the objects in the collection (all are of type vpiTrvsObj). A collection of traverse objects is a vpiTrvsCollection.
The collection contains a set of member VPI objects and can take on an arbitrary size. The collection can be created at any time and existing objects can be added to it. The reader implementation can perform a type check on the items being added to the collection and generate an error if the item added does not belong to the allowed vpiType.

The purpose of a collection is to group design objects and permit operating on each element with a single operation applied to the whole collection group. vpi_iterate(vpiMember, <collection_handle>) is used to create a member iterator. vpi_scan() can then be used to scan the iterator for the elements of the collection.

A collection object is created with vpi_create(). The first call provides NULL handles to the collection object and the object to be added. Following calls, which can be performed at any time, provide the collection handle and a handle to the object for addition. The return argument is a handle to the collection object.

For example:

Copy Code
vpiHandle designCollection;
vpiHandle designObj;
vpiHandle trvsCollection;
vpiHandle trvsObj;
/* Create a collection of design objects */
designCollection = vpi_create(vpiObjCollection, NULL, NULL);
/* Add design object designObj into it */
designCollection = vpi_create(vpiObjCollection, designCollection, designObj);
/* Create a collection of traverse objects*/
trvsCollection = vpi_create(vpiTrvsCollection, NULL, NULL);
/* Add traverse object trvsObj into it */
trvsCollection = vpi_create(vpiTrvsCollection, trvsCollection, trvsObj);

Sometimes it is necessary to filter a collection and extract a set of handles which meet, or do not meet, a specific criterion for a given collection. The function vpi_filter() can be used for this purpose in the form of:

Copy Code
vpiHandle colFilterHdl = vpi_filter((vpiHandle) colHdl, (PLI_INT32)
filterType, (PLI_INT32) flag);

The first argument of vpi_filter(), colHdl, shall be the collection on which to apply the filter operation. The second argument, filterType can be any vpiType or VPI boolean property. This argument is the criterion used for filtering the collection members. The third argument, flag, is a boolean value. If set to TRUE, vpi_filter() shall return a collection of handles which match the criterion indicated by filterType, if set to FALSE, vpi_filter() shall return a collection of handles which do not match the criterion indicated by filterType. The original collection passed as a first argument remains unchanged.

A collection object exists from the time it is created until its handle is released. It is the application’s responsibility to keep a handle to the created collection, and to release it when it is no longer needed.

Group

30.4 VPI object type additions

主题
主题 | 描述
30.4.2.1 Operations on collections | A traverse collection can be obtained (i.e. created) from a design collection using vpi_handle(). The call would take on the form of:
链接
30.4 VPI object type additions, 主题


30.4.2.1 Operations on collections

链接
30.4.2 VPI collection
SystemVerilog 3.1a语言参考手册
30.4.2.1 Operations on collections
30.4.2 VPI collection

A traverse collection can be obtained (i.e. created) from a design collection using vpi_handle(). The call would take on the form of:

Copy Code
vpiHandle objCollection;
/* Obtain a traverse collection from the object collection */
vpi_handle(vpiTrvsCollection, objCollection);

The usage of this capability is discussed in Section 30.8.7.

Another optional method is defined, which is used in the case the user wishes to directly control the data load, for loading data of objects in a collection: vpi_load(). This operation loads all the objects in the collection. It is equivalent to performing a vpi_load() on every single handle of the object elements in the collection.

A traversal method is also defined on collections of traverse handles; i.e. collections of type vpiTrvsCollection. The method is vpi_goto().

Group

30.4.2 VPI collection

链接
30.4.2 VPI collection


30.5 Object model diagrams

链接
第三十章 SystemVerilog数据读API
SystemVerilog 3.1a语言参考手册
30.5 Object model diagrams
第三十章 SystemVerilog数据读API

A traverse object of type vpiTrvsObj is related to its parent object; it is a means to access the value data of said object. An object can have several traverse objects each pointing and moving in a different way along the value data horizon. This is shown graphically in the model diagram below. The traversable class is a representational grouping consisting of any object that:

  • Has a name
  • Can take on a value accessible with vpi_get_value(), the value must be variable over time (i.e. necessitates creation of a traverse object to access the value over time).
The class includes nets, net arrays, regs, reg arrays, variables, memory, primitive, primitive arrays, concurrent assertions, and parameters. It also includes part selects of all the design object types that can have part selects.

Figure 30-3 — Model diagram of traverse object

A collection object of type vpiObjCollection groups together a set of design objects Obj (of any type). A traverse collection object of type vpiTrvsCollection groups together a set of traverse objects trvsObj of type vpiTrvsObj.

Figure 30-4 — Model diagram of collection

Group

第三十章 SystemVerilog数据读API

链接
第三十章 SystemVerilog数据读API


30.6 Usage extensions to VPI routines

链接
第三十章 SystemVerilog数据读API
SystemVerilog 3.1a语言参考手册
30.6 Usage extensions to VPI routines
第三十章 SystemVerilog数据读API

Several VPI routines, that have existed before SystemVerilog, have been extended in usage with the addition of new object types and/or properties. While the extensions are fairly obvious, they are emphasized here again to turn the reader’s attention to the extended usage.

Table 30-1: Usage extensions to Verilog 2001 VPI routines

To | Use | New Usage
Get tool’s reader version | vpi_get_vlog_info() | Reader version information
Create an iterator for the loaded objects (using vpi_iterate(vpiData-Loaded, <instance>)). Create an iterator for (object or traverse) collections using vpi_iterate(vpiMember, <collection>). | vpi_iterate() | Add iteration types vpiData- Loaded and vpiMember. Extended with collection handle to create a collection member element iterator.
Obtain a traverse (collection) handle from an object (collection) handle | vpi_handle() | Add new types vpiTrvsObj and vpiTrvsCollection. Extended with collection handle (of traversable objects) to create a traverse collection from an object collection.
Obtain a property. | vpi_get() | Extended with the new check properties: vpiIsLoaded , vpiHasDataVC, vpiHasVC, vpiHasNoValue, and vpiBelong.
Get a value. | vpi_get_value() | Use traverse handle as argument to get value where handle points.
Get time traverse (collection) handle points at. | vpi_get_time() | Use traverse (collection) handle as argument to get current time where handle points. Also, get the traverse handle min, max, previous VC time, or next VC time.
Free traverse handle Free (traverse) collection handle. | vpi_free_object() | Use traverse handle as argument Use (traverse) collection handle as argument.
Group

第三十章 SystemVerilog数据读API

链接
第三十章 SystemVerilog数据读API


30.7 VPI routines added in SystemVerilog

链接
第三十章 SystemVerilog数据读API
SystemVerilog 3.1a语言参考手册
30.7 VPI routines added in SystemVerilog
第三十章 SystemVerilog数据读API

This section lists all the VPI routines added in SystemVerilog.

Table 30-2: VPI routines

Table 30-3: Reader VPI routines

Group

第三十章 SystemVerilog数据读API

链接
第三十章 SystemVerilog数据读API


30.8 Reading data

链接
第三十章 SystemVerilog数据读API, 主题
SystemVerilog 3.1a语言参考手册
30.8 Reading data
第三十章 SystemVerilog数据读API | 主题

Reading data is performed in 3 steps:

  1. A design object must be selected for traverse access from a database (or from memory).
  2. Indicate the intent to access data. This is typically done by a vpi_load_init() call as a hint from the user to the tool on which areas of the design are going to be accessed. The tool shall then load the data in an invisible fashion to the user (for example, either right after the call, or at traverse handle creation, or usage). Alternatively, if the user wishes he can (also) choose to add a specific vpi_load() call (this can be done at any point in time) to load, or force the load of, a specific object or collection of objects. This can be done either instead of, or in addition to, the objects in the scope or collection specified in vpi_load_init()). vpi_unload() can be used by the user to force the tool to unload specific objects. It should be noted that traverse handle creation shall fail for unloaded objects or collections.
  3. Once an object is selected, and marked for load, a traverse object handle can be created and used to traverse the design objects’ stored data.
  4. At this point the object is available for reading. The traverse object permits the data value traversal and access.

Group

第三十章 SystemVerilog数据读API

主题
主题 | 描述
30.8.1 VPI read initialization and load access initialization | Selecting an object is done in 3 steps: 1) The first step is to initialize the read access with a call to vpi_load_extension() to load the reader extension and set: a) Name of the reader library to be used specified as a character string. This is either a full pathname to this library or the single filename (without path information) of this library, assuming a vendor specific way of defining the location of such a library. The latter method is more portable and therefore recommended. Neither the full pathname, nor the single filename shall include an extension, the name of... more
30.8.2 Object selection for traverse access | In order to select an object for access, the user must first obtain the object handle. This can be done using the VPI routines (that are supported in the tool being used) for traversing the HDL hierarchy and obtaining an object handle based on the type of object relationship to another (top) handle. Any tool that implements this read API (e.g. waveform tool) shall implement at least a basic subset of the design navigation VPI routines that shall include vpi_handle_by_name() to permit the user to get a vpiHandle from an object name. It is left up to tool implementation to... more
30.8.3 Optionally loading objects | As mentioned earlier, vpi_load_init() allows the tool implementing the reader to load objects in a fashion that is invisible to the user. Optionally, if the user chooses to do their own loading at some point in time, then once the object handle is obtained they can use the VPI data load routine vpi_load() with the object’s vpiHandle to load the data for the specific object onto memory. Alternatively, for efficiency considerations, vpi_load() can be called with a design object collection handle of type vpiObjCollection. The collection must have already been created with vpi_create() and the (additional) selected object handles added... more
30.8.4 Reading an object | The sections above have outlined: — How to select an object for access, in other words, marking this object as a target for access. This is where the design navigation VPI is used. — How to call vpi_load_init() as a hint on the areas to be accessed, and/or optionally load an object into memory after obtaining a handle and then either loading objects individually or as a group using the object collection. — How to optionally iterate the design scope and the object collection to find the loaded objects if needed. In this section reading data is discussed. Reading an... more
30.8.5 Sample code using object (and traverse) collections |
30.8.6 Object-based traversal | Object based traversal can be performed by creating a traverse handle for the object and then moving it back and forth to the next or previous Value Change (VC) or by performing jumps in time. A traverse object handle for any object in the design can be obtained by calling vpi_handle() with a vpiTrvsObj type, and an object vpiHandle. This is the method described in Section 30.8.4, and used in all the code examples thus far. Using this method, the traversal would be object-based because the individual object traverse handles are created, and then the application can query the (value,... more
30.8.7 Time-ordered traversal | Alternatively, a user might wish to do a time-ordered traversal i.e. a time-based examination of values of several objects. This can be done by using a collection. The first step is to create a traverse collection of type vpiTrvsCollection of the objects to be traversed from the design object collection of type vpiObjCollection using vpi_handle() with a vpiTrvsCollection type and collection handle argument. vpi_goto() can then be called on the traverse collection to move to next or previous or do jump in time for the collection as a whole. A move to next (previous) VC means move to the next... more
链接
第三十章 SystemVerilog数据读API, 主题


30.8.1 VPI read initialization and load access initialization

链接
30.8 Reading data
SystemVerilog 3.1a语言参考手册
30.8.1 VPI read initialization and load access initialization
30.8 Reading data

Selecting an object is done in 3 steps:

1) The first step is to initialize the read access with a call to vpi_load_extension() to load the reader extension and set:

a) Name of the reader library to be used specified as a character string. This is either a full pathname to this library or the single filename (without path information) of this library, assuming a vendor specific way of defining the location of such a library. The latter method is more portable and therefore recommended. Neither the full pathname, nor the single filename shall include an extension, the name of the library must be unique and the appropriate extension for the actual platform should be provided by the application loading this library More details are in Section 30.10.

b) Name of the database holding the stored data or flush database in case of vpiAccessPostProcess or vpiAccessInteractive respectively; a NULL can be used in case of vpiAccessLimitedInteractive. This is the logical name of a database, not the name of a file in the file system. It is implementation dependent whether there is any relationship to an actual on-disk object and the provided name. See access mode below for more details on the access modes.

c) Access mode: The following VPI properties set the mode of access

— vpiAccessLimitedInteractive: Means that the access shall be done for the data stored in the tool memory (e.g. simulator), the history (or future) that the tool stores is implementation dependent. If the tool does not store the requested info then the querying routines shall return a fail. The database name argument to vpi_load_extension() in this mode shall be ignored (even if not NULL).

— vpiAccessInteractive: Means that the access shall be done interactively. The tool shall then use the database specified as a “flush” area for its data. This mode is very similar to the vpiAccessLimitedInteractive with the additional requirement that all the past history (before current time) shall be stored (for the specified scope/collection, see the access scope/collection description of vpi_load_init().

— vpiAccessPostProcess: Means that the access shall be done through the specified database. All data queries shall return the data stored in the specified database. Data history depends on what is stored in the database, and can be nothing (i.e. no data).

vpi_load_extension() can be called multiple times for different reader interface libraries (coming from different tools), database specification, and/or read access. A call with vpiAccessInteractive means that the user is querying the data stored inside the simulator database and uses the VPI routines supported by the simulator. A call with vpiAccessPostProcess means that the user is accessing the data stored in the database and uses the VPI services provided by the waveform tool. The application, if accessing several databases and/or using multiple read API libraries, can use the routine vpi_get(vpiBelong, <vpiHandle>) to check whether a handle belongs to that database. The call is performed as follows:

Copy Code
reader_extension_ptr->vpi_get(vpiBelong, <vpiHandle>);

where reader_extension_ptr is the reader library pointer returned by the call to vpi_load_extension(). TRUE is returned if the passed handle belongs to that extension, and FALSE otherwise.

If the application uses the built-in library (i.e. the one provided by the tool it is running under), there is no need to use indirection to call the VPI routines; they can be called directly. An initial call must however be made to set the access mode, specify the database, and check for error indicated by a NULL return.

vpi_close() shall be called in case of:

  • vpiAcessLimitedInteractive to perform any tool cleanup. The validity of VPI handles after this call is left up to the particular reader implementation.
  • vpiAccessPostProcess or vpiAccessInteractive mode to perform any tool cleanup and close the opened database. Handles obtained before the call to vpi_close() are no longer valid after this call.
Multiple databases, possibly in different access modes (for example a simulator database opened in vpi- AccessInteractive and a database opened in vpiAccessPostProcess, or two different databases opened in vpiAccessPostProcess) can be accessed at the same time. Section 30.10 shows an example of how to access multiple databases from multiple read interfaces simultaneously.

2) Next step is to specify the elements that shall be accessed. This is accomplished by calling vpi_load_init() and specifying a scope and/or an item collection. At least one of the two (scope or collection) needs to be specified. If both are specified then the union of all the object elements forms the entire set of objects the user can access.

  • Access scope: The specified scope handle, and nesting mode govern the scope that access returns. Data queries outside this scope (and its sub-scopes as governed by the nesting mode) shall return a fail in the access routines unless the object belongs to access collection described below. It can be used either in a complementary or in an exclusive fashion to access collection. NULL is to be passed to the collection when access scope is used in an exclusive fashion.
  • Access collection: The specified collection stores the traverse object handles to be loaded. It can be used either in a complementary or in an exclusive fashion to access scope. NULL is to be passed to the scope when access collection is used in an exclusive fashion.
vpi_load_init() enables access to the objects stored in the database and can be called multiple times. The load access specification of a call remains valid until the next call is executed. This routine serves to initialize the tool load access and provides an entry point for the tool to perform data access optimizations.

Group

30.8 Reading data

链接
30.8 Reading data


30.8.2 Object selection for traverse access

链接
30.8 Reading data
SystemVerilog 3.1a语言参考手册
30.8.2 Object selection for traverse access
30.8 Reading data

In order to select an object for access, the user must first obtain the object handle. This can be done using the VPI routines (that are supported in the tool being used) for traversing the HDL hierarchy and obtaining an object handle based on the type of object relationship to another (top) handle.

Any tool that implements this read API (e.g. waveform tool) shall implement at least a basic subset of the design navigation VPI routines that shall include vpi_handle_by_name() to permit the user to get a vpiHandle from an object name. It is left up to tool implementation to support additional design navigation relationships. Therefore, if the application wishes to access similar elements from one database to another, it shall use the name of the object, and then call vpi_handle_by_name(), to get the object handle from the relevant database. This level of indirection is always safe to do when switching the database query context, and shall be guaranteed to work.

It should be noted that an object’s vpiHandle depends on the access mode specified in vpi_load_extension() and the database accessed (identified by the returned extension pointer, see Section 30.10). A handle obtained through a post process access mode (vpiAccessPostProcess) from a waveform tool for example is not interchangeable in general with a handle obtained through interactive access mode (vpiAccessLimitedInteractive or vpiAccessInteractive) from a simulator. Also handles obtained through post process access mode of different databases are not interchangeable. This is because objects, their data, and relationships in a stored database could be quite different from those in the simulation model, and those in other databases.

Group

30.8 Reading data

链接
30.8 Reading data


30.8.3 Optionally loading objects

链接
30.8 Reading data, 主题
SystemVerilog 3.1a语言参考手册
30.8.3 Optionally loading objects
30.8 Reading data | 主题

As mentioned earlier, vpi_load_init() allows the tool implementing the reader to load objects in a fashion that is invisible to the user. Optionally, if the user chooses to do their own loading at some point in time, then once the object handle is obtained they can use the VPI data load routine vpi_load() with the object’s vpiHandle to load the data for the specific object onto memory. Alternatively, for efficiency considerations, vpi_load() can be called with a design object collection handle of type vpiObjCollection. The collection must have already been created with vpi_create() and the (additional) selected object handles added to the load collection using vpi_create() with the created collection list passed as argument. The object(s) data is not accessible as of yet to the user’s read queries; a traverse handle must still be created. This is presented in Section 30.8.4.

Note that loading the object means loading the object from a database into memory, or marking it for active use if it is already in the memory hierarchy. Object loading is the portion that tool implementers need to look at for efficiency considerations. Reading the data of an object, if loaded in memory, is a simple consequence of the load initialization (vpi_load_init()) and/or vpi_load() optionally called by the user. The API does not specify here any memory hierarchy or caching strategy that governs the access (load or read) speed. It is left up to tool implementation to choose the appropriate scheme. It is recommended that this happens in a fashion invisible to the user without requiring additional routine calls.

The API here provides the tool with the chance to prepare itself for data load and access with the vpi_load_init(). With this call, the tool can examine what objects the user wishes to access before the actual read access is made. The API also provides the user the ability to force loads and unloads but it is recommended to leave this to the tool unless there is a need for the user application to influence this aspect.

Group

30.8 Reading data

主题
主题 | 描述
30.8.3.1 Iterating the design for the loaded objects | The user shall be allowed to optionally iterate for the loaded objects in a specific instantiation scope using vpi_iterate(). This shall be accomplished by calling vpi_iterate() with the appropriate reference handle, and using the property vpiDataLoaded. This is shown below. a) Iterate all data read loaded objects in the design: use a NULL reference handle (ref_h) to
30.8.3.2 Iterating the object collection for its member objects | The user shall be allowed to iterate for the design objects in a design collection using vpi_iterate() and vpi_scan(). This shall be accomplished by creating an iterator for the members of the collection and then use vpi_scan() on the iterator handle e.g.
链接
30.8 Reading data, 主题


30.8.3.1 Iterating the design for the loaded objects

链接
30.8.3 Optionally loading objects
SystemVerilog 3.1a语言参考手册
30.8.3.1 Iterating the design for the loaded objects
30.8.3 Optionally loading objects

The user shall be allowed to optionally iterate for the loaded objects in a specific instantiation scope using vpi_iterate(). This shall be accomplished by calling vpi_iterate() with the appropriate reference handle, and using the property vpiDataLoaded. This is shown below.

a) Iterate all data read loaded objects in the design: use a NULL reference handle (ref_h) to

Copy Code
vpi_iterate(), e.g.,
itr = vpi_iterate(vpiDataLoaded, /* ref_h */ NULL);
while (loadedObj = vpi_scan(itr)) {
    /* process loadedObj */
}

b) Iterate all data read loaded objects in an instance: pass the appropriate instance handle as a reference

Copy Code
handle to vpi_iterate(), e.g.,
itr = vpi_iterate(vpiDataLoaded, /* ref_h */ instanceHandle);
while (loadedObj = vpi_scan(itr)) {
    /* process loadedObj */
}
Group

30.8.3 Optionally loading objects

链接
30.8.3 Optionally loading objects


30.8.3.2 Iterating the object collection for its member objects

链接
30.8.3 Optionally loading objects
SystemVerilog 3.1a语言参考手册
30.8.3.2 Iterating the object collection for its member objects
30.8.3 Optionally loading objects

The user shall be allowed to iterate for the design objects in a design collection using vpi_iterate() and vpi_scan(). This shall be accomplished by creating an iterator for the members of the collection and then use vpi_scan() on the iterator handle e.g.

Copy Code
vpiHandle var_handle; /* some object */
vpiHandle varCollection;/* object collection */
vpiHandle Var; /* object handle */
vpiHandle itr; /* iterator handle */
/* Create object collection */
varCollection = vpi_create(vpiObjCollection, NULL, NULL);
/* Add elements to the object collection */
varCollection = vpi_create(vpiObjCollection, varCollection, var_handle);
/* Iterating a collection for its elements */
itr = vpi_iterate(vpiMember, varCollection);/* create iterator*/
while (Var = vpi_scan(itr)) { /* scan iterator */
    /* process Var */
}
Group

30.8.3 Optionally loading objects

链接
30.8.3 Optionally loading objects


30.8.4 Reading an object

链接
30.8 Reading data, 主题
SystemVerilog 3.1a语言参考手册
30.8.4 Reading an object
30.8 Reading data | 主题

The sections above have outlined:

— How to select an object for access, in other words, marking this object as a target for access. This is

where the design navigation VPI is used.

— How to call vpi_load_init() as a hint on the areas to be accessed, and/or optionally load an object

into memory after obtaining a handle and then either loading objects individually or as a group using

the object collection.

— How to optionally iterate the design scope and the object collection to find the loaded objects if needed.

In this section reading data is discussed. Reading an object’s data means obtaining its value changes. VPI, before this extension, had allowed a user to query a value at a specific point in time—namely the current time, and its access does not require the extra step of giving a load hint or actually loading the object data. This step is added here because VPI is extended with a temporal access component: The user can ask about all the values in time (regardless of whether that value is available to a particular tool, or found in memory or a database, the mechanism is provided) since accessing this value horizon involves a larger memory expense, and possibly a considerable access time. Let’s see now how to access and traverse this value timeline of an object.

To access the value changes of an object over time, a traverse object is used, as introduced earlier in Section 30.4.1. Several VPI routines are also added to traverse the value changes (using this new handle) back and forth. This mechanism is very different from the “iteration” notion of VPI that returns objects related to a given object, the traversal here can walk or jump back and forth on the value change timeline of an object. To create a value change traverse handle the routine vpi_handle() must be called in the following manner:

Copy Code
vpiHandle trvsHndl = vpi_handle(vpiTrvsObj, object_handle);

Note that the user (or tool) application can create more than one value change traverse handle for the same object, thus providing different views of the value changes. Each value change traverse handle shall have a means to have an internal index, which is used to point to its “current” time and value change of the place it points. In fact, the value change traversal can be done by increasing or decreasing this internal index. What this index is, and how its function is performed is left up to tools’ implementation; It is only used as a concept for explanation here.

Once created the traverse handle can point anywhere along the timeline; its initial location is left for tool implementation. However, if the traverse object has no value changes the handle shall point to the minimum time (of the trace), so that calls to vpi_get_time() can return a valid time. It is up to the user to call an initial vpi_goto() to move to the desired initial pointing location.

Group

30.8 Reading data

主题
主题 | 描述
30.8.4.1 Traversing value changes of objects | After getting a traverse vpiHandle, the application can do a forward or backward walk or jump traversal by using vpi_goto() on a vpiTrvsObj object type with the new traverse properties. Here is a sample code segment for the complete process from handle creation to traversal.
30.8.4.2 Jump Behavior | Jump behavior refers to the behavior of vpi_goto() with a vpiTime control constant, vpiTrvsObj type, and a jump time argument. The user specifies a time to which he or she would like the traverse handle to jump, but the specified time might or might not have value changes. In that case, the traverse handle shall point to the latest VC equal to or less than the time requested. In the example below, the whole simulation run is from time 10 to time 65, and a variable has value changes at time 10, 15 and 50. If a value change traverse... more
30.8.4.3 Dump off regions | When accessing a database, it is likely that there are gaps along the value time-line where possibly the data recording (e.g. dumping from simulator) was turned off. In this case the starting point of that interval shall be marked as a VC if the object had a stored value before that time. vpi_goto(), whether used to jump to that time or using next VC or previous VC traversal from a point before or after respectively, shall stop at that VC. Calling vpi_get_value() on the traverse object pointing to that VC shall have no effect on the value argument passed; the... more
链接
30.8 Reading data, 主题


30.8.4.1 Traversing value changes of objects

链接
30.8.4 Reading an object
SystemVerilog 3.1a语言参考手册
30.8.4.1 Traversing value changes of objects
30.8.4 Reading an object

After getting a traverse vpiHandle, the application can do a forward or backward walk or jump traversal by using vpi_goto() on a vpiTrvsObj object type with the new traverse properties.

Here is a sample code segment for the complete process from handle creation to traversal.

Copy Code
p_vpi_extension reader_p; /* Pointer to VPI reader extension structure */
vpiHandle instanceHandle; /* Some scope object is inside */
vpiHandle var_handle; /* Object handle */
vpiHandle vc_trvs_hdl; /* Traverse handle */
vpiHandle itr;
p_vpi_value value_p; /* Value storage */
p_vpi_time time_p; /* Time storage */
PLI_INT32 code; /* return code */
...
/* Initialize the read interface: Access data from memory */
/* NOTE: Use built-in VPI (e.g. that of simulator application is running
under) */
reader_p = vpi_load_extension(NULL, NULL, vpiAccessLimitedInteractive);
if (reader_p == NULL) ... ; /* Not successful */
/* Initialize the load: Access data from simulator) memory, for scope
instanceHandle and its subscopes */
/* NOTE: Call marks access for all the objects in the scope */
vpi_load_init(NULL, instanceHandle, 0);
itr = vpi_iterate(vpiVariables, instanceHandle);
while (var_handle = vpi_scan(itr)) {
/* Demo how to force the load, this part can be skipped in general */
if (vpi_get(vpiIsLoaded, var_handle) == 0) { /* not loaded*/
/* Load data: object-based load, one by one */
if (!vpi_load(var_handle)); /* Data not found ! */
break;
}
/*-- End of Demo how to force the load, this part can be skipped in general */
/* Create a traverse handle for read queries */
vc_trvs_hdl = vpi_handle(vpiTrvsObj, var_handle);
/* Go to minimum time */
vc_trvs_hdl = vpi_goto(vpiMinTime, vc_trvs_hdl, NULL, NULL);
/* Get info at the min time */
time_p->type = vpiSimTime;
vpi_get_time(vc_trvs_hdl, time_p); /* Minimum time */
vpi_printf(...);
vpi_get_value(vc_trvs_hdl, value_p); /* Value */
vpi_printf(...);
if (vpi_get(vpiHasDataVC, vc_trvs_hdl)) { /* Have any VCs ? */
for (;;) { /* All the elements in time */
vc_trvs_hdl = vpi_goto(vpiNextVC, vc_trvs_hdl, NULL, &code);
if (!code) {
/* failure (e.g. already at MaxTime or no more VCs) */
break; /* cannot go further */
}
/* Get Max time: Set bits of s_vpi_time type field */
/* time_p->type = vpiMaxTime & vpiSimTime; */
/* vpi_get_time(vc_trvs_hdl, time_p); */
time_p->type = vpiSimTime;
vpi_get_time(vc_trvs_hdl, time_p); /* Time of VC */
vpi_get_value(vc_trvs_hdl, value_p); /* VC data */
}
}
}
/* free handles */
vpi_free_object(...);

The code segment above declares an interactive access scheme, where only a limited history of values is provided by the tool (e.g. simulator). It then creates a Value Change (VC) traverse handle associated with an object whose handle is represented by var_handle but only after vpi_load_init() is called. It then creates a traverse handle, vc_trvs_hdl. With this traverse handle, it first calls vpi_goto() to move to the minimum time where the value has changed. It moves the handle (internal index) to that time by calling vpi_goto() with a vpiMinTime argument. It then repeatedly calls vpi_goto() with a vpiNextVC to move the internal index forward repeatedly until there is no value change left. vpi_get_time() gets the actual time where this VC is, and data is obtained by vpi_get_value(). The application can also choose to call vpi_goto() with a time_p argument to automatically get the VC time instead of calling vpi_get_time() separately to get this information.

The traverse and collection handles can be freed when they are no longer needed using vpi_free_object().

Group

30.8.4 Reading an object

链接
30.8.4 Reading an object


30.8.4.2 Jump Behavior

链接
30.8.4 Reading an object
SystemVerilog 3.1a语言参考手册
30.8.4.2 Jump Behavior
30.8.4 Reading an object

Jump behavior refers to the behavior of vpi_goto() with a vpiTime control constant, vpiTrvsObj type, and a jump time argument. The user specifies a time to which he or she would like the traverse handle to jump, but the specified time might or might not have value changes. In that case, the traverse handle shall point to the latest VC equal to or less than the time requested.

In the example below, the whole simulation run is from time 10 to time 65, and a variable has value changes at time 10, 15 and 50. If a value change traverse handle is associated with this variable and a jump to a different time is attempted, the result shall be determined as follows:

  • Jump to 12; traverse handle return time is 10.
  • Jump to 15; traverse handle return time is 15.
  • Jump to 65; traverse handle return time is 50.
  • Jump to 30; traverse handle return time is 15.
  • Jump to 0; traverse handle return time is 10.
  • Jump to 50; traverse handle return time is 50.
If the jump time has a value change, then the internal index of the traverse handle shall point to that time. Therefore, the return time is exactly the same as the jump time.

If the jump time does not have a value change, and if the jump time is not less than the minimum time of the whole trace2 run, then the return time is aligned backward. If the jump time is less than the minimum time, then the return time shall be the minimum time. In case the object has hold value semantics between the VCs such as static variables, then the return of vpi_goto() (with a specified time argument to jump to) is a new handle pointing to that time to indicate success. In case the time is greater than the trace maximum time, or when an automatic object or an assertion or any other object that does not hold its value between the VCs then the return code should indicate failure (and the backward time alignment is still performed). In other words the time returned by the traverse object shall never exceed the trace maximum; the maximum point in the trace is not marked as a VC unless there is truly a value change at that point in time (see the example in this subsection).

Group

30.8.4 Reading an object

链接
30.8.4 Reading an object


30.8.4.3 Dump off regions

链接
30.8.4 Reading an object
SystemVerilog 3.1a语言参考手册
30.8.4.3 Dump off regions
30.8.4 Reading an object

When accessing a database, it is likely that there are gaps along the value time-line where possibly the data recording (e.g. dumping from simulator) was turned off. In this case the starting point of that interval shall be marked as a VC if the object had a stored value before that time. vpi_goto(), whether used to jump to that time or using next VC or previous VC traversal from a point before or after respectively, shall stop at that VC. Calling vpi_get_value() on the traverse object pointing to that VC shall have no effect on the value argument passed; the time argument shall be filled with the time at that VC. vpi_get() can be called in the form: vpi_get(vpiHasNoValue, <traverse handle>) to return TRUE if the traverse handle has no value (i.e. pointing to the start of a dump off region) and FALSE otherwise.

There is, of course, another VC (from no recorded value to an actual recorded value) at the end of the dump off interval, if the end exists i.e. there is additional dumping performed and data for this object exists before the end of the trace. There are no VCs in between the two marking the beginning and end (if they exist); a move to the next VC from the start point leads to the end point.

Group

30.8.4 Reading an object

链接
30.8.4 Reading an object


30.8.5 Sample code using object (and traverse) collections

链接
30.8 Reading data
SystemVerilog 3.1a语言参考手册
30.8.5 Sample code using object (and traverse) collections
30.8 Reading data
Copy Code
p_vpi_extension reader; /* Pointer to reader VPI library */
vpiHandle scope; /* Some scope being looked at */
vpiHandle var_handle; /* Object handle */
vpiHandle some_net; /* Handle of some net */
vpiHandle some_reg; /* Handle of some reg */
vpiHandle vc_trvs_hdl1; /* Traverse handle */
vpiHandle vc_trvs_hdl2; /* Traverse handle */
vpiHandle itr; /* Iterator */
vpiHandle objCollection; /* Object collection */
vpiHandle trvsCollection; /* Traverse collection */
PLI_BYTE8 *data = “my_database”;/* database */
p_vpi_time time_p; /* time */
PLI_INT32 code; /* Return code */
/* Initialize the read interface: Post process mode, read from a database */
/* NOTE: Uses “toolX” library */
reader_p = vpi_load_extension(“toolX”, data, vpiAccessPostProcess);
if (reader_p == NULL) ... ; /* Not successful */
/* Get the scope using its name */
scope = reader_p->vpi_handle_by_name(“top.m1.s1”, NULL);
/* Create object collection */
objCollection = reader_p->vpi_create(vpiObjCollection, NULL, NULL);
/* Add data to collection: All the nets in scope */
/* ASSUMPTION: (waveform) tool “toolX” supports this navigation
relationship */
itr = reader_p->vpi_iterate(vpiNet, scope);
while (var_handle = reader_p->vpi_scan(itr)) {
objCollection = reader_p->vpi_create(vpiObjCollection, objCollection,
var_handle);
}
/* Add data to collection: All the regs in scope */
/* ASSUMPTION: (waveform) tool supports this navigation relationship */
itr = reader_p->vpi_iterate(vpiReg, scope);
while (var_handle = reader_p->vpi_scan(itr)) {
objCollection = reader_p->vpi_create(vpiObjCollection, objCollection,
var_handle);
}
/* Initialize the load: focus only on the signals in the object collection:
objCollection */
reader_p->vpi_load_init(objCollection, NULL, 0);
/* Demo scanning the object collection */
itr = reader_p->vpi_iterate(vpiMember, objCollection);
while (var_handle = reader_p->vpi_scan(itr)) {
...
}
/* Application code here */
some_net = ...;
time_p = ...;
some_reg = ...;
....
vc_trvs_hdl1 = reader_p->vpi_handle(vpiTrvsObj, some_net);
vc_trvs_hdl2 = reader_p->vpi_handle(vpiTrvsObj, some_reg);
vc_trvs_hdl1 = reader_p->vpi_goto(vpiTime, vc_trvs_hdl1, time_p, &code);
vc_trvs_hdl2 = reader_p->vpi_goto(vpiTime, vc_trvs_hdl2, time_p, &code);
/* Data querying and processing here */
....
/* free handles*/
reader_p->vpi_free_object(...);
/* close database */
reader_p->vpi_close(0, vpiAccessPostProcess, data);

The code segment above initializes the read interface for post process read access from database data. It then creates an object collection objCollection then adds to it all the objects in scope of type vpiNet and vpiReg (assuming this type of navigation is allowed in the tool). Load access is initialized and set to the objects listed in objCollection. objCollection can be iterated using vpi_iterate() to create the iterator and then using vpi_scan() to scan it assuming here that the waveform tool provides this navigation. The application code is then free to obtain traverse handles for the objects, and perform its querying and data processing as it desires.

The code segment below shows a simple code segment that mimics the function of a $dumpvars call to access data of all the regs in a specific scope and its subscopes and process the data.

Copy Code
p_vpi_extension reader_p; /* Reader library pointer */
vpiHandle big_scope; /* Some scope being looked at */
vpiHandle obj_handle; /* Object handle */
vpiHandle obj_trvs_hdl; /* Traverse handle */
vpiHandle signal_iterator; /* Iterator for signals */
p_vpi_time time_p; /* time */
/* Initialize the read interface: Access data from simulator */
/* NOTE: Use built-in VPI (e.g. that of simulator application is running
under */
reader_p = vpi_load_extension(NULL, NULL, vpiAccessLimitedInteractive);
if (reader_p == NULL) ... ; /* Not successful */
/* Initialize the load access: data from (simulator) memory, for scope
big_scope and its subscopes */
/* NOTE: Call marks load access */
vpi_load_init(NULL, big_scope, 0);
/* Application code here */
/* Obtain handle for all the regs in scope */
signal_iterator = vpi_iterate(vpiReg, big_scope);
/* Data querying and processing here */
while ( (obj_handle = vpi_scan(signal_iterator)) != NULL ) {
assert(vpi_get(vpiType, obj_handle) == vpiReg);
/* Create a traverse handle for read queries */
obj_trvs_hdl = vpi_handle(vpiTrvsObj, obj_handle);
time_p = ...; /* some time */
obj_trvs_hdl = vpi_goto(vpiTime, obj_trvs_hdl, time_p, &code);
/* Get info at time */
vpi_get_value(obj_trvs_hdl, value_p); /* Value */
vpi_printf(“....”);
}
/* free handles*/
vpi_free_object(...);
Group

30.8 Reading data

链接
30.8 Reading data


30.8.6 Object-based traversal

链接
30.8 Reading data
SystemVerilog 3.1a语言参考手册
30.8.6 Object-based traversal
30.8 Reading data

Object based traversal can be performed by creating a traverse handle for the object and then moving it back and forth to the next or previous Value Change (VC) or by performing jumps in time. A traverse object handle for any object in the design can be obtained by calling vpi_handle() with a vpiTrvsObj type, and an object vpiHandle. This is the method described in Section 30.8.4, and used in all the code examples thus far.

Using this method, the traversal would be object-based because the individual object traverse handles are created, and then the application can query the (value, time) pairs for each VC. This method works well when the design is being navigated and there is a need to access the (stored) data of any individual object.

Group

30.8 Reading data

链接
30.8 Reading data


30.8.7 Time-ordered traversal

链接
30.8 Reading data
SystemVerilog 3.1a语言参考手册
30.8.7 Time-ordered traversal
30.8 Reading data

Alternatively, a user might wish to do a time-ordered traversal i.e. a time-based examination of values of several objects. This can be done by using a collection. The first step is to create a traverse collection of type vpiTrvsCollection of the objects to be traversed from the design object collection of type vpiObjCollection using vpi_handle() with a vpiTrvsCollection type and collection handle argument.

vpi_goto() can then be called on the traverse collection to move to next or previous or do jump in time for the collection as a whole. A move to next (previous) VC means move to the next (previous) earliest VC among the objects in the collection; any traverse handle that does not have any VC is ignored; on return its new handle points to the same place as its old. A jump to a specific time aligns the new returned handles of all the objects in the collection (as if this had been done object by object, but here it is done in one-shot for all elements).

It is possible to loop in time by incrementing the time, and doing a jump to those time increments. This is shown in the following code snippet.

Copy Code
vpiHandle objCollection = ...;
vpiHandle trvsCollection;
p_vpi_time time_p;
PLI_INT32 code;
/* Obtain (create) traverse collection from object collection */
trvsCollection = vpi_handle(vpiTrvsCollection, objCollection);
/* Loop in time: increments of 100 units */
for (i = 0; i < 1000; i = i + 100) {
    time_p = ...;
    /* Go to point in time */
    trvsCollection = vpi_goto(vpiTime, trvsCollection, time_p, &code);
    ...
}

Alternatively, the user might wish to get a new collection returned of all the objects that have a value change at the given time the traverse collection was moved to. In this case vpi_filter() follows the call to vpi_goto(). The latter returns a new collection with all the new traverse objects, whether they have a VC or not. vpi_filter() allows us to filter the members that have a VC at that time. This is shown in the code snippet that follows.

Copy Code
...
vpiHandle rettrvsCollection; /* Collection for all the objects */
vpiHandle vctrvsCollection; /* collection for the objects with VC */
vpiHandle itr; /* collection member iterator */
...
/* Go to earliest next VC in the collection */
for (;;) { /* for all collection VCs in time */
rettrvsCollection = vpi_goto(vpiNextVC, trvsCollection, NULL, &code);
if (!code) {
/* failure (e.g. already at MaxTime or no more VCs) */
break; /* cannot go further */
}
vctrvsCollection = vpi_filter(rettrvsCollection, vpiHasVC, 1);
/* create iterator then scan the VC collection */
itr = vpi_iterate(vpiMember, vctrvsCollection);
while (vc_trvs1_hdl = vpi_scan(itr)) {
/* Element has a VC */
vpi_get_value(vc_trvs1_hdl, value_p); /* VC data */
/* Do something at this VC point */
...
}
...
}
Group

30.8 Reading data

链接
30.8 Reading data


30.9 Optionally unloading the data

链接
第三十章 SystemVerilog数据读API
SystemVerilog 3.1a语言参考手册
30.9 Optionally unloading the data
第三十章 SystemVerilog数据读API

The implementation tool should handle unloading the unused data in a fashion invisible to the user. Managing the data caching and memory hierarchy is left to tool implementation but it should be noted that failure to unload can affect the tool performance and capacity.

The user can optionally choose to call vpi_unload() to unload the data from (active) memory if the user application is done with accessing the data.

Calling vpi_unload() before releasing (freeing) traverse (collection) handles that are manipulating the data using vpi_free_object() is not recommended practice by users; the behavior of traversal using existing handles is not defined here. It is left up to tool implementation to decide how best to handle this. Tools shall, however, prevent creation of new traverse handles, after the call to vpi_unload(), by returning the appropriate fail codes in the respective creation routines.

Group

第三十章 SystemVerilog数据读API

链接
第三十章 SystemVerilog数据读API


30.10 Reading data from multiple databases and/or different read library providers

链接
第三十章 SystemVerilog数据读API
SystemVerilog 3.1a语言参考手册
30.10 Reading data from multiple databases and/or different read library providers
第三十章 SystemVerilog数据读API

The VPI routine vpi_load_extension() is used to load VPI extensions. Such extensions include reader libraries from such tools as waveform viewers. vpi_load_extension() shall return a pointer to a function pointer structure with the following definition.

Copy Code
typedef struct {
    void *user_data; /* Attach user data here if needed */
    /* Below this point user application MUST NOT modify any values */
    size_t struct_size; /* Must be set to sizeof(s_vpi_extension) */
    long struct_version; /* Set to 1 for SystemVerilog 3.1a */
    PLI_BYTE8 *extension_version;
    PLI_BYTE8 *extension_name;
    /* One function pointer for each of the defined VPI routines:
     - Each function pointer has to have the correct prototype */
    ...
    PLI_INT32 (*vpi_chk_error)(error_info_p);
    ...
    PLI_INT32 (*vpi_vprintf)(PLI_BYTE8 *format, ...);
    ...
} s_vpi_extension, *p_vpi_extension;

Subsequent versions of the s_vpi_extension structure shall only extend it by adding members at the end; previously existing entries must not be changed, removed, or re-ordered in order to preserve backward compatability. The struct_size entry allows users to perform basic sanity checks (e.g. before type casting), and the struct_version permits keeping track and checking the version of the s_vpi_extension structure. The structure also has a user_data field to give users a way to attach data to a particular load of an extension if they wish to do so.

The structure shall have an entry for every VPI routine; the order and synopsis of these entries within the structure shall exactly match the order and synopsis of function definitions in Chapter 27 of the Verilog Standard, IEEE Std 1364-2001. After those entries the SystemVerilog VPI routine additions for assertions vpi_get_assertion_info() and then vpi_register_assertion_cb() shall be added in that order. Then all new reader routines defined in Table 30-3 shall be added in exactly the order noted in the table. If a particular extension does not support a specific VPI routine, then it shall still have an entry (with the correct prototype), and a dummy body that shall always have a return (consistent with the VPI prototype) to signify failure (i.e. NULL or FALSE ). The routine call must also raise the appropriate VPI error, which can be checked by vpi_chk_error(), and/or automatically generate an error message in a manner consistent with the specific VPI routine.

If tool providers want to add their own implementation extensions, those extensions must only have the effect of making the s_vpi_extension structure larger and any non-standard content must occur after all the standard fields. This permits applications to use the pointer to the extended structure as if it was a p_vpi_extension pointer, yet still allow the applications to go beyond and access or call tool-specific fields or routines in the extended structure. For example, a tool extended s_vpi_extension could be:

Copy Code
typedef struct {
    /* inline a copy of s_vpi_extension */
    /* begin */
    void *user_data;
    ...
    /* end */
    /* “toolZ” extension with one additional routine */
    int (*toolZfunc)(int);
} s_toolZ_extension, *p_toolZ_extension;

An example of use of the above extended structure is as follows:

Copy Code
p_vpi_extension h;
p_toolZ_extension hZ;
h = vpi_load_extension(“toolZ”, <args>);
if ( h && (h->struct_size >= sizeof(s_toolZ_extension))
&& !(strcmp(h->extension_version, “...”)
&& !strcmp(h->extension_name, “toolZ”) ) {
hZ = (p_toolZ_extension) h;
/* Can now use hZ to access all the VPI routines, including toolZ’s
‘toolZfunc’ */
...
}

The SystemVerilog tool the user application is running under is responsible for loading the appropriate extension, i.e. the reader API library in the case of the read API. The extension name is used for this purpose, following a specific policy, for example, this extension name can be the name of the library to be loaded. Once the reader API library is loaded all VPI function calls that wish to use the implementation in the library shall be performed using the returned p_vpi_extension pointer as an indirection to call the function pointers specified in s_vpi_extension or the extended vendor specific structure as described above. Note that, as stated earlier, in the case the application is using the built-in routine implementation (i.e. the ones provided by the tool (e.g. simulator) it is running under) then the de-reference through the pointer is not necessary.

Multiple databases can be opened for read simultaneously by the application. After a vpi_load_extension() call, a top scope handle can be created for that database to be used later to derive any other handles for objects in that database. An example of multiple database access is shown below. In the example, scope1 and scope2 are the top scope handles used to point into database1 and database2 respectively and perform the processing (comparing data in the two databases for example).

Copy Code
p_vpi_extension reader_pX; /* Pointer to reader libraryfunction struct */
p_vpi_extension reader_pY; /* Pointer to reader libraryfunction struct */
vpiHandle scope1, scope2; /* Some scope being looked at */
vpiHandle var_handle; /* Object handle */
vpiHandle some_net; /* Handle of some net */
vpiHandle some_reg; /* Handle of some reg */
vpiHandle vc_trvs_hdl1; /* Traverse handle */
vpiHandle vc_trvs_hdl2; /* Traverse handle */
vpiHandle itr; /* Iterator */
vpiHandle objCollection1, objCollection2; /* Object collection */
vpiHandle trvsCollection1, trvsCollection2; /* Traverse collection */
p_vpi_time time_p; /* time */
PLI_BYTE8 *data1 = “database1”;
PLI_BYTE8 *data2 = “database2”;
/* Initialize the read interface: Post process mode, read from a database */
/* NOTE: Use library from “toolX” */
reader_pX = vpi_load_extension(“toolX”, data1, vpiAccessPostProcess);
/* Get the scope using its name */
/* NOTE: scope handle comes from database: data1 */
scope1 = reader_pX->vpi_handle_by_name(“top.m1.s1”, NULL);
/* Initialize the read interface: Post process mode, read from a database */
/* NOTE: Use library from “toolY” */
reader_pY = vpi_load_extension(“toolY”, data2, vpiAccessPostProcess);
/* Get the scope using its name */
/* NOTE: scope handle comes from database: data2 */
scope2 = reader_pY->vpi_handle_by_name(“top.m1.s1”, NULL);
/* Create object collections */
objCollection1 = reader_pX->vpi_create(vpiObjCollection, NULL, NULL);
objCollection2 = reader_pY->vpi_create(vpiObjCollection, NULL, NULL);
/* Add data to collection1: All the nets in scope1,
data comes from database1 */
/* ASSUMPTION: (waveform) tool supports this navigation relationship */
itr = reader_pX->vpi_iterate(vpiNet, scope1);
while (var_handle = reader_pX->vpi_scan(itr)) {
objCollection1 = reader_pX->vpi_create(vpiObjCollection, objCollection1,
var_handle);
}
/* Add data to collection2: All the nets in scope2,
data comes from database2 */
/* ASSUMPTION: (waveform) tool supports this navigation relationship */
itr = reader_pY->vpi_iterate(vpiNet, scope2);
while (var_handle = reader_pY->vpi_scan(itr)) {
objCollection2 = reader_pY->vpi_create(vpiObjCollection, objCollection2,
var_handle);
}
/* Initialize the load: focus only on the signals in the object collection:
objCollection */
reader_pX->vpi_load_init(objCollection1, NULL, 0);
reader_pY->vpi_load_init(objCollection2, NULL, 0);
/* Demo: Scan the object collection */
itr = reader_pX->vpi_iterate(vpiMember, objCollection1);
while (var_handle = reader_pX->vpi_scan(itr)) {
...
}
itr = reader_pY->vpi_iterate(vpiMember, objCollection2);
while (var_handle = reader_pY->vpi_scan(itr)) {
...
}
/* Application code here: Access Objects from database1 or database2 */
some_net = ...;
time_p = ...;
some_reg = ...;
....
/* Data querying and processing here */
....
/* free handles*/
reader_pX->vpi_free_object(...);
reader_pY->vpi_free_object(...);
/* close databases */
reader_pX->vpi_close(0, vpiAccessPostProcess, data1);
reader_pY->vpi_close(0, vpiAccessPostProcess, data2);
Group

第三十章 SystemVerilog数据读API

链接
第三十章 SystemVerilog数据读API


30.11 VPI routines extended in SystemVerilog

链接
第三十章 SystemVerilog数据读API
SystemVerilog 3.1a语言参考手册
30.11 VPI routines extended in SystemVerilog
第三十章 SystemVerilog数据读API

Table 30-1 lists the usage extensions. They are repeated here the additional extended usage with traverse (collection) handles of vpi_get_time() for clarity.

Copy Code
vpi_get_time()
Synopsis: Retrieve the time of the object or collection of objects traverse handle.
Syntax: vpi_get_time(vpiHandle obj, p_vpi_time time_p)
Returns: PLI_INT32, 1 for success, 0 for fail.
Arguments:
vpiHandle obj: Handle to a traverse object of type vpiTrvsObj or a traverse collection of
type vpiTrvsCollection.
p_vpi_time time_p: Pointer to a structure containing the returned time information. There are
several cases to consider:
PLI_INT32 type = ...; /* vpiScaledRealTime, vpiSimTime, or vpiSuppressTime */
(time_p == type): Get the time of traverse object or collection. In case of collection
return time only if all the members have the same time, otherwise time_p is not modified.
(time_p == vpiMinTime & type): Gets the minimum time of traverse object or
collection.
(time_p == vpiMaxTime & type): Gets the maximum time of traverse object or
collection.
(time_p == vpiNextVC & type): Gets the time where traverse handle points next.
Returns failure if traverse object or collection has no next VC and time_p is not modified. In
the case of a collection, it returns success when any traverse object in the collection has a next
VC, time_p is updated with the smallest next VC time.
(time_p == vpiPrevVC & type): Gets the time where traverse handle previously
points. Returns failure if traverse object or collection has no previous VC and time_p is not
modified. In the case of a collection, it returns success when any traverse object in the
collection has a previous VC, time_p is updated with the largest previous VC time.
Related routines: None.
Group

第三十章 SystemVerilog数据读API

链接
第三十章 SystemVerilog数据读API


30.12 VPI routines added in SystemVerilog

链接
第三十章 SystemVerilog数据读API, 主题
SystemVerilog 3.1a语言参考手册
30.12 VPI routines added in SystemVerilog
第三十章 SystemVerilog数据读API | 主题

This section describes the additional VPI routines in detail.

Copy Code
vpi_load_extension()
Synopsis: Load specified VPI extension. The general form of this function allows for later extensions.
For the reader-specific form, initialize the reader with access mode, and specify the database if used.
Syntax: vpi_load_extension(PLI_BYTE8 *extension_name, ...) in its general form
vpi_load_extension( PLI_BYTE8 *extension_name,
PLI_BYTE8 *name,
vpiType mode, ...) for the reader extension
Returns: PLI_INT32, 1 for success, 0 for fail.
Arguments:
PLI_BYTE8 *extension_name: Extension name of the extension library to be loaded.
In the case of the reader, this is the reader VPI library (with the supported navigation
VPI routines).
...: Contains all the additional arguments. For the reader extension these are:
PLI_BYTE8 *name: Database.
vpiType mode:
vpiAccessLimitedInteractive: Access data in tool memory, with limited
history. The tool shall at least have the current time value, no history is required.
vpiAccessInteractive: Access data interactively. Tool shall keep value history up
to the current time.
vpiAccessPostProcess: Access data stored in specified database.
...: Additional arguments if required by specific reader extensions.
Related routines: None.
Group

第三十章 SystemVerilog数据读API

主题
主题 | 描述
30.12.1 VPI reader routines |
链接
第三十章 SystemVerilog数据读API, 主题


30.12.1 VPI reader routines

链接
30.12 VPI routines added in SystemVerilog
SystemVerilog 3.1a语言参考手册
30.12.1 VPI reader routines
30.12 VPI routines added in SystemVerilog
Copy Code
vpi_close()
Synopsis: Close the database if open.
Syntax: vpi_close(PLI_INT32 tool, vpiType prop, PLI_BYTE8* name)
Returns: PLI_INT32, 1 for success, 0 for fail.
Arguments:
    PLI_INT32 tool: 0 for the reader.
    vpiType prop:
        vpiAccessPostProcess: Access data stored in specified database.
        vpiAccessInteractive: Access data interactively, database is the flush area.
        Tool shall keep value history up to the current time.
    PLI_BYTE8* name: Name of the database. This can be the logical name of a database
    or the actual name of the data file depending on the tool implementation.
Related routines: None.

vpi_load_init()
    Synopsis: Initialize the load access to scope and/or collection of objects.
    Syntax: vpi_load_init(vpiHandle objCollection, vpiHandle scope, PLI_INT32 level)
    Returns: PLI_INT32, 1 for success, 0 for fail.
    Arguments:
        vpiHandle objCollection: Object collection of type vpiObjCollection, a
                                 collection of design objects.
        vpiHandle scope: Scope of the load.
        PLI_INT32 level: If 0 then enables read access to scope and all its subscopes,
                         1 means just the scope.
    Related routines: None.

vpi_load()
    Synopsis: Load the data of the given object into memory for data access and
              traversal if object is an object handle; load the whole collection
              (i.e. set of objects) if passed handle is an object collection of type
              vpiObjCollection.
    Syntax: vpi_load(vpiHandle h)
    Returns: PLI_INT32, 1 for success of loading (all) object(s) (in collection),
             0 for fail of loading (any) object (in collection).
    Arguments:
        vpiHandle h: Handle to a design object (of any valid type) or object collection
                     of type vpiObjCollection.
    Related routines: None

vpi_unload()
    Synopsis: Unload the given object data from (active) memory if object is an object
              handle, unload the whole collection if passed object is a collection of
              type vpiObjCollection. See Section 30.9 for a description of data
              unloading.
    Syntax: vpi_unload(vpiHandle h)
    Returns: PLI_INT32, 1 for success, 0 for fail.
    Arguments:
        vpiHandle h: Handle to an object or collection (of type vpiObjCollection).
    Related routines: None.

vpi_create()
    Synopsis: Create or add to an object or traverse collection.
    Syntax: vpi_create(vpiType prop, vpiHandle h, vpiHandle obj)
    Returns: vpiHandle of type vpiObjCollection for success, NULL for fail.
    Arguments:
        vpiType prop:
        vpiObjCollection: Create (or add to) object (vpiObjCollection) or
                          traverse (vpiTrvsCollection) collection.
        vpiHandle h: Handle to a (object) traverse collection of
                     type (vpiObjCollection)
        vpiTrvsCollection, NULL for first call (creation)
        vpiHandle obj: Handle of object to add, NULL if for first time creation of
                       collection.
    Related routines: None.

vpi_goto()
    Synopsis: Try to move to min, max or specified time. A new traverse (collection)
              handle is returned pointing to the specified time. If the traverse handle
              (members of collection) has a VC at that time then the returned handle
              (members of returned collection) is updated to point to the specified
              time, otherwise it is not updated. If the passed handle has no VC (for
              collection this means no VC for any object) a fail is indicated,
              otherwise a success is indicated. In case of a jump to a specified time,
              and there is no value change at the specified time, then the value change
              traverse index of the returned (new) handle (member of returned collection)
              is aligned based on the jump behavior defined in Section 30.8.4.2, and
              its time (and the time pointer argument if passed and is non-NULL) shall
              be updated based on the aligned traverse point. In the case of vpiNextVC
              or vpiPrevVC, the time argument, if passed and is non-NULL (otherwise
              it is ignored and not updated), is updated if there is a VC (for
              collection this means a VC for any object) to the new time, otherwise the
              value is not updated.
    Syntax: vpi_goto(vpiType prop, vpiHandle obj, p_vpi_time time_p, PLI_INT32
                     *ret_code)
    Returns: vpiHandle of type vpitrvsObj (vpiObjCollection).
    Arguments:
vpiType prop:
vpiMinTime: Goto the minimum time of traverse collection handle.
vpiMaxTime: Goto the maximum time of traverse collection handle.
vpiTime: Jump to the time specified in time_p.
vpiNextVC: Goto the (time of) next VC.
vpiPrevVC: Goto the (time of) previous VC.
vpiHandle obj: Handle to a traverse object (collection) of type vpiTrvsObj
(vpiTrvsCollection)
p_vpi_time time_p: Pointer to a structure containing time information. Used only if prop is
of type vpiTime, otherwise it is ignored.
PLI_INT32 *ret_code:Pointer to a return code indicator. It is 1 for success and 0 for fail.
Related routines: None.
vpi_filter()
Synopsis: Filter a general collection, a traversable object collection, or traverse collection according to a
specific criterion. Return a collection of the handles that meet the criterion. Original collection is not
changed.
Syntax: vpi_filter(vpiHandle h, PLI_INT32 ft, PLI_INT32 flag)
Returns: vpiHandle of type vpiObjCollection for success, NULL for fail.
Arguments:
vpiHandle h: Handle to a collection of type vpiCollection, vpiObjCollection or
vpiTrvsCollection
PLI_INT32 ft: Filter criterion, any vpiType or a VPI boolean property.
PLI_INT32 flag: Flag to indicate whether to match criterion (if set to TRUE), or not (if set to
FALSE).
Related routines: None.
Group

30.12 VPI routines added in SystemVerilog

链接
30.12 VPI routines added in SystemVerilog


第三十一章 SystemVerilog VPI Object Model

链接
主题
SystemVerilog 3.1a语言参考手册
第三十一章 SystemVerilog VPI Object Model
主题
主题
主题
描述
31.1 简介（一般信息）
SystemVerilog extends the Verilog Procedural Interface (VPI) object diagrams to support SystemVerilog constructs. The VPI object diagrams document the properties of objects and the relationships of objects. How these diagrams illustrate this information is explained in Section 26 of the IEEE Std. 1364-2001 Verilog standard. The SystemVerilog extensions to the VPI diagrams are in the form of changes to or additions to the diagrams contained in 1364-2001 Verilog standard.

The following table summarizes the changes and additions made to the Verilog VPI object diagrams:

Table 31-4: Verilog VPI object diagram changes and additions

31.2 Instance

NOTES

  1. Top-level instances shall be accessed using vpi_iterate() with a NULL reference object.
  2. Passing a NULL handle to vpi_get() with types vpiTimePrecision or vpiTimeUnit shall return the smallest time precision of all instances in the design.
  3. If an instance is an element within an array, the vpiIndex transition is used to access the index within the array. If the instance is not part of an array, this transition shall return NULL.
  4. Compilation units are represented as packages that have a vpiUnit property set to TRUE. Such implicitly declared packages shall have implementation dependent names.
31.3 Interface

NOTE
All interfaces are instances and all relations and properties in the Instances diagram also apply.

31.4 Program

NOTE
All programs are instances and all relations and properties in the Instances diagram also apply.

31.5 Module (supersedes IEEE 1364-2001 26.6.1)

31.6 Modport
31.7 Interface tf decl

NOTE
vpiIterate(vpiTaskFunc) can return more than one task/function declaration for modport tasks/functions with an access type of vpiForkJoin, because the task or function can be imported from multiple module instances.

31.8 Ports (supersedes IEEE 1364-2001 26.6.5)

NOTES

  1. vpiPortType shall be one of the following three types: vpiPort, vpiInterfacePort, and vpiModportPort. Port type depends on the formal, not on the actual.
  2. vpi_get_delays, vpi_put_delays delays shall not be applicable for vpiInterfacePort.
  3. vpiHighConn shall indicate the hierarchically higher (closer to the top module) port connection.
  4. vpiLowConn shall indicate the lower (further from the top module) port connection.
  5. vpiLowConn of a vpiInterfacePort shall always be vpiRefObj.
  6. Properties scalar and vector shall indicate if the port is 1 bit or more than 1 bit. They shall not indicate anything about what is connected to the port.
  7. Properties index and name shall... more
31.9 Ref Obj
31.10 Variables (supersedes IEEE 1364-2001 section 26.6.8)

NOTES
1) A var select is a word selected from a variable array.
2) The boolean property vpiArray shall be TRUE if the variable handle references an array of variables, and FALSE otherwise. If the variable is an array, iterate on vpiVarSelect to obtain handles to each variable in the array.
3) To obtain the members of a union and structure, see the relations in Section 31.21
4) The range relation is valid only when vpiArray is true. When applied to array vars this relation returns only unpacked ranges. When applied to logic and bit variables, it returns only the... more

31.11 Var Select (supersedes IEEE 1364-2001 26.6.8)
31.12 Typespec

NOTES
1) If the vpiTypedef is TRUE and the typedef creates an alias of another typedef, then the vpiTypedefAlias shall return a non null handle which represents the handle to the aliased typedef. For example:
31.13 Variable Drivers and Loads (supersedes IEEE 1364-2001 26.6.23)

NOTES
1) vpiDrivers/Loads for a structure, union, or class variable will include the following:
— Driver/Load for the whole variable
— Driver/Load for any bit/part select of that variable
— Driver/Load of any member nested inside that variable
2) vpiDrivers/Loads for any variable array should include the following:
— Driver/Load for entire array/vector or any portion of an array/vector to which a handle can be obtained.
31.14 Instance Arrays (supersedes IEEE 1364-2001 26.6.2)

NOTE
1) Param assignments can only be obtained from non-primitive instance arrays.
2) To obtain all the dimensions of a multi-dimensional array, the range iterator must be used. Using the vpiLeftRange/vpiRightRange properties will only return the last dimension of a multidimensional array.
31.15 Scope (supersedes IEEE 1364-2001 26.6.3)

NOTE
1: Unnamed scopes shall have valid names, though tool dependent.
2: The vpiImport iterator shall return all objects imported into the current scope via import statements. Note that only objects actually referenced through the import shall be returned, rather than items potentially made visible as a result of the import. Refer to Section 18.2.2 for more details.
31.16 IO Declaration (supersedes IEEE 1364-2001 26.6.4)

vpiDirection returns vpiRef for pass by ref ports.
31.17 Clocking Block
31.18 Class Object Definition

NOTE
  1. ClassDefn handle is a new concept. It does not correspond to any vpiUserDefined (class object) in the design. Rather it represents the actual type definition of a class.
  2. Should not call vpi_get_value/vpi_put_value on the non-static variables obtained from the class definition handle.
  3. Iterator to constraints returns only normal constraints and not inline constraints.
  4. To get constraints inherited from base classes, you will need to traverse the extend relation to obtain the base class.
  5. The vpiDerivedClasses iterator returns all the classes derived from the given class.
  6. The relation to vpiExtend exists whenever a one class is derived from another class... more
31.19 Constraint, constraint ordering, distribution,
31.20 Constraint expression
31.21 Class Variables

NOTES
1) vpiWaiting/Process iterator on mailbox/semaphores will show the processes waiting on the object:
— Waiting process means either frame or task/function handle.
2) vpiMessage iterator shall return all the messages in a mailbox.
3) vpiClassDefn returns the ClassDefn which was used to create the handle. vpiActualDefn returns
the ClassDefn that handle object points to when the query is made. The difference can be seen in
the example below:
class Packet
...
endclass : Packet
class LinkedPacket extends Packet
...
endclass : LinkedPacket
LinkedPacket l = new;
Packet p = l;
In this example, the vpiClassDefn of variable "p" is... more
31.22 Structure/Union

NOTES
vpi_get_value/vpi_put_value cannot be used to access values of entire unpacked structures and unpacked unions.
31.23 Named Events (supersedes IEEE 1364-2001 26.6.11)

NOTE
The new iterator (vpiWaitingProcesses) returns all waiting processes, identified by their frame, for that named event.

NOTE
vpi_iterate(vpiIndex, named_event_handle) shall return the set of indices for a named event within an array, starting with the index for the named event and working outward. If the named event is not part of an array, a NULL shall be returned.
31.24 Task, Function Declaration (supersedes IEEE 1364-2001 26.6.18)

NOTE
5) A Verilog HDL function shall contain an object with the same name, size, and type as the function.
6) vpiInterfaceTask/vpiInterfaceFunction shall be true if task/function is declared inside an interface or a modport of an interface.
7) For function where return type is a user-defined type, vpi_handle (vpiReturn,Function_handle) shall return the implicit variable handle representing the return of the function from which the user can get the details of that user-defined type.
8) vpiReturn will always return a var object, even for simple returns.
31.25 Alias Statement
31.26 Frames (supersedes IEEE 1364-2001 26.6.20)

NOTES
1) The following callbacks shall be supported on frames:
— cbStartOfFrame: triggers whenever any frame gets executed.
— cbEndOfFrame: triggers when a particular thread is deleted after all storage is deleted.
31.27 Threads

NOTES
The following callbacks shall be supported on threads
— cbStartOfThread: triggers whenever any thread is created
— cbEndOfThread: triggers when a particular thread gets deleted after storage is deleted.
— cbEnterThread: triggers whenever a particular thread resumes execution
31.28 tf call (supersedes IEEE 1364-2001 26.6.19)

NOTE:
1) the vpiWith relation is only available for randomize methods (see Section 12.6) and for array locator methods (see Section 4.15.1).
2) For methods (method func call, method task call), the vpiPrefix relation will return the object to which the method is being applied. For example, for the class method invocation
packet.send();
the prefix for the "send" method is the class var "packet"
31.29 Module path, path term (supersedes IEEE 1364-2001 26.6.15)

NOTE:
1) specify blocks can occur in both modules and interfaces. For backwards compatibility the vpiModule relation has been preserved; however this relation will return NULL for specify blocks in interfaces. For new code it is recommended that the vpiInstance relation be used instead.
31.30 Concurrent assertions

NOTE
Clocking event is always the actual clocking event on which the assertion is being evaluated, regardless of whether this is explicit or implicit (inferred)
31.31 Property Decl
31.32 Property Specification

NOTE
Variables are declarations of property variables. You cannot get the value of these variables.

NOTES:
1. within the context of a property expr, vpiOpType can be any one of vpiNotOp, vpiImplyOp, vpiDelayedImplyOp, vpiAndOp, vpiOrOp, vpiIfOp, vpiIfElseOp
Operands to these operations will be provided in the same order as show in the BNF.
31.33 Multiclock Sequence Expression
31.34 Sequence Declaration

NOTE:
the vpiArgument iterator shall return the sequence instance arguments in the order that the formals for the sequence are declared, so that the correspondence between each argument and its respective formal can be made. If a formal has a default value, that value will appear as the argument should the instantiation not provide a value for that argument.
31.35 Sequence Expression

Notes:
2. Within a sequence expression, vpiOpType can be any one of vpiAndOp, vpiIntersectOp, vpiOr, vpiFirstMatchOp, vpiThroughoutOp, vpiWithinOp, vpiUnaryCycleDelayOp, vpiCycleDelayOp, vpiRepeatOp, vpiConsecutiveRepeatOp or vpiGotoRepeatOp.
3. For operations, the operands are provided in the same order as the operands appear in BNF, with the following exceptions:
vpiUnaryCycleDelayOp: arguments will be: sequence, left range, right range. Right range will only be given if different than left range.
vpiCycleDelayOp: argument will be: LHS sequence, rhs sequence, left range, right range. Right range will only be provided if different than left range.
all the repeat operators: the first argument will be the sequence being... more
31.36 Attribute (supersedes IEEE 1364-2001 26.6.42)
31.37 Atomic Statement (supersedes IEEE 1364-2001 26.6.27)
31.38 If, if else, return, case, do while (supersedes IEEE 1364-2001 26.6.35, 26.6.36)
31.39 waits, disables, expect, foreach (supersedes IEEE 1364 26.6.38)
31.40 Simple expressions (supersedes IEEE 1364-2001 26.6.25)
31.41 Expressions (supersedes IEEE 1364-2001 26.6.26)

NOTES:
1) For an operator whose type is vpiMultiConcat, the first operand shall be the multiplier expression. The remaining operands shall be the expressions within the concatenation.
2) The property vpiDecompile will return a string with a functionally equivalent expression to the original expression within the HDL. Parenthesis shall be added only to preserve precedence. Each operand and operator shall be separated by a single space character. No additional white space shall be added due to parenthesis.
3) New vpiOpTypes: vpiInsideOp, vpiMatchOp, vpiCastOp, vpiPreIncOp, vpiPostIncOp, vpiPreDecOp, vpiPostDecOp, vpiIffOp, vpiCycleDelayOp. The cast operation is represented as a unary operation, with its... more
31.42 Event control (supersedes IEEE 1364-2001 26.6.30)

NOTE—For event control associated with assignment, the statement shall always be NULL.
31.43 Event stmt (supersedes IEEE 1364-2001 26.6.27)
31.44 Process (supersedes IEEE 1364-2001 26.6.27)

NOTE- vpiAlwaysType can be one of: vpiAlwaysComb, vpiAlwaysFF, vpiAlwaysLatch
31.45 Assignment (supersedes IEEE 1364-2001 26.6.28)

NOTE: vpiOpType will return vpiAssignmentOp for normal non-blocking ’=’ assignments, and the operator combined with the assignment for the operators described in section 7.3.

For example, the assignment
链接
主题


31.1 简介（一般信息）

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.1 简介（一般信息）
第三十一章 SystemVerilog VPI Object Model

SystemVerilog extends the Verilog Procedural Interface (VPI) object diagrams to support SystemVerilog constructs. The VPI object diagrams document the properties of objects and the relationships of objects. How these diagrams illustrate this information is explained in Section 26 of the IEEE Std. 1364-2001 Verilog standard. The SystemVerilog extensions to the VPI diagrams are in the form of changes to or additions to the diagrams contained in 1364-2001 Verilog standard.

The following table summarizes the changes and additions made to the Verilog VPI object diagrams:

Table 31-4: Verilog VPI object diagram changes and additions

Diagram | Notes
Instances | New
Interface | New
Program | New
Module | Replaces IEEE 1364.2001 section 26.6.1
Modport | New
Interface tf decl | New
Ports | Replaces IEEE 1364.2001, section 26.6.5
Ref Obj | New
Variable | Replaces IEEE 1364.2001 section 26.6.8
Var select | New
Typespec | New
Variable Drivers and Loads | New
Instance Arrays | Replaces IEEE 1364.2001 section 26.6.2
Scope | Replaces IEEE 1364.2001 section 26.6.3
IO Declaration | Replaces IEEE 1364.2001 section 26.6.4
Class Object Definition | New
Constraint | New
Dist Item | New
Constraint Expression | New
Class Variables | New
Structure/Union | New
Named Events | New
Named Event Array | New
Task, Function Declaration | Replaces IEEE 1364.2001 section 26.6.18
Alias Statement | New
Frames | Replaces IEEE 1364.2001 section 26.6.20
Threads | New
Concurrent Assertions | New
Disable Condition | New
Clocking Event | New
Property Declaration | New
Property Specification | New
Property Expression | New
Multiclock Sequence Expression | New
Sequence Declaration | New
Sequence Expression | New
Instances | New
Atomic Statement | New
if, if-else | Replaces IEEE 1364-2001 section 26.6.35
case | Replaces IEEE 1364-2001 section 26.6.36
return | New
do while | New
waits | Replaces wait in IEEE 1364-2001 section 26.6.32
disables | Replaces IEEE 1364-2001 section 26.6 38
expect | New
foreach | New
Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.2 Instance

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.2 Instance
第三十一章 SystemVerilog VPI Object Model

NOTES

  1. Top-level instances shall be accessed using vpi_iterate() with a NULL reference object.
  2. Passing a NULL handle to vpi_get() with types vpiTimePrecision or vpiTimeUnit shall return the smallest time precision of all instances in the design.
  3. If an instance is an element within an array, the vpiIndex transition is used to access the index within the array. If the instance is not part of an array, this transition shall return NULL.
  4. Compilation units are represented as packages that have a vpiUnit property set to TRUE. Such implicitly declared packages shall have implementation dependent names.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.3 Interface

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.3 Interface
第三十一章 SystemVerilog VPI Object Model

NOTE

All interfaces are instances and all relations and properties in the Instances diagram also apply.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.4 Program

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.4 Program
第三十一章 SystemVerilog VPI Object Model

NOTE

All programs are instances and all relations and properties in the Instances diagram also apply.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.5 Module (supersedes IEEE 1364-2001 26.6.1)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.5 Module (supersedes IEEE 1364-2001 26.6.1)
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.6 Modport

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.6 Modport
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.7 Interface tf decl

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.7 Interface tf decl
第三十一章 SystemVerilog VPI Object Model

NOTE

vpiIterate(vpiTaskFunc) can return more than one task/function declaration for modport tasks/functions with an access type of vpiForkJoin, because the task or function can be imported from multiple module instances.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.8 Ports (supersedes IEEE 1364-2001 26.6.5)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.8 Ports (supersedes IEEE 1364-2001 26.6.5)
第三十一章 SystemVerilog VPI Object Model

NOTES

  1. vpiPortType shall be one of the following three types: vpiPort, vpiInterfacePort, and vpiModportPort. Port type depends on the formal, not on the actual.
  2. vpi_get_delays, vpi_put_delays delays shall not be applicable for vpiInterfacePort.
  3. vpiHighConn shall indicate the hierarchically higher (closer to the top module) port connection.
  4. vpiLowConn shall indicate the lower (further from the top module) port connection.
  5. vpiLowConn of a vpiInterfacePort shall always be vpiRefObj.
  6. Properties scalar and vector shall indicate if the port is 1 bit or more than 1 bit. They shall not indicate anything about what is connected to the port.
  7. Properties index and name shall not apply for port bits.
  8. If a port is explicitly named, then the explicit name shall be returned. If not, and a name exists, then that name shall be returned. Otherwise, NULL shall be returned.
  9. vpiPortIndex can be used to determine the port order. The first port has a port index of zero.
  10. vpiHighConn and vpiLowConn shall return NULL if the port is not connected.
  11. vpiSize for a null port shall return 0.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.9 Ref Obj

链接
第三十一章 SystemVerilog VPI Object Model, 主题
SystemVerilog 3.1a语言参考手册
31.9 Ref Obj
第三十一章 SystemVerilog VPI Object Model | 主题

Group

第三十一章 SystemVerilog VPI Object Model

主题
主题 | 描述
31.9.1 Examples | These objects are newly defined objects needed for supporting the full connectivity through ports where the ports are vpiInterface or vpiModport or any object inside modport or interface. RefObjs are dummy objects and they always have a handle to the original object.
链接
第三十一章 SystemVerilog VPI Object Model, 主题


31.9.1 Examples

链接
31.9 Ref Obj
SystemVerilog 3.1a语言参考手册
31.9.1 Examples
31.9 Ref Obj

These objects are newly defined objects needed for supporting the full connectivity through ports where the ports are vpiInterface or vpiModport or any object inside modport or interface.

RefObjs are dummy objects and they always have a handle to the original object.

Copy Code
interface simple ()
    logic req, gnt;
    modport slave (input req, output gnt);
    modport master (input gnt, output req);
}

module top()
    interface simple i;
    child1 i1(i);
    child2 i2(i.master);
endmodule

/***********************************
for port of i1,
    vpiHighConn = vpiRefObj where vpiRefObjType = vpiInterface

for port of i2 ,
    vpiHighConn = vpiRefObj where vpifullType = vpiModport
****************************************/
module child1(interface simple s)
    c1 c_1(s);
    c1 c_2(s.master);
endmodule

/****************************
for port of child1,
    vpiLowConn = vpiRefObj where vpiRefObjType = vpiInterface

for that refObj,
    vpiPort is = port of child1.

vpiPortInst is = s, s.master
vpiActual is = i.

for port of c_1 :
    vpiHighConn is a vpiRefObj, where full type is vpiInterface.

for port of c_2 :
    vpiHighConn is a vpiRefObj, where full type is vpiModport.
Group

31.9 Ref Obj

链接
31.9 Ref Obj


31.10 Variables (supersedes IEEE 1364-2001 section 26.6.8)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.10 Variables (supersedes IEEE 1364-2001 section 26.6.8)
第三十一章 SystemVerilog VPI Object Model

NOTES

1) A var select is a word selected from a variable array.

2) The boolean property vpiArray shall be TRUE if the variable handle references an array of variables, and FALSE otherwise. If the variable is an array, iterate on vpiVarSelect to obtain handles to each variable in the array.

3) To obtain the members of a union and structure, see the relations in Section 31.21

4) The range relation is valid only when vpiArray is true. When applied to array vars this relation returns only unpacked ranges. When applied to logic and bit variables, it returns only the packed ranges.

5) vpi_handle (vpiIndex, var_select_handle) shall return the index of a var select in a 1-dimensional array. vpi_iterate (vpiIndex, var_select_handle) shall return the set of indices for a var select in a multidimensional array, starting with the index for the var select and working outward

6) vpiLeftRange and vpiRightRange shall only apply if vpiMultiArray is not true, i.e. if the array is not multi-dimensional.

7) A variable handle of type vpiArrayVar represents an unpacked array. The range iterator for array vars returns only the unpacked ranges for the array.

8) If the variable has an initialization expression, the expression can be obtained from vpi_handle(vpiExpr, ar_handle)

9) vpiSize for a variable array shall return the number of variables in the array. For non-array variables, it shall return the size of the variable in bits. For unpacked structures and unions the size returned indicates the number of fields in the structure or union.

10) vpiSize for a var select shall return the number of bits in the var select. This applies only for packed var select.

11) Variables whose boolean property vpiArray is TRUE do not have a value property.

12) vpiBit iterator applies only for logic, bit, packed struct, and packed union variables.

13) vpi_handle(vpiIndex, var_bit_handle) shall return the bit index for the variable bit. vpi_iterate(vpiIndex, var_bit_handle) shall return the set of indices for a multidimensional variable bit select, starting with the index for the bit and working outwards

14) cbSizeChange will be applicable only for dynamic and associative arrays. If both value and size change, the size change callback will be invoked first. This callback fires after size change occurs and before any value changes for that variable. The value in the callback is new size of the array.

15) The property vpiRandType, returns the current randomization type for the variable, which can be one of vpiRand, vpiRandC, and vpiNotRand.

16) vpiIsRandomized is a property to determine whether a random variable is currently active for randomization.

17) When the vpiMember property is true, it indicates that the variable is a member of a parent struct or union variable. See also relations in Section 31.21

18) If a variable is an element of an array, the vpiIndex iterator will return the indexing expressions that select that specific variable out of the array.

19) Note that:

logic var == reg

var bit var == reg bit

array var == reg array

20) The properties vpiScalar and vpiVector are applicable only to packed struct vars, packed union vars, bit vars and logic vars. These properties return false for all other objects.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.11 Var Select (supersedes IEEE 1364-2001 26.6.8)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.11 Var Select (supersedes IEEE 1364-2001 26.6.8)
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.12 Typespec

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.12 Typespec
第三十一章 SystemVerilog VPI Object Model

NOTES

1) If the vpiTypedef is TRUE and the typedef creates an alias of another typedef, then the vpiTypedefAlias shall return a non null handle which represents the handle to the aliased typedef. For example:

Copy Code
typedef enum bit [0:2] {red, yellow, blue} primary_colors;
typdef primary_colors colors;

If “h1” is a handle to the typespec colors, its vpiType shall return a vpiEnumTypespec, the vpiTypedef property shall be true, the vpiName property shall return “colors”, the vpiTypedefAlias shall return a handle “h2” to the typespec “primary_colors” of vpiType vpiEnumTypespec. The vpiTypedef property shall be false for h2 and its vpiTypedefAlias shall return null.

2) vpiIndexTypespec relation is present only on associative arrays and returns the type that is used as the key into the associative array.

3) If the type of a type is vpiStruct or vpiUnion, then you can iterate over numbers to obtain the structure of the user-defined type. For each member the typespec relation from the member will detail its type.

4) The name of a typedef may be the empty string if the typedef is representing the type of a typedef field defined inline rather than via a typedef. For example:

Copy Code
typedef struct {
    struct {
        int a;
    }B
} C;

5) The typedef C has vpiTypedefType vpiStruct, a single field named B with vpiTypedefType vpiStruct. Obtaining the typedef of field B, you will obtain a typedef with no name and a single field, named "a" with vpiTypedefType of vpiInt.

6) If a type is defined as an alias of another type, it inherits the vpiType of this other type. For example:

Copy Code
typedef time my_time;
my_time t;

The vpiTypespec of the variable named “t” shall return a handle h1 to the typespec “my_time” whose vpiType shall be a vpiTimeTypespec. The vpiTypedefAlias applied to handle h1 shall return a typespec handle h2 to the predefined type “time”.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.13 Variable Drivers and Loads (supersedes IEEE 1364-2001 26.6.23)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.13 Variable Drivers and Loads (supersedes IEEE 1364-2001 26.6.23)
第三十一章 SystemVerilog VPI Object Model

NOTES

1) vpiDrivers/Loads for a structure, union, or class variable will include the following:

— Driver/Load for the whole variable

— Driver/Load for any bit/part select of that variable

— Driver/Load of any member nested inside that variable

2) vpiDrivers/Loads for any variable array should include the following:

— Driver/Load for entire array/vector or any portion of an array/vector to which a handle can be obtained.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.14 Instance Arrays (supersedes IEEE 1364-2001 26.6.2)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.14 Instance Arrays (supersedes IEEE 1364-2001 26.6.2)
第三十一章 SystemVerilog VPI Object Model

NOTE

1) Param assignments can only be obtained from non-primitive instance arrays.

2) To obtain all the dimensions of a multi-dimensional array, the range iterator must be used. Using the vpiLeftRange/vpiRightRange properties will only return the last dimension of a multidimensional array.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.15 Scope (supersedes IEEE 1364-2001 26.6.3)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.15 Scope (supersedes IEEE 1364-2001 26.6.3)
第三十一章 SystemVerilog VPI Object Model

NOTE

1: Unnamed scopes shall have valid names, though tool dependent.

2: The vpiImport iterator shall return all objects imported into the current scope via import statements. Note that only objects actually referenced through the import shall be returned, rather than items potentially made visible as a result of the import. Refer to Section 18.2.2 for more details.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.16 IO Declaration (supersedes IEEE 1364-2001 26.6.4)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.16 IO Declaration (supersedes IEEE 1364-2001 26.6.4)
第三十一章 SystemVerilog VPI Object Model

vpiDirection returns vpiRef for pass by ref ports.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.17 Clocking Block

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.17 Clocking Block
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.18 Class Object Definition

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.18 Class Object Definition
第三十一章 SystemVerilog VPI Object Model

NOTE

  1. ClassDefn handle is a new concept. It does not correspond to any vpiUserDefined (class object) in the design. Rather it represents the actual type definition of a class.
  2. Should not call vpi_get_value/vpi_put_value on the non-static variables obtained from the class definition handle.
  3. Iterator to constraints returns only normal constraints and not inline constraints.
  4. To get constraints inherited from base classes, you will need to traverse the extend relation to obtain the base class.
  5. The vpiDerivedClasses iterator returns all the classes derived from the given class.
  6. The relation to vpiExtend exists whenever a one class is derived from another class (ref Section 11.12). The relation from extend to classDefn provides the base class. The iterators from extend to param assign and arguments provide the parameters and arguments used in constructor chaining (ref Section 11.16 and 11.23)

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.19 Constraint, constraint ordering, distribution,

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.19 Constraint, constraint ordering, distribution,
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.20 Constraint expression

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.20 Constraint expression
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.21 Class Variables

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.21 Class Variables
第三十一章 SystemVerilog VPI Object Model

NOTES

1) vpiWaiting/Process iterator on mailbox/semaphores will show the processes waiting on the object:

— Waiting process means either frame or task/function handle.

2) vpiMessage iterator shall return all the messages in a mailbox.

3) vpiClassDefn returns the ClassDefn which was used to create the handle. vpiActualDefn returns

the ClassDefn that handle object points to when the query is made. The difference can be seen in

the example below:

class Packet

...

endclass : Packet

class LinkedPacket extends Packet

...

endclass : LinkedPacket

LinkedPacket l = new;

Packet p = l;

In this example, the vpiClassDefn of variable "p" is Packet, but the vpiActualDefn is

"LinkedPacket".

4) vpiClassDefn/vpiActualDefn both shall return NULL for built-in classes.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.22 Structure/Union

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.22 Structure/Union
第三十一章 SystemVerilog VPI Object Model

NOTES

vpi_get_value/vpi_put_value cannot be used to access values of entire unpacked structures and unpacked unions.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.23 Named Events (supersedes IEEE 1364-2001 26.6.11)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.23 Named Events (supersedes IEEE 1364-2001 26.6.11)
第三十一章 SystemVerilog VPI Object Model

NOTE

The new iterator (vpiWaitingProcesses) returns all waiting processes, identified by their frame, for that named event.

NOTE

vpi_iterate(vpiIndex, named_event_handle) shall return the set of indices for a named event within an array, starting with the index for the named event and working outward. If the named event is not part of an array, a NULL shall be returned.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.24 Task, Function Declaration (supersedes IEEE 1364-2001 26.6.18)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.24 Task, Function Declaration (supersedes IEEE 1364-2001 26.6.18)
第三十一章 SystemVerilog VPI Object Model

NOTE

5) A Verilog HDL function shall contain an object with the same name, size, and type as the function.

6) vpiInterfaceTask/vpiInterfaceFunction shall be true if task/function is declared inside an interface or a modport of an interface.

7) For function where return type is a user-defined type, vpi_handle (vpiReturn,Function_handle) shall return the implicit variable handle representing the return of the function from which the user can get the details of that user-defined type.

8) vpiReturn will always return a var object, even for simple returns.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.25 Alias Statement

链接
第三十一章 SystemVerilog VPI Object Model, 主题
SystemVerilog 3.1a语言参考手册
31.25 Alias Statement
第三十一章 SystemVerilog VPI Object Model | 主题

Group

第三十一章 SystemVerilog VPI Object Model

主题
主题 | 描述
31.25.1 Examples | alias a=b=c=d Results in 3 aliases: alias a=d alias b=d alias c=d d is Rhs for all.
链接
第三十一章 SystemVerilog VPI Object Model, 主题


31.25.1 Examples

链接
31.25 Alias Statement
SystemVerilog 3.1a语言参考手册
31.25.1 Examples
31.25 Alias Statement

alias a=b=c=d

Results in 3 aliases:

alias a=d

alias b=d

alias c=d

d is Rhs for all.

Group

31.25 Alias Statement

链接
31.25 Alias Statement


31.26 Frames (supersedes IEEE 1364-2001 26.6.20)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.26 Frames (supersedes IEEE 1364-2001 26.6.20)
第三十一章 SystemVerilog VPI Object Model

NOTES

1) The following callbacks shall be supported on frames:

— cbStartOfFrame: triggers whenever any frame gets executed.

— cbEndOfFrame: triggers when a particular thread is deleted after all storage is deleted.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.27 Threads

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.27 Threads
第三十一章 SystemVerilog VPI Object Model

NOTES

The following callbacks shall be supported on threads

— cbStartOfThread: triggers whenever any thread is created

— cbEndOfThread: triggers when a particular thread gets deleted after storage is deleted.

— cbEnterThread: triggers whenever a particular thread resumes execution

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.28 tf call (supersedes IEEE 1364-2001 26.6.19)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.28 tf call (supersedes IEEE 1364-2001 26.6.19)
第三十一章 SystemVerilog VPI Object Model

NOTE:

1) the vpiWith relation is only available for randomize methods (see Section 12.6) and for array locator methods (see Section 4.15.1).

2) For methods (method func call, method task call), the vpiPrefix relation will return the object to which the method is being applied. For example, for the class method invocation

packet.send();

the prefix for the "send" method is the class var "packet"

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.29 Module path, path term (supersedes IEEE 1364-2001 26.6.15)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.29 Module path, path term (supersedes IEEE 1364-2001 26.6.15)
第三十一章 SystemVerilog VPI Object Model

NOTE:

1) specify blocks can occur in both modules and interfaces. For backwards compatibility the vpiModule relation has been preserved; however this relation will return NULL for specify blocks in interfaces. For new code it is recommended that the vpiInstance relation be used instead.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.30 Concurrent assertions

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.30 Concurrent assertions
第三十一章 SystemVerilog VPI Object Model

NOTE

Clocking event is always the actual clocking event on which the assertion is being evaluated, regardless of whether this is explicit or implicit (inferred)

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.31 Property Decl

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.31 Property Decl
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.32 Property Specification

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.32 Property Specification
第三十一章 SystemVerilog VPI Object Model

NOTE

Variables are declarations of property variables. You cannot get the value of these variables.

NOTES:

1. within the context of a property expr, vpiOpType can be any one of vpiNotOp, vpiImplyOp, vpiDelayedImplyOp, vpiAndOp, vpiOrOp, vpiIfOp, vpiIfElseOp

Operands to these operations will be provided in the same order as show in the BNF.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.33 Multiclock Sequence Expression

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.33 Multiclock Sequence Expression
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.34 Sequence Declaration

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.34 Sequence Declaration
第三十一章 SystemVerilog VPI Object Model

NOTE:

the vpiArgument iterator shall return the sequence instance arguments in the order that the formals for the sequence are declared, so that the correspondence between each argument and its respective formal can be made. If a formal has a default value, that value will appear as the argument should the instantiation not provide a value for that argument.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.35 Sequence Expression

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.35 Sequence Expression
第三十一章 SystemVerilog VPI Object Model

Notes:

2. Within a sequence expression, vpiOpType can be any one of vpiAndOp, vpiIntersectOp, vpiOr, vpiFirstMatchOp, vpiThroughoutOp, vpiWithinOp, vpiUnaryCycleDelayOp, vpiCycleDelayOp, vpiRepeatOp, vpiConsecutiveRepeatOp or vpiGotoRepeatOp.

3. For operations, the operands are provided in the same order as the operands appear in BNF, with the following exceptions:

vpiUnaryCycleDelayOp: arguments will be: sequence, left range, right range. Right range will only be given if different than left range.

vpiCycleDelayOp: argument will be: LHS sequence, rhs sequence, left range, right range. Right range will only be provided if different than left range.

all the repeat operators: the first argument will be the sequence being repeated, the next argument will be the left repeat bound, followed by the right repeat bound. The right repeat bound will only be provided if different than left repeat bound.

and, intersect, or,

first_match,

throughout, within,

##,

[*], [=], [->]

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.36 Attribute (supersedes IEEE 1364-2001 26.6.42)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.36 Attribute (supersedes IEEE 1364-2001 26.6.42)
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.37 Atomic Statement (supersedes IEEE 1364-2001 26.6.27)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.37 Atomic Statement (supersedes IEEE 1364-2001 26.6.27)
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.38 If, if else, return, case, do while (supersedes IEEE 1364-2001 26.6.35, 26.6.36)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.38 If, if else, return, case, do while (supersedes IEEE 1364-2001 26.6.35, 26.6.36)
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.39 waits, disables, expect, foreach (supersedes IEEE 1364 26.6.38)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.39 waits, disables, expect, foreach (supersedes IEEE 1364 26.6.38)
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.40 Simple expressions (supersedes IEEE 1364-2001 26.6.25)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.40 Simple expressions (supersedes IEEE 1364-2001 26.6.25)
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.41 Expressions (supersedes IEEE 1364-2001 26.6.26)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.41 Expressions (supersedes IEEE 1364-2001 26.6.26)
第三十一章 SystemVerilog VPI Object Model

NOTES:

1) For an operator whose type is vpiMultiConcat, the first operand shall be the multiplier expression. The remaining operands shall be the expressions within the concatenation.

2) The property vpiDecompile will return a string with a functionally equivalent expression to the original expression within the HDL. Parenthesis shall be added only to preserve precedence. Each operand and operator shall be separated by a single space character. No additional white space shall be added due to parenthesis.

3) New vpiOpTypes: vpiInsideOp, vpiMatchOp, vpiCastOp, vpiPreIncOp, vpiPostIncOp, vpiPreDecOp, vpiPostDecOp, vpiIffOp, vpiCycleDelayOp. The cast operation is represented as a unary operation, with its sole argument being the expression being cast, and the typespec of the cast expression being the type to which the argument is being cast.

4) New vpiConstType: vpiNullConst, vpiOneStepConst, vpiUnboundedConst. The constant vpiUnboundedConst represents the $ value used in assertion ranges.

5) The one to one relation to typespec must always be available for vpiCastOp operations and for simple expressions. For other expressions it is implementation dependent whether there is any associated typespec.

6) Variable slices are represented by part-selects whose parent simple expression is an array variable.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.42 Event control (supersedes IEEE 1364-2001 26.6.30)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.42 Event control (supersedes IEEE 1364-2001 26.6.30)
第三十一章 SystemVerilog VPI Object Model

NOTE—For event control associated with assignment, the statement shall always be NULL.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.43 Event stmt (supersedes IEEE 1364-2001 26.6.27)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.43 Event stmt (supersedes IEEE 1364-2001 26.6.27)
第三十一章 SystemVerilog VPI Object Model

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.44 Process (supersedes IEEE 1364-2001 26.6.27)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.44 Process (supersedes IEEE 1364-2001 26.6.27)
第三十一章 SystemVerilog VPI Object Model

NOTE- vpiAlwaysType can be one of: vpiAlwaysComb, vpiAlwaysFF, vpiAlwaysLatch

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


31.45 Assignment (supersedes IEEE 1364-2001 26.6.28)

链接
第三十一章 SystemVerilog VPI Object Model
SystemVerilog 3.1a语言参考手册
31.45 Assignment (supersedes IEEE 1364-2001 26.6.28)
第三十一章 SystemVerilog VPI Object Model

NOTE: vpiOpType will return vpiAssignmentOp for normal non-blocking ’=’ assignments, and the operator combined with the assignment for the operators described in section 7.3.

For example, the assignment

Copy Code
a[i] += 2;

will return vpiAddOp for the vpiOpType property.

Group

第三十一章 SystemVerilog VPI Object Model

链接
第三十一章 SystemVerilog VPI Object Model


附录A 形式语法

链接
主题
SystemVerilog 3.1a语言参考手册
附录A 形式语法
主题

The formal syntax of SystemVerilog is described using Backus-Naur Form (BNF). The conventions used are:

  • Keywords and punctuation are in bold text.
  • Syntactic categories are named in non-bold text.
  • A vertical bar (|) separates alternatives.
  • Square brackets ([]) enclose optional items.
  • Braces ({}) enclose items which can be repeated zero or more times.
The full syntax and semantics of Verilog and SystemVerilog are not described solely using BNF. The normative text description contained within the chapters of the IEEE 1364-2001 Verilog standard and this SystemVerilog document provide additional details on the syntax and semantics described in this BNF.

主题
主题
描述
A.1 源文本
A.2 声明
A.3 Primitive instances
A.4 Module, interface and generated instantiation
A.5 UDP declaration and instantiation
A.6 Behavioral statements
A.7 Specify section
A.8 Expressions
A.9 General
A.10 Footnotes (normative)
  1. Embedded spaces are illegal.
  2. A simple_identifier, c_identifier, and arrayed_reference shall start with an alpha or underscore ( _ ) character, shall have at least one character, and shall not have any spaces.
  3. The $ character in a system_tf_identifier shall not be followed by white_space. A system_tf_identifier shall not be escaped.
  4. End of file.
  5. The unsigned number or fixed point number in time_literal shall not be followed by a white_space.
  6. implicit_class_handle shall only appear within the scope of a class_declaration or out-of-block method declaration.
  7. In any one declaration, only one of protected or local is allowed, only one of rand or... more
链接
主题


A.1 源文本

链接
附录A 形式语法, 主题
SystemVerilog 3.1a语言参考手册
A.1 源文本
附录A 形式语法 | 主题
Group

附录A 形式语法

主题
主题
描述
A.1.1 库源文本
A.1.2 配置源文本
A.1.3 模块和原语源文本
A.1.4 模块参数和端口
A.1.5 模块条目
A.1.6 接口条目
A.1.7 程序条目
A.1.8 类条目
A.1.9 Constraints
constraint_declaration ::= [ static ] constraint constraint_identifier constraint_block
constraint_block ::= { { constraint_block_item } }
constraint_block_item ::=
solve identifier_list before identifier_list ;
| constraint_expression
constraint_expression ::=
expression_or_dist ;
| expression –> constraint_set
| if ( expression ) constraint_set [ else constraint_set ]
| foreach ( array_identifier [ loop_variables ] ) constraint_set
constraint_set ::=
constraint_expression
| { { constraint_expression } }
dist_list ::= dist_item { , dist_item }
dist_item ::= value_range [ dist_weight ]
dist_weight ::=
:= expression
| :/ expression
constraint_prototype ::= [ static ] constraint constraint_identifier ;
extern_constraint_declaration ::=
[ static ] constraint class_scope constraint_identifier constraint_block
identifier_list ::= identifier... more
A.1.10 Package items
package_item ::=
package_or_generate_item_declaration
| specparam_declaration
| anonymous_program
| timeunits_declaration18
package_or_generate_item_declaration ::=
net_declaration
| data_declaration
| task_declaration
| function_declaration
| dpi_import_export
| extern_constraint_declaration
| class_declaration
| class_constructor_declaration
| parameter_declaration ;
| local_parameter_declaration
| covergroup_declaration
| overload_declaration
| concurrent_assertion_item_declaration
| ;
anonymous_program ::= program ; { anonymous_program_item } endprogram
anonymous_program_item ::=
task_declaration
| function_declaration
| class_declaration
| covergroup_declaration
| class_constructor_declaration
| ;
链接
附录A 形式语法, 主题


A.1.1 库源文本

链接
A.1 源文本
SystemVerilog 3.1a语言参考手册
A.1.1 库源文本
A.1 源文本
Copy Code
library_text ::= {library_descriptions}

library_descriptions ::=
    library_declaration
  | include_statement
  | config_declaration
  | ;

library_declaration ::=
    library library_identifier file_path_spec{, file_path_spec}
        [-incdir file_path_spec{, file_path_spec}];

file_path_spec ::= file_path

include_statement ::= include file_path_spec;
Group

A.1 源文本

链接
A.1 源文本


A.1.2 配置源文本

链接
A.1 源文本
SystemVerilog 3.1a语言参考手册
A.1.2 配置源文本
A.1 源文本
Copy Code
config_declaration ::=
    config config_identifier;
        design_statement
        {config_rule_statement}
    endconfig[: config_identifier]

design_statement ::= design {[library_identifier.]cell_identifier};

config_rule_statement ::=
    default_clause liblist_clause
  | inst_clause liblist_clause
  | inst_clause use_clause
  | cell_clause liblist_clause
  | cell_clause use_clause
  | ;

default_clause ::= default

inst_clause ::= instance inst_name

inst_name ::= topmodule_identifier{.instance_identifier}

cell_clause ::= cell [library_identifier.]cell_identifier

liblist_clause ::= liblist {library_identifier}

use_clause ::= use [library_identifier.]cell_identifier[: config]
Group

A.1 源文本

链接
A.1 源文本


A.1.3 模块和原语源文本

链接
A.1 源文本
SystemVerilog 3.1a语言参考手册
A.1.3 模块和原语源文本
A.1 源文本
Copy Code
source_text ::= [timeunits_declaration] {description}

description ::=
    module_declaration
  | udp_declaration
  | interface_declaration
  | program_declaration
  | package_declaration
  | {attribute_instance} package_item
  | {attribute_instance} bind_directive

module_nonansi_header ::=
    {attribute_instance} module_keyword [lifetime] module_identifier [parameter_port_list]
        list_of_ports;

module_ansi_header ::=
    {attribute_instance} module_keyword [lifetime] module_identifier [parameter_port_list]
        [list_of_port_declarations];

module_declaration ::=
    module_nonansi_header [timeunits_declaration] {module_item}
        endmodule[: module_identifier]
  | module_ansi_header [timeunits_declaration] {non_port_module_item}
        endmodule[: module_identifier]
  | {attribute_instance} module_keyword [lifetime] module_identifier(.*);
        [timeunits_declaration] {module_item} endmodule[: module_identifier]
  | extern module_nonansi_header
  | extern module_ansi_header

module_keyword ::= module | macromodule

interface_nonansi_header ::=
    {attribute_instance} interface [lifetime] interface_identifier
        [parameter_port_list] list_of_ports;

interface_ansi_header ::=
    {attribute_instance} interface [lifetime] interface_identifier
        [parameter_port_list] [list_of_port_declarations];

interface_declaration ::=
    interface_nonansi_header [timeunits_declaration] {interface_item}
        endinterface [: interface_identifier]
  | interface_ansi_header [timeunits_declaration] {non_port_interface_item}
        endinterface [: interface_identifier]
  | {attribute_instance} interface interface_identifier(.*);
        [timeunits_declaration] {interface_item}
        endinterface [: interface_identifier]
  | extern interface_nonansi_header
  | extern interface_ansi_header

program_nonansi_header ::=
    {attribute_instance} program [lifetime] program_identifier
        [parameter_port_list] list_of_ports;

program_ansi_header ::=
    {attribute_instance} program [lifetime] program_identifier
        [parameter_port_list] [list_of_port_declarations];

program_declaration ::=
    program_nonansi_header [timeunits_declaration] {program_item}
        endprogram [: program_identifier]
  | program_ansi_header [timeunits_declaration] {non_port_program_item}
        endprogram [: program_identifier]
  | {attribute_instance} program program_identifier (.*);
        [timeunits_declaration] {program_item}
    endprogram [: program_identifier]
  | extern program_nonansi_header
  | extern program_ansi_header

class_declaration ::=
    [virtual] class [lifetime] class_identifier [parameter_port_list]
        [extends class_type [(list_of_arguments)]];
        {class_item}
    endclass [: class_identifier]

package_declaration ::=
    {attribute_instance} package package_identifier;
        [timeunits_declaration] {{attribute_instance} package_item}
    endpackage [: package_identifier]

timeunits_declaration ::=
    timeunit time_literal;
  | timeprecision time_literal;
  | timeunit time_literal;
    timeprecision time_literal;
  | timeprecision time_literal;
    timeunit time_literal;
Group

A.1 源文本

链接
A.1 源文本


A.1.4 模块参数和端口

链接
A.1 源文本
SystemVerilog 3.1a语言参考手册
A.1.4 模块参数和端口
A.1 源文本
Copy Code
parameter_port_list ::=
    #(list_of_param_assignments{,parameter_port_declaration})
  | #(parameter_port_declaration{,parameter_port_declaration})

parameter_port_declaration ::=
    parameter_declaration
  | data_type list_of_param_assignments
  | type list_of_type_assignments

list_of_ports ::= (port{,port})

list_of_port_declarations26 ::=
    ([{attribute_instance} ansi_port_declaration
        {,{attribute_instance} ansi_port_declaration}])

port_declaration ::=
    {attribute_instance} inout_declaration
  | {attribute_instance} input_declaration
  | {attribute_instance} output_declaration
  | {attribute_instance} ref_declaration
  | {attribute_instance} interface_port_declaration

port ::=
    [port_expression]
  | .port_identifier([port_expression])

port_expression ::=
    port_reference
  | {port_reference{,port_reference}}

port_reference ::=
    port_identifier constant_select

port_direction ::= input | output | inout | ref

net_port_header ::= [port_direction] port_type

variable_port_header ::= [port_direction] data_type

interface_port_header ::=
    interface_identifier [.modport_identifier]
  | interface [.modport_identifier]

ansi_port_declaration ::=
    [net_port_header | interface_port_header] port_identifier {unpacked_dimension}
  | [variable_port_header] port_identifier variable_dimension [= constant_expression]
  | [net_port_header | variable_port_header].port_identifier ([expression])
Group

A.1 源文本

链接
A.1 源文本


A.1.5 模块条目

链接
A.1 源文本
SystemVerilog 3.1a语言参考手册
A.1.5 模块条目
A.1 源文本
Copy Code
module_common_item ::=
    module_or_generate_item_declaration
  | interface_instantiation
  | program_instantiation
  | concurrent_assertion_item
  | bind_directive
  | continuous_assign
  | net_alias
  | initial_construct
  | final_construct
  | always_construct

module_item ::=
    port_declaration;
  | non_port_module_item

module_or_generate_item ::=
    {attribute_instance} parameter_override
  | {attribute_instance} gate_instantiation
  | {attribute_instance} udp_instantiation
  | {attribute_instance} module_instantiation
  | {attribute_instance} module_common_item

module_or_generate_item_declaration ::=
    package_or_generate_item_declaration
  | genvar_declaration
  | clocking_declaration
  | default clocking clocking_identifier;

non_port_module_item ::=
    generated_module_instantiation
  | module_or_generate_item
  | specify_block
  | {attribute_instance} specparam_declaration
  | program_declaration
  | module_declaration
  | timeunits_declaration18

parameter_override ::= defparam list_of_defparam_assignments;

bind_directive ::= bind hierarchical_identifier constant_select bind_instantiation;

bind_instantiation ::=
    program_instantiation
  | module_instantiation
  | interface_instantiation
Group

A.1 源文本

链接
A.1 源文本


A.1.6 接口条目

链接
A.1 源文本
SystemVerilog 3.1a语言参考手册
A.1.6 接口条目
A.1 源文本
Copy Code
interface_or_generate_item ::=
    {attribute_instance} module_common_item
  | {attribute_instance} modport_declaration
  | {attribute_instance} extern_tf_declaration

extern_tf_declaration ::=
    extern method_prototype;
  | extern forkjoin task_prototype;

interface_item ::=
    port_declaration;
  | non_port_interface_item

non_port_interface_item ::=
    generated_interface_instantiation
  | {attribute_instance} specparam_declaration
  | interface_or_generate_item
  | program_declaration
  | interface_declaration
  | timeunits_declaration18
Group

A.1 源文本

链接
A.1 源文本


A.1.7 程序条目

链接
A.1 源文本
SystemVerilog 3.1a语言参考手册
A.1.7 程序条目
A.1 源文本
Copy Code
program_item ::=
    port_declaration;
  | non_port_program_item

non_port_program_item ::=
    {attribute_instance} continuous_assign
  | {attribute_instance} module_or_generate_item_declaration
  | {attribute_instance} specparam_declaration
  | {attribute_instance} initial_construct
  | {attribute_instance} concurrent_assertion_item
  | {attribute_instance} timeunits_declaration18
Group

A.1 源文本

链接
A.1 源文本


A.1.8 类条目

链接
A.1 源文本
SystemVerilog 3.1a语言参考手册
A.1.8 类条目
A.1 源文本
Copy Code
class_item ::=
    {attribute_instance} class_property
  | {attribute_instance} class_method
  | {attribute_instance} class_constraint
  | {attribute_instance} type_declaration
  | {attribute_instance} class_declaration
  | {attribute_instance} timeunits_declaration18
  | ;

class_property ::=
    {property_qualifier} data_declaration
  | const {class_item_qualifier} data_type const_identifier [= constant_expression];

class_method ::=
    {method_qualifier} task_declaration
  | {method_qualifier} function_declaration
  | extern {method_qualifier} method_prototype ;
  | {method_qualifier} class_constructor_declaration
  | extern {method_qualifier} class_constructor_prototype

class_constructor_prototype ::=
    function new([tf_port_list]);

class_constraint ::=
    constraint_prototype
  | constraint_declaration

class_item_qualifier7 ::=
    static
  | protected
  | local

property_qualifier7 ::=
    rand
  | randc
  | class_item_qualifier

method_qualifier7 ::=
    virtual
  | class_item_qualifier

method_prototype ::=
    task_prototype;
  | function_prototype;

class_constructor_declaration ::=
    function [class_scope] new[([tf_port_list])];
        {block_item_declaration}
        [super.new[(list_of_arguments)];]
        {function_statement_or_null}
    endfunction [: new]
Group

A.1 源文本

链接
A.1 源文本


A.1.9 Constraints

链接
A.1 源文本
SystemVerilog 3.1a语言参考手册
A.1.9 Constraints
A.1 源文本

constraint_declaration ::= [ static ] constraint constraint_identifier constraint_block

constraint_block ::= { { constraint_block_item } }

constraint_block_item ::=

solve identifier_list before identifier_list ;

| constraint_expression

constraint_expression ::=

expression_or_dist ;

| expression –> constraint_set

| if ( expression ) constraint_set [ else constraint_set ]

| foreach ( array_identifier [ loop_variables ] ) constraint_set

constraint_set ::=

constraint_expression

| { { constraint_expression } }

dist_list ::= dist_item { , dist_item }

dist_item ::= value_range [ dist_weight ]

dist_weight ::=

:= expression

| :/ expression

constraint_prototype ::= [ static ] constraint constraint_identifier ;

extern_constraint_declaration ::=

[ static ] constraint class_scope constraint_identifier constraint_block

identifier_list ::= identifier { , identifier }

Group

A.1 源文本

链接
A.1 源文本


A.1.10 Package items

链接
A.1 源文本
SystemVerilog 3.1a语言参考手册
A.1.10 Package items
A.1 源文本

package_item ::=

package_or_generate_item_declaration

| specparam_declaration

| anonymous_program

| timeunits_declaration18

package_or_generate_item_declaration ::=

net_declaration

| data_declaration

| task_declaration

| function_declaration

| dpi_import_export

| extern_constraint_declaration

| class_declaration

| class_constructor_declaration

| parameter_declaration ;

| local_parameter_declaration

| covergroup_declaration

| overload_declaration

| concurrent_assertion_item_declaration

| ;

anonymous_program ::= program ; { anonymous_program_item } endprogram

anonymous_program_item ::=

task_declaration

| function_declaration

| class_declaration

| covergroup_declaration

| class_constructor_declaration

| ;

Group

A.1 源文本

链接
A.1 源文本


A.2 声明

链接
附录A 形式语法, 主题
SystemVerilog 3.1a语言参考手册
A.2 声明
附录A 形式语法 | 主题
Group

附录A 形式语法

主题
主题
描述
A.2.1 声明类型
A.2.2 Declaration data types
A.2.3 Declaration lists
list_of_defparam_assignments ::= defparam_assignment { , defparam_assignment }
list_of_genvar_identifiers ::= genvar_identifier { , genvar_identifier }
list_of_interface_identifiers ::= interface_identifier { unpacked_dimension }
{ , interface_identifier { unpacked_dimension } }
list_of_net_decl_assignments ::= net_decl_assignment { , net_decl_assignment }
list_of_net_identifiers ::= net_identifier { unpacked_dimension }
{ , net_identifier { unpacked_dimension } }
list_of_param_assignments ::= param_assignment { , param_assignment }
list_of_port_identifiers ::= port_identifier { unpacked_dimension }
{ , port_identifier { unpacked_dimension } }
list_of_udp_port_identifiers ::= port_identifier { , port_identifier }
list_of_specparam_assignments ::= specparam_assignment { , specparam_assignment }
list_of_tf_variable_identifiers ::= port_identifier variable_dimension [ = expression ]
{ , port_identifier variable_dimension [ = expression ] }
list_of_type_assignments ::=... more
A.2.4 Declaration assignments
defparam_assignment ::= hierarchical_parameter_identifier = constant_mintypmax_expression
net_decl_assignment ::= net_identifier { unpacked_dimension } [ = expression ]
param_assignment ::= parameter_identifier { unpacked_dimension } = constant_param_expression
specparam_assignment ::=
specparam_identifier = constant_mintypmax_expression
| pulse_control_specparam
type_assignment ::= type_identifier = data_type
pulse_control_specparam ::=
PATHPULSE$ = ( reject_limit_value [ , error_limit_value ] ) ;
| PATHPULSE$specify_input_terminal_descriptor$specify_output_terminal_descriptor
= ( reject_limit_value [ , error_limit_value ] ) ;
error_limit_value ::= limit_value
reject_limit_value ::= limit_value
limit_value ::= constant_mintypmax_expression
variable_decl_assignment ::=
variable_identifier variable_dimension [ = expression ]
| dynamic_array_variable_identifier [ ] [ = dynamic_array_new ]
| class_variable_identifier [ = class_new ]
| [ covergroup_variable_identifier ] = new [ ( list_of_arguments ) ]16... more
A.2.5 Declaration ranges
unpacked_dimension ::= [ constant_range ]
| [ constant_expression ]
packed_dimension11 ::=
[ constant_range ]
| unsized_dimension
associative_dimension ::=
[ data_type ]
| [ * ]
variable_dimension12 ::=
{ sized_or_unsized_dimension }
| associative_dimension
| queue_dimension
queue_dimension ::= [ $ [ : constant_expression ] ]
unsized_dimension11 ::= [ ]
sized_or_unsized_dimension ::= unpacked_dimension | unsized_dimension
A.2.6 Function declarations
function_data_type ::= data_type | void
function_data_type_or_implicit ::=
function_data_type
| [ signing ] { packed_dimension }
function_declaration ::= function [ lifetime ] function_body_declaration
function_body_declaration ::=
function_data_type_or_implicit
[ interface_identifier . | class_scope ] function_identifier ;
{ tf_item_declaration }
{ function_statement_or_null }
endfunction [ : function_identifier ]
| function_data_type_or_implicit
[ interface_identifier . | class_scope ] function_identifier ( [ tf_port_list ] ) ;
{ block_item_declaration }
{ function_statement_or_null }
endfunction [ : function_identifier ]
function_prototype ::= function function_data_type function_identifier ( [ tf_port_list ] )
dpi_import_export ::=
import "DPI" [ dpi_function_import_property ] [ c_identifier = ] dpi_function_proto ;
| import "DPI" [ dpi_task_import_property ] [... more
A.2.7 Task declarations
task_declaration ::= task [ lifetime ] task_body_declaration
task_body_declaration ::=
[ interface_identifier . | class_scope ] task_identifier ;
{ tf_item_declaration }
{ statement_or_null }
endtask [ : task_identifier ]
| [ interface_identifier . | class_scope ] task_identifier ( [ tf_port_list ] ) ;
{ block_item_declaration }
{ statement_or_null }
endtask [ : task_identifier ]
tf_item_declaration ::=
block_item_declaration
| tf_port_declaration
tf_port_list ::=
tf_port_item { , tf_port_item }
tf_port_item ::=
{ attribute_instance }
[ tf_port_direction ] data_type_or_implicit
port_identifier variable_dimension [ = expression ]
tf_port_direction ::= port_direction | const ref
tf_port_declaration ::=
{ attribute_instance } tf_port_direction data_type_or_implicit list_of_tf_variable_identifiers ;
task_prototype ::= task task_identifier (... more
A.2.8 Block item declarations
block_item_declaration ::=
{ attribute_instance } data_declaration
| { attribute_instance } local_parameter_declaration
| { attribute_instance } parameter_declaration ;
| { attribute_instance } overload_declaration
overload_declaration ::=
bind overload_operator function data_type function_identifier ( overload_proto_formals ) ;
overload_operator ::= + | ++ | – | – – | * | ** | / | % | == | != | < | <= | > | >= | =
overload_proto_formals ::= data_type {, data_type}
A.2.9 Interface declarations
virtual_interface_declaration ::=
virtual [ interface ] interface_identifier list_of_virtual_interface_decl ;
modport_declaration ::= modport modport_item { , modport_item } ;
modport_item ::= modport_identifier ( modport_ports_declaration { , modport_ports_declaration } )
modport_ports_declaration ::=
{ attribute_instance } modport_simple_ports_declaration
| { attribute_instance } modport_hierarchical_ports_declaration
| { attribute_instance } modport_tf_ports_declaration
| { attribute_instance } modport_clocking_declaration
modport_clocking_declaration ::= clocking clocking_identifier
modport_simple_ports_declaration ::=
port_direction modport_simple_port { , modport_simple_port }
modport_simple_port ::=
port_identifier
| . port_identifier ( [ expression ] )
modport_hierarchical_ports_declaration ::=
interface_instance_identifier [ [ constant_expression ] ] . modport_identifier
modport_tf_ports_declaration ::=
import_export modport_tf_port { , modport_tf_port }
modport_tf_port ::=
method_prototype
| tf_identifier
import_export ::= import | export... more
A.2.10 Assertion declarations
concurrent_assertion_item ::= [ block_identifier : ] concurrent_assertion_statement
concurrent_assertion_statement ::=
assert_property_statement
| assume_property_statement
| cover_property_statement
assert_property_statement::=
assert property ( property_spec ) action_block
assume_property_statement::=
assume property ( property_spec ) ;
cover_property_statement::=
cover property ( property_spec ) statement_or_null
expect_property_statement ::=
expect ( property_spec ) action_block
property_instance ::=
ps_property_identifier [ ( [ actual_arg_list ] ) ]
concurrent_assertion_item_declaration ::=
property_declaration
| sequence_declaration
property_declaration ::=
property property_identifier [ ( [ list_of_formals ] ) ] ;
{ assertion_variable_declaration }
property_spec ;
endproperty [ : property_identifier ]
property_spec ::=
[clocking_event ] [ disable iff ( expression_or_dist ) ] property_expr
property_expr ::=
sequence_expr
| ( property_expr )
| not... more
A.2.11 Covergroup declarations
covergroup_declaration ::=
covergroup covergroup_identifier [ ( [ tf_port_list ] ) ] [ coverage_event ] ;
{ coverage_spec_or_option ; }
endgroup [ : covergroup_identifier ]
coverage_spec_or_option ::=
{attribute_instance} coverage_spec
| {attribute_instance} coverage_option ;
coverage_option ::=
option.member_identifier = expression
| type_option.member_identifier = expression
coverage_spec ::=
cover_point
| cover_cross
coverage_event ::=
clocking_event
| @@( block_event_expression )
block_event_expression :: =
block_event_expression or block_event_expression
| begin hierarchical_btf_identifier
| end hierarchical_btf_identifier
hierarchical_btf_identifier :: =
hierarchical_tf_identifier
| hierarchical_block_identifier
| hierarchical _identifier [ class_scope ] method_identifier
cover_point ::= [ cover_point_identifer : ] coverpoint expression [ iff ( expression ) ] bins_or_empty
bins_or_empty ::=
{ {attribute_instance} { bins_or_options ;... more
链接
附录A 形式语法, 主题


A.2.1 声明类型

链接
A.2 声明, 主题
SystemVerilog 3.1a语言参考手册
A.2.1 声明类型
A.2 声明 | 主题
Group

A.2 声明

主题
主题
描述
A.2.1.1 模块参数声明
A.2.1.2 Port declarations
inout_declaration ::=
inout port_type list_of_port_identifiers
input_declaration ::=
input port_type list_of_port_identifiers
| input data_type list_of_variable_identifiers
output_declaration ::=
output port_type list_of_port_identifiers
| output data_type list_of_variable_port_identifiers
interface_port_declaration ::=
interface_identifier list_of_interface_identifiers
| interface_identifier . modport_identifier list_of_interface_identifiers
ref_declaration ::= ref data_type list_of_port_identifiers
A.2.1.3 Type declarations
data_declaration15 ::=
[ const ] [ lifetime ] variable_declaration
| type_declaration
| package_import_declaration
| virtual_interface_declaration
package_import_declaration ::=
import package_import_item { , package_import_item } ;
package_import_item ::=
package_identifier :: identifier
| package_identifier :: *
genvar_declaration ::= genvar list_of_genvar_identifiers ;
net_declaration14 ::=
net_type_or_trireg [ drive_strength | charge_strength ] [ vectored | scalared ]
[ signing ] { packed_dimension } [ delay3 ] list_of_net_decl_assignments ;
type_declaration ::=
typedef data_type type_identifier variable_dimension ;
| typedef interface_instance_identifier . type_identifier type_identifer ;
| typedef [ enum | struct | union | class ] type_identifier ;
variable_declaration ::=
data_type list_of_variable_decl_assignments ;
lifetime ::= static | automatic
链接
A.2 声明, 主题


A.2.1.1 模块参数声明

链接
A.2.1 声明类型
SystemVerilog 3.1a语言参考手册
A.2.1.1 模块参数声明
A.2.1 声明类型
Copy Code
local_parameter_declaration ::=
    localparam data_type_or_implicit list_of_param_assignments;

parameter_declaration ::=
    parameter data_type_or_implicit list_of_param_assignments
  | parameter type list_of_type_assignments

specparam_declaration ::=
    specparam [packed_dimension] list_of_specparam_assignments;
Group

A.2.1 声明类型

链接
A.2.1 声明类型


A.2.1.2 Port declarations

链接
A.2.1 声明类型
SystemVerilog 3.1a语言参考手册
A.2.1.2 Port declarations
A.2.1 声明类型

inout_declaration ::=

inout port_type list_of_port_identifiers

input_declaration ::=

input port_type list_of_port_identifiers

| input data_type list_of_variable_identifiers

output_declaration ::=

output port_type list_of_port_identifiers

| output data_type list_of_variable_port_identifiers

interface_port_declaration ::=

interface_identifier list_of_interface_identifiers

| interface_identifier . modport_identifier list_of_interface_identifiers

ref_declaration ::= ref data_type list_of_port_identifiers

Group

A.2.1 声明类型

链接
A.2.1 声明类型


A.2.1.3 Type declarations

链接
A.2.1 声明类型
SystemVerilog 3.1a语言参考手册
A.2.1.3 Type declarations
A.2.1 声明类型

data_declaration15 ::=

[ const ] [ lifetime ] variable_declaration

| type_declaration

| package_import_declaration

| virtual_interface_declaration

package_import_declaration ::=

import package_import_item { , package_import_item } ;

package_import_item ::=

package_identifier :: identifier

| package_identifier :: *

genvar_declaration ::= genvar list_of_genvar_identifiers ;

net_declaration14 ::=

net_type_or_trireg [ drive_strength | charge_strength ] [ vectored | scalared ]

[ signing ] { packed_dimension } [ delay3 ] list_of_net_decl_assignments ;

type_declaration ::=

typedef data_type type_identifier variable_dimension ;

| typedef interface_instance_identifier . type_identifier type_identifer ;

| typedef [ enum | struct | union | class ] type_identifier ;

variable_declaration ::=

data_type list_of_variable_decl_assignments ;

lifetime ::= static | automatic

Group

A.2.1 声明类型

链接
A.2.1 声明类型


A.2.2 Declaration data types

链接
A.2 声明, 主题
SystemVerilog 3.1a语言参考手册
A.2.2 Declaration data types
A.2 声明 | 主题
Group

A.2 声明

主题
主题 | 描述
A.2.2.1 Net and variable types | casting_type ::= simple_type | size | signing data_type ::= integer_vector_type [ signing ] { packed_dimension } | integer_atom_type [ signing ] | non_integer_type | struct_union [ packed [ signing ] ] { struct_union_member { struct_union_member } } { packed_dimension }13 | enum [ enum_base_type ] { enum_name_declaration { , enum_name_declaration } } | string | chandle | virtual [ interface ] interface_identifier | [ class_scope | package_scope ] type_identifier { packed_dimension } | class_type | event | ps_covergroup_identifier data_type_or_implicit ::= data_type | [ signing ] { packed_dimension } enum_base_type ::= integer_atom_type [ signing ] | integer_vector_type [ signing ] [... more
A.2.2.2 Strengths | drive_strength ::= ( strength0 , strength1 ) | ( strength1 , strength0 ) | ( strength0 , highz1 ) | ( strength1 , highz0 ) | ( highz0 , strength1 ) | ( highz1 , strength0 ) strength0 ::= supply0 | strong0 | pull0 | weak0 strength1 ::= supply1 | strong1 | pull1 | weak1 charge_strength ::= ( small ) | ( medium ) | ( large )
A.2.2.3 Delays | delay3 ::= # delay_value | # ( mintypmax_expression [ , mintypmax_expression [ , mintypmax_expression ] ] ) delay2 ::= # delay_value | # ( mintypmax_expression [ , mintypmax_expression ] ) delay_value ::= unsigned_number | real_number | ps_identifier | time_literal
链接
A.2 声明, 主题


A.2.2.1 Net and variable types

链接
A.2.2 Declaration data types
SystemVerilog 3.1a语言参考手册
A.2.2.1 Net and variable types
A.2.2 Declaration data types

casting_type ::= simple_type | size | signing

data_type ::=

integer_vector_type [ signing ] { packed_dimension }

| integer_atom_type [ signing ]

| non_integer_type

| struct_union [ packed [ signing ] ] { struct_union_member { struct_union_member } }

{ packed_dimension }13

| enum [ enum_base_type ] { enum_name_declaration { , enum_name_declaration } }

| string

| chandle

| virtual [ interface ] interface_identifier

| [ class_scope | package_scope ] type_identifier { packed_dimension }

| class_type

| event

| ps_covergroup_identifier

data_type_or_implicit ::=

data_type

| [ signing ] { packed_dimension }

enum_base_type ::=

integer_atom_type [ signing ]

| integer_vector_type [ signing ] [ packed_dimension ]

| type_identifier [ packed_dimension ]24

enum_name_declaration ::=

enum_identifier [ [ integral_number [ : integral_number ] ] ] [ = constant_expression ]

class_scope ::= class_type ::

class_type ::=

ps_class_identifier [ parameter_value_assignment ]

{ :: class_identifier [ parameter_value_assignment ] }

integer_type ::= integer_vector_type | integer_atom_type

integer_atom_type ::= byte | shortint | int | longint | integer | time

integer_vector_type ::= bit | logic | reg

non_integer_type ::= shortreal | real | realtime

net_type ::= supply0 | supply1 | tri | triand | trior | tri0 | tri1 | wire | wand | wor

port_type ::=

[ net_type_or_trireg ] [ signing ] { packed_dimension }

net_type_or_trireg ::= net_type | trireg

signing ::= signed | unsigned

simple_type ::= integer_type | non_integer_type | ps_type_identifier

struct_union_member27 ::=

{ attribute_instance } data_type_or_void list_of_variable_identifiers ;

data_type_or_void ::= data_type | void

struct_union ::= struct | union [ tagged ]

Group

A.2.2 Declaration data types

链接
A.2.2 Declaration data types


A.2.2.2 Strengths

链接
A.2.2 Declaration data types
SystemVerilog 3.1a语言参考手册
A.2.2.2 Strengths
A.2.2 Declaration data types

drive_strength ::=

( strength0 , strength1 )

| ( strength1 , strength0 )

| ( strength0 , highz1 )

| ( strength1 , highz0 )

| ( highz0 , strength1 )

| ( highz1 , strength0 )

strength0 ::= supply0 | strong0 | pull0 | weak0

strength1 ::= supply1 | strong1 | pull1 | weak1

charge_strength ::= ( small ) | ( medium ) | ( large )

Group

A.2.2 Declaration data types

链接
A.2.2 Declaration data types


A.2.2.3 Delays

链接
A.2.2 Declaration data types
SystemVerilog 3.1a语言参考手册
A.2.2.3 Delays
A.2.2 Declaration data types

delay3 ::= # delay_value | # ( mintypmax_expression [ , mintypmax_expression [ , mintypmax_expression ] ] )

delay2 ::= # delay_value | # ( mintypmax_expression [ , mintypmax_expression ] )

delay_value ::=

unsigned_number

| real_number

| ps_identifier

| time_literal

Group

A.2.2 Declaration data types

链接
A.2.2 Declaration data types


A.2.3 Declaration lists

链接
A.2 声明
SystemVerilog 3.1a语言参考手册
A.2.3 Declaration lists
A.2 声明

list_of_defparam_assignments ::= defparam_assignment { , defparam_assignment }

list_of_genvar_identifiers ::= genvar_identifier { , genvar_identifier }

list_of_interface_identifiers ::= interface_identifier { unpacked_dimension }

{ , interface_identifier { unpacked_dimension } }

list_of_net_decl_assignments ::= net_decl_assignment { , net_decl_assignment }

list_of_net_identifiers ::= net_identifier { unpacked_dimension }

{ , net_identifier { unpacked_dimension } }

list_of_param_assignments ::= param_assignment { , param_assignment }

list_of_port_identifiers ::= port_identifier { unpacked_dimension }

{ , port_identifier { unpacked_dimension } }

list_of_udp_port_identifiers ::= port_identifier { , port_identifier }

list_of_specparam_assignments ::= specparam_assignment { , specparam_assignment }

list_of_tf_variable_identifiers ::= port_identifier variable_dimension [ = expression ]

{ , port_identifier variable_dimension [ = expression ] }

list_of_type_assignments ::= type_assignment { , type_assignment }

list_of_variable_decl_assignments ::= variable_decl_assignment { , variable_decl_assignment }

list_of_variable_identifiers ::= variable_identifier variable_dimension

{ , variable_identifier variable_dimension }

list_of_variable_port_identifiers ::= port_identifier variable_dimension [ = constant_expression ]

{ , port_identifier variable_dimension [ = constant_expression ] }

list_of_virtual_interface_decl ::=

variable_identifier [ = interface_instance_identifier ]

{ , variable_identifier [ = interface_instance_identifier ] }

Group

A.2 声明

链接
A.2 声明


A.2.4 Declaration assignments

链接
A.2 声明
SystemVerilog 3.1a语言参考手册
A.2.4 Declaration assignments
A.2 声明

defparam_assignment ::= hierarchical_parameter_identifier = constant_mintypmax_expression

net_decl_assignment ::= net_identifier { unpacked_dimension } [ = expression ]

param_assignment ::= parameter_identifier { unpacked_dimension } = constant_param_expression

specparam_assignment ::=

specparam_identifier = constant_mintypmax_expression

| pulse_control_specparam

type_assignment ::= type_identifier = data_type

pulse_control_specparam ::=

PATHPULSE$ = ( reject_limit_value [ , error_limit_value ] ) ;

| PATHPULSE$specify_input_terminal_descriptor$specify_output_terminal_descriptor

= ( reject_limit_value [ , error_limit_value ] ) ;

error_limit_value ::= limit_value

reject_limit_value ::= limit_value

limit_value ::= constant_mintypmax_expression

variable_decl_assignment ::=

variable_identifier variable_dimension [ = expression ]

| dynamic_array_variable_identifier [ ] [ = dynamic_array_new ]

| class_variable_identifier [ = class_new ]

| [ covergroup_variable_identifier ] = new [ ( list_of_arguments ) ]16

class_new20 ::= new [ ( list_of_arguments ) | expression ]

dynamic_array_new ::= new [ expression ] [ ( expression ) ]

Group

A.2 声明

链接
A.2 声明


A.2.5 Declaration ranges

链接
A.2 声明
SystemVerilog 3.1a语言参考手册
A.2.5 Declaration ranges
A.2 声明

unpacked_dimension ::= [ constant_range ]

| [ constant_expression ]

packed_dimension11 ::=

[ constant_range ]

| unsized_dimension

associative_dimension ::=

[ data_type ]

| [ * ]

variable_dimension12 ::=

{ sized_or_unsized_dimension }

| associative_dimension

| queue_dimension

queue_dimension ::= [ $ [ : constant_expression ] ]

unsized_dimension11 ::= [ ]

sized_or_unsized_dimension ::= unpacked_dimension | unsized_dimension

Group

A.2 声明

链接
A.2 声明


A.2.6 Function declarations

链接
A.2 声明
SystemVerilog 3.1a语言参考手册
A.2.6 Function declarations
A.2 声明

function_data_type ::= data_type | void

function_data_type_or_implicit ::=

function_data_type

| [ signing ] { packed_dimension }

function_declaration ::= function [ lifetime ] function_body_declaration

function_body_declaration ::=

function_data_type_or_implicit

[ interface_identifier . | class_scope ] function_identifier ;

{ tf_item_declaration }

{ function_statement_or_null }

endfunction [ : function_identifier ]

| function_data_type_or_implicit

[ interface_identifier . | class_scope ] function_identifier ( [ tf_port_list ] ) ;

{ block_item_declaration }

{ function_statement_or_null }

endfunction [ : function_identifier ]

function_prototype ::= function function_data_type function_identifier ( [ tf_port_list ] )

dpi_import_export ::=

import "DPI" [ dpi_function_import_property ] [ c_identifier = ] dpi_function_proto ;

| import "DPI" [ dpi_task_import_property ] [ c_identifier = ] dpi_task_proto ;

| export "DPI" [ c_identifier = ] function function_identifier ;

| export "DPI" [ c_identifier = ] task task_identifier ;

dpi_function_import_property ::= context | pure

dpi_task_import_property ::= context

dpi_function_proto8,9 ::= function_prototype

dpi_task_proto9 ::= task_prototype

Group

A.2 声明

链接
A.2 声明


A.2.7 Task declarations

链接
A.2 声明
SystemVerilog 3.1a语言参考手册
A.2.7 Task declarations
A.2 声明

task_declaration ::= task [ lifetime ] task_body_declaration

task_body_declaration ::=

[ interface_identifier . | class_scope ] task_identifier ;

{ tf_item_declaration }

{ statement_or_null }

endtask [ : task_identifier ]

| [ interface_identifier . | class_scope ] task_identifier ( [ tf_port_list ] ) ;

{ block_item_declaration }

{ statement_or_null }

endtask [ : task_identifier ]

tf_item_declaration ::=

block_item_declaration

| tf_port_declaration

tf_port_list ::=

tf_port_item { , tf_port_item }

tf_port_item ::=

{ attribute_instance }

[ tf_port_direction ] data_type_or_implicit

port_identifier variable_dimension [ = expression ]

tf_port_direction ::= port_direction | const ref

tf_port_declaration ::=

{ attribute_instance } tf_port_direction data_type_or_implicit list_of_tf_variable_identifiers ;

task_prototype ::= task task_identifier ( [ tf_port_list ] )

Group

A.2 声明

链接
A.2 声明


A.2.8 Block item declarations

链接
A.2 声明
SystemVerilog 3.1a语言参考手册
A.2.8 Block item declarations
A.2 声明

block_item_declaration ::=

{ attribute_instance } data_declaration

| { attribute_instance } local_parameter_declaration

| { attribute_instance } parameter_declaration ;

| { attribute_instance } overload_declaration

overload_declaration ::=

bind overload_operator function data_type function_identifier ( overload_proto_formals ) ;

overload_operator ::= + | ++ | – | – – | * | ** | / | % | == | != | < | <= | > | >= | =

overload_proto_formals ::= data_type {, data_type}

Group

A.2 声明

链接
A.2 声明


A.2.9 Interface declarations

链接
A.2 声明
SystemVerilog 3.1a语言参考手册
A.2.9 Interface declarations
A.2 声明

virtual_interface_declaration ::=

virtual [ interface ] interface_identifier list_of_virtual_interface_decl ;

modport_declaration ::= modport modport_item { , modport_item } ;

modport_item ::= modport_identifier ( modport_ports_declaration { , modport_ports_declaration } )

modport_ports_declaration ::=

{ attribute_instance } modport_simple_ports_declaration

| { attribute_instance } modport_hierarchical_ports_declaration

| { attribute_instance } modport_tf_ports_declaration

| { attribute_instance } modport_clocking_declaration

modport_clocking_declaration ::= clocking clocking_identifier

modport_simple_ports_declaration ::=

port_direction modport_simple_port { , modport_simple_port }

modport_simple_port ::=

port_identifier

| . port_identifier ( [ expression ] )

modport_hierarchical_ports_declaration ::=

interface_instance_identifier [ [ constant_expression ] ] . modport_identifier

modport_tf_ports_declaration ::=

import_export modport_tf_port { , modport_tf_port }

modport_tf_port ::=

method_prototype

| tf_identifier

import_export ::= import | export

Group

A.2 声明

链接
A.2 声明


A.2.10 Assertion declarations

链接
A.2 声明
SystemVerilog 3.1a语言参考手册
A.2.10 Assertion declarations
A.2 声明

concurrent_assertion_item ::= [ block_identifier : ] concurrent_assertion_statement

concurrent_assertion_statement ::=

assert_property_statement

| assume_property_statement

| cover_property_statement

assert_property_statement::=

assert property ( property_spec ) action_block

assume_property_statement::=

assume property ( property_spec ) ;

cover_property_statement::=

cover property ( property_spec ) statement_or_null

expect_property_statement ::=

expect ( property_spec ) action_block

property_instance ::=

ps_property_identifier [ ( [ actual_arg_list ] ) ]

concurrent_assertion_item_declaration ::=

property_declaration

| sequence_declaration

property_declaration ::=

property property_identifier [ ( [ list_of_formals ] ) ] ;

{ assertion_variable_declaration }

property_spec ;

endproperty [ : property_identifier ]

property_spec ::=

[clocking_event ] [ disable iff ( expression_or_dist ) ] property_expr

property_expr ::=

sequence_expr

| ( property_expr )

| not property_expr

| property_expr or property_expr

| property_expr and property_expr

| sequence_expr |-> property_expr

| sequence_expr |=> property_expr

| if ( expression_or_dist ) property_expr [ else property_expr ]

| property_instance

| clocking_event property_expr

sequence_declaration ::=

sequence sequence_identifier [ ( [ list_of_formals ] ) ] ;

{ assertion_variable_declaration }

sequence_expr ;

endsequence [ : sequence_identifier ]

sequence_expr ::=

cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }

| sequence_expr cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }

| expression_or_dist [ boolean_abbrev ]

| ( expression_or_dist {, sequence_match_item } ) [ boolean_abbrev ]

| sequence_instance [ sequence_abbrev ]

| ( sequence_expr {, sequence_match_item } ) [ sequence_abbrev ]

| sequence_expr and sequence_expr

| sequence_expr intersect sequence_expr

| sequence_expr or sequence_expr

| first_match ( sequence_expr {, sequence_match_item} )

| expression_or_dist throughout sequence_expr

| sequence_expr within sequence_expr

| clocking_event sequence_expr

cycle_delay_range ::=

## integral_number

| ## identifier

| ## ( constant_expression )

| ## [ cycle_delay_const_range_expression ]

sequence_method_call ::=

sequence_instance . method_identifier

sequence_match_item ::=

operator_assignment

| inc_or_dec_expression

| subroutine_call

sequence_instance ::=

ps_sequence_identifier [ ( [ actual_arg_list ] ) ]

formal_list_item ::=

formal_identifier [ = actual_arg_expr ]

list_of_formals ::= formal_list_item { , formal_list_item }

actual_arg_list ::=

actual_arg_expr { , actual_arg_expr }

| . formal_identifier ( actual_arg_expr ) { , . formal_identifier ( actual_arg_expr ) }

actual_arg_expr ::=

event_expression

| $

boolean_abbrev ::=

consecutive_repetition

| non_consecutive_repetition

| goto_repetition

sequence_abbrev ::= consecutive_repetition

consecutive_repetition ::= [* const_or_range_expression ]

non_consecutive_repetition ::= [= const_or_range_expression ]

goto_repetition ::= [-> const_or_range_expression ]

const_or_range_expression ::=

constant_expression

| cycle_delay_const_range_expression

cycle_delay_const_range_expression ::=

constant_expression : constant_expression

| constant_expression : $

expression_or_dist ::= expression [ dist { dist_list } ]

assertion_variable_declaration ::=

data_type list_of_variable_identifiers ;

Group

A.2 声明

链接
A.2 声明


A.2.11 Covergroup declarations

链接
A.2 声明
SystemVerilog 3.1a语言参考手册
A.2.11 Covergroup declarations
A.2 声明

covergroup_declaration ::=

covergroup covergroup_identifier [ ( [ tf_port_list ] ) ] [ coverage_event ] ;

{ coverage_spec_or_option ; }

endgroup [ : covergroup_identifier ]

coverage_spec_or_option ::=

{attribute_instance} coverage_spec

| {attribute_instance} coverage_option ;

coverage_option ::=

option.member_identifier = expression

| type_option.member_identifier = expression

coverage_spec ::=

cover_point

| cover_cross

coverage_event ::=

clocking_event

| @@( block_event_expression )

block_event_expression :: =

block_event_expression or block_event_expression

| begin hierarchical_btf_identifier

| end hierarchical_btf_identifier

hierarchical_btf_identifier :: =

hierarchical_tf_identifier

| hierarchical_block_identifier

| hierarchical _identifier [ class_scope ] method_identifier

cover_point ::= [ cover_point_identifer : ] coverpoint expression [ iff ( expression ) ] bins_or_empty

bins_or_empty ::=

{ {attribute_instance} { bins_or_options ; } }

| ;

bins_or_options ::=

coverage_option

| [ wildcard ] bins_keyword bin_identifier [ [ [ expression ] ] ] = { range_list } [ iff ( expression ) ]

| [ wildcard] bins_keyword bin_identifier [ [ ] ] = trans_list [ iff ( expression ) ]

| bins_keyword bin_identifier [ [ [ expression ] ] ] = default [ iff ( expression ) ]

| bins_keyword bin_identifier = default sequence [ iff ( expression ) ]

bins_keyword::= bins | illegal_bins | ignore_bins

range_list ::= value_range { , value_range }

trans_list ::= ( trans_set ) { , ( trans_set ) }

trans_set ::= trans_range_list => trans_range_list { => trans_range_list }

trans_range_list ::=

trans_item

| trans_item [ [* repeat_range ] ]

| trans_item [ [–> repeat_range ] ]

| trans_item [ [= repeat_range ] ]

trans_item ::= range_list

repeat_range ::=

expression

| expression : expression

cover_cross ::= [cover_point_identifer : ] cross list_of_coverpoints [ iff ( expression ) ] select_bins_or_empty

list_of_coverpoints ::= cross_item , cross_item { , cross_item }

cross_item ::=

cover_point_identifier

| variable_identifier

select_bins_or_empty ::=

{ { bins_selections_or_option ; } }

| ;

bins_selection_or_option ::=

{ attribute_instance } coverage_option

| { attribute_instance } bins_selection

bins_selection ::= bins_keyword bin_identifier = select_expression [ iff ( expression ) ]

select_expression ::=

select_condition

| ! select_condition

| select_expression && select_expression

| select_expression || select_expression

| ( select_expression )

select_condition ::= binsof ( bins_expression ) [ intersect { open_range_list } ]

bins_expression ::=

variable_identifier

| cover_point_identifier [ . bins_identifier ]

open_range_list ::= open_value_range { , open_value_range }

open_value_range ::= value_range21

Group

A.2 声明

链接
A.2 声明


A.3 Primitive instances

链接
附录A 形式语法, 主题
SystemVerilog 3.1a语言参考手册
A.3 Primitive instances
附录A 形式语法 | 主题
Group

附录A 形式语法

主题
主题
描述
A.3.1 Primitive instantiation and instances
gate_instantiation ::=
cmos_switchtype [delay3] cmos_switch_instance { , cmos_switch_instance } ;
| enable_gatetype [drive_strength] [delay3] enable_gate_instance { , enable_gate_instance } ;
| mos_switchtype [delay3] mos_switch_instance { , mos_switch_instance } ;
| n_input_gatetype [drive_strength] [delay2] n_input_gate_instance { , n_input_gate_instance } ;
| n_output_gatetype [drive_strength] [delay2] n_output_gate_instance
{ , n_output_gate_instance } ;
| pass_en_switchtype [delay2] pass_enable_switch_instance { , pass_enable_switch_instance } ;
| pass_switchtype pass_switch_instance { , pass_switch_instance } ;
| pulldown [pulldown_strength] pull_gate_instance { , pull_gate_instance } ;
| pullup [pullup_strength] pull_gate_instance { , pull_gate_instance } ;
cmos_switch_instance ::= [ name_of_instance ] ( output_terminal , input_terminal ,
ncontrol_terminal , pcontrol_terminal )
enable_gate_instance ::=... more
A.3.2 Primitive strengths
pulldown_strength ::=
( strength0 , strength1 )
| ( strength1 , strength0 )
| ( strength0 )
pullup_strength ::=
( strength0 , strength1 )
| ( strength1 , strength0 )
| ( strength1 )
A.3.3 Primitive terminals
enable_terminal ::= expression
inout_terminal ::= net_lvalue
input_terminal ::= expression
ncontrol_terminal ::= expression
output_terminal ::= net_lvalue
pcontrol_terminal ::= expression
A.3.4 Primitive gate and switch types
cmos_switchtype ::= cmos | rcmos
enable_gatetype ::= bufif0 | bufif1 | notif0 | notif1
mos_switchtype ::= nmos | pmos | rnmos | rpmos
n_input_gatetype ::= and | nand | or | nor | xor | xnor
n_output_gatetype ::= buf | not
pass_en_switchtype ::= tranif0 | tranif1 | rtranif1 | rtranif0
pass_switchtype ::= tran | rtran
链接
附录A 形式语法, 主题


A.3.1 Primitive instantiation and instances

链接
A.3 Primitive instances
SystemVerilog 3.1a语言参考手册
A.3.1 Primitive instantiation and instances
A.3 Primitive instances

gate_instantiation ::=

cmos_switchtype [delay3] cmos_switch_instance { , cmos_switch_instance } ;

| enable_gatetype [drive_strength] [delay3] enable_gate_instance { , enable_gate_instance } ;

| mos_switchtype [delay3] mos_switch_instance { , mos_switch_instance } ;

| n_input_gatetype [drive_strength] [delay2] n_input_gate_instance { , n_input_gate_instance } ;

| n_output_gatetype [drive_strength] [delay2] n_output_gate_instance

{ , n_output_gate_instance } ;

| pass_en_switchtype [delay2] pass_enable_switch_instance { , pass_enable_switch_instance } ;

| pass_switchtype pass_switch_instance { , pass_switch_instance } ;

| pulldown [pulldown_strength] pull_gate_instance { , pull_gate_instance } ;

| pullup [pullup_strength] pull_gate_instance { , pull_gate_instance } ;

cmos_switch_instance ::= [ name_of_instance ] ( output_terminal , input_terminal ,

ncontrol_terminal , pcontrol_terminal )

enable_gate_instance ::= [ name_of_instance ] ( output_terminal , input_terminal , enable_terminal )

mos_switch_instance ::= [ name_of_instance ] ( output_terminal , input_terminal , enable_terminal )

n_input_gate_instance ::= [ name_of_instance ] ( output_terminal , input_terminal { , input_terminal } )

n_output_gate_instance ::= [ name_of_instance ] ( output_terminal { , output_terminal } ,

input_terminal )

pass_switch_instance ::= [ name_of_instance ] ( inout_terminal , inout_terminal )

pass_enable_switch_instance ::= [ name_of_instance ] ( inout_terminal , inout_terminal ,

enable_terminal )

pull_gate_instance ::= [ name_of_instance ] ( output_terminal )

Group

A.3 Primitive instances

链接
A.3 Primitive instances


A.3.2 Primitive strengths

链接
A.3 Primitive instances
SystemVerilog 3.1a语言参考手册
A.3.2 Primitive strengths
A.3 Primitive instances

pulldown_strength ::=

( strength0 , strength1 )

| ( strength1 , strength0 )

| ( strength0 )

pullup_strength ::=

( strength0 , strength1 )

| ( strength1 , strength0 )

| ( strength1 )

Group

A.3 Primitive instances

链接
A.3 Primitive instances


A.3.3 Primitive terminals

链接
A.3 Primitive instances
SystemVerilog 3.1a语言参考手册
A.3.3 Primitive terminals
A.3 Primitive instances

enable_terminal ::= expression

inout_terminal ::= net_lvalue

input_terminal ::= expression

ncontrol_terminal ::= expression

output_terminal ::= net_lvalue

pcontrol_terminal ::= expression

Group

A.3 Primitive instances

链接
A.3 Primitive instances


A.3.4 Primitive gate and switch types

链接
A.3 Primitive instances
SystemVerilog 3.1a语言参考手册
A.3.4 Primitive gate and switch types
A.3 Primitive instances

cmos_switchtype ::= cmos | rcmos

enable_gatetype ::= bufif0 | bufif1 | notif0 | notif1

mos_switchtype ::= nmos | pmos | rnmos | rpmos

n_input_gatetype ::= and | nand | or | nor | xor | xnor

n_output_gatetype ::= buf | not

pass_en_switchtype ::= tranif0 | tranif1 | rtranif1 | rtranif0

pass_switchtype ::= tran | rtran

Group

A.3 Primitive instances

链接
A.3 Primitive instances


A.4 Module, interface and generated instantiation

链接
附录A 形式语法, 主题
SystemVerilog 3.1a语言参考手册
A.4 Module, interface and generated instantiation
附录A 形式语法 | 主题
Group

附录A 形式语法

主题
主题 | 描述
A.4.1 Instantiation |
A.4.2 Generated instantiation |
链接
附录A 形式语法, 主题


A.4.1 Instantiation

链接
A.4 Module, interface and generated instantiation, 主题
SystemVerilog 3.1a语言参考手册
A.4.1 Instantiation
A.4 Module, interface and generated instantiation | 主题
Group

A.4 Module, interface and generated instantiation

主题
主题
描述
A.4.1.1 Module instantiation
module_instantiation ::=
module_identifier [ parameter_value_assignment ] hierarchical_instance { , hierarchical_instance } ;
parameter_value_assignment ::= # ( list_of_parameter_assignments )
list_of_parameter_assignments ::=
ordered_parameter_assignment { , ordered_parameter_assignment }
| named_parameter_assignment { , named_parameter_assignment }
ordered_parameter_assignment ::= param_expression
named_parameter_assignment ::= . parameter_identifier ( [ param_expression ] )
hierarchical_instance ::= name_of_instance ( [ list_of_port_connections ] )
name_of_instance ::= instance_identifier { unpacked_dimension }
list_of_port_connections17 ::=
ordered_port_connection { , ordered_port_connection }
| named_port_connection { , named_port_connection }
ordered_port_connection ::= { attribute_instance } [ expression ]
named_port_connection ::=
{ attribute_instance } . port_identifier [ ( [ expression ] ) ]
| { attribute_instance } .*
A.4.1.2 Interface instantiation
interface_instantiation ::=
interface_identifier [ parameter_value_assignment ] hierarchical_instance { , hierarchical_instance } ;
A.4.1.3 Program instantiation
program_instantiation ::=
program_identifier [ parameter_value_assignment ] hierarchical_instance { , hierarchical_instance } ;
链接
A.4 Module, interface and generated instantiation, 主题


A.4.1.1 Module instantiation

链接
A.4.1 Instantiation
SystemVerilog 3.1a语言参考手册
A.4.1.1 Module instantiation
A.4.1 Instantiation

module_instantiation ::=

module_identifier [ parameter_value_assignment ] hierarchical_instance { , hierarchical_instance } ;

parameter_value_assignment ::= # ( list_of_parameter_assignments )

list_of_parameter_assignments ::=

ordered_parameter_assignment { , ordered_parameter_assignment }

| named_parameter_assignment { , named_parameter_assignment }

ordered_parameter_assignment ::= param_expression

named_parameter_assignment ::= . parameter_identifier ( [ param_expression ] )

hierarchical_instance ::= name_of_instance ( [ list_of_port_connections ] )

name_of_instance ::= instance_identifier { unpacked_dimension }

list_of_port_connections17 ::=

ordered_port_connection { , ordered_port_connection }

| named_port_connection { , named_port_connection }

ordered_port_connection ::= { attribute_instance } [ expression ]

named_port_connection ::=

{ attribute_instance } . port_identifier [ ( [ expression ] ) ]

| { attribute_instance } .*

Group

A.4.1 Instantiation

链接
A.4.1 Instantiation


A.4.1.2 Interface instantiation

链接
A.4.1 Instantiation
SystemVerilog 3.1a语言参考手册
A.4.1.2 Interface instantiation
A.4.1 Instantiation

interface_instantiation ::=

interface_identifier [ parameter_value_assignment ] hierarchical_instance { , hierarchical_instance } ;

Group

A.4.1 Instantiation

链接
A.4.1 Instantiation


A.4.1.3 Program instantiation

链接
A.4.1 Instantiation
SystemVerilog 3.1a语言参考手册
A.4.1.3 Program instantiation
A.4.1 Instantiation

program_instantiation ::=

program_identifier [ parameter_value_assignment ] hierarchical_instance { , hierarchical_instance } ;

Group

A.4.1 Instantiation

链接
A.4.1 Instantiation


A.4.2 Generated instantiation

链接
A.4 Module, interface and generated instantiation, 主题
SystemVerilog 3.1a语言参考手册
A.4.2 Generated instantiation
A.4 Module, interface and generated instantiation | 主题
Group

A.4 Module, interface and generated instantiation

主题
主题
描述
A.4.2.1 Generated module instantiation
generated_module_instantiation ::= generate { generate_module_item } endgenerate
generate_module_item ::=
generate_module_conditional_statement
| generate_module_case_statement
| generate_module_loop_statement
| [ generate_block_identifier : ] generate_module_block
| module_or_generate_item
generate_module_conditional_statement ::=
if ( constant_expression ) generate_module_item [ else generate_module_item ]
generate_module_case_statement ::=
case ( constant_expression ) genvar_module_case_item { genvar_module_case_item }endcase
genvar_module_case_item ::=
constant_expression { , constant_expression } : generate_module_item
| default [ : ] generate_module_item
generate_module_loop_statement ::=
for ( genvar_decl_assignment ; constant_expression ; genvar_assignment )
generate_module_named_block
genvar_assignment ::=
genvar_identifier assignment_operator constant_expression
| inc_or_dec_operator genvar_identifier
| genvar_identifier inc_or_dec_operator
genvar_decl_assignment ::=
[ genvar ] genvar_identifier = constant_expression
generate_module_named_block ::=
begin : generate_block_identifier { generate_module_item } end [ : generate_block_identifier... more
A.4.2.2 Generated interface instantiation
generated_interface_instantiation ::= generate { generate_interface_item } endgenerate
generate_interface_item ::=
generate_interface_conditional_statement
| generate_interface_case_statement
| generate_interface_loop_statement
| [ generate_block_identifier : ] generate_interface_block
| interface_or_generate_item
generate_interface_conditional_statement ::=
if ( constant_expression ) generate_interface_item [ else generate_interface_item ]
generate_interface_case_statement ::=
case ( constant_expression ) genvar_interface_case_item { genvar_interface_case_item } endcase
genvar_interface_case_item ::=
constant_expression { , constant_expression } : generate_interface_item
| default [ : ] generate_interface_item
generate_interface_loop_statement ::=
for ( genvar_decl_assignment ; constant_expression ; genvar_assignment )
generate_interface_named_block
generate_interface_named_block ::=
begin : generate_block_identifier { generate_interface_item } end [ : generate_block_identifier ]
| generate_block_identifier : generate_interface_block
generate_interface_block ::=
begin [ : generate_block_identifier ]
{ generate_interface_item }
end [ :... more
链接
A.4 Module, interface and generated instantiation, 主题


A.4.2.1 Generated module instantiation

链接
A.4.2 Generated instantiation
SystemVerilog 3.1a语言参考手册
A.4.2.1 Generated module instantiation
A.4.2 Generated instantiation

generated_module_instantiation ::= generate { generate_module_item } endgenerate

generate_module_item ::=

generate_module_conditional_statement

| generate_module_case_statement

| generate_module_loop_statement

| [ generate_block_identifier : ] generate_module_block

| module_or_generate_item

generate_module_conditional_statement ::=

if ( constant_expression ) generate_module_item [ else generate_module_item ]

generate_module_case_statement ::=

case ( constant_expression ) genvar_module_case_item { genvar_module_case_item }endcase

genvar_module_case_item ::=

constant_expression { , constant_expression } : generate_module_item

| default [ : ] generate_module_item

generate_module_loop_statement ::=

for ( genvar_decl_assignment ; constant_expression ; genvar_assignment )

generate_module_named_block

genvar_assignment ::=

genvar_identifier assignment_operator constant_expression

| inc_or_dec_operator genvar_identifier

| genvar_identifier inc_or_dec_operator

genvar_decl_assignment ::=

[ genvar ] genvar_identifier = constant_expression

generate_module_named_block ::=

begin : generate_block_identifier { generate_module_item } end [ : generate_block_identifier ]

| generate_block_identifier : generate_module_block

generate_module_block ::=

begin [ : generate_block_identifier ] { generate_module_item } end [ : generate_block_identifier ]

Group

A.4.2 Generated instantiation

链接
A.4.2 Generated instantiation


A.4.2.2 Generated interface instantiation

链接
A.4.2 Generated instantiation
SystemVerilog 3.1a语言参考手册
A.4.2.2 Generated interface instantiation
A.4.2 Generated instantiation

generated_interface_instantiation ::= generate { generate_interface_item } endgenerate

generate_interface_item ::=

generate_interface_conditional_statement

| generate_interface_case_statement

| generate_interface_loop_statement

| [ generate_block_identifier : ] generate_interface_block

| interface_or_generate_item

generate_interface_conditional_statement ::=

if ( constant_expression ) generate_interface_item [ else generate_interface_item ]

generate_interface_case_statement ::=

case ( constant_expression ) genvar_interface_case_item { genvar_interface_case_item } endcase

genvar_interface_case_item ::=

constant_expression { , constant_expression } : generate_interface_item

| default [ : ] generate_interface_item

generate_interface_loop_statement ::=

for ( genvar_decl_assignment ; constant_expression ; genvar_assignment )

generate_interface_named_block

generate_interface_named_block ::=

begin : generate_block_identifier { generate_interface_item } end [ : generate_block_identifier ]

| generate_block_identifier : generate_interface_block

generate_interface_block ::=

begin [ : generate_block_identifier ]

{ generate_interface_item }

end [ : generate_block_identifier ]

Group

A.4.2 Generated instantiation

链接
A.4.2 Generated instantiation


A.5 UDP declaration and instantiation

链接
附录A 形式语法, 主题
SystemVerilog 3.1a语言参考手册
A.5 UDP declaration and instantiation
附录A 形式语法 | 主题
Group

附录A 形式语法

主题
主题
描述
A.5.1 UDP declaration
udp_nonansi_declaration ::=
{ attribute_instance } primitive udp_identifier ( udp_port_list ) ;
udp_ansi_declaration ::=
{ attribute_instance } primitive udp_identifier ( udp_declaration_port_list ) ;
udp_declaration ::=
udp_nonansi_declaration udp_port_declaration { udp_port_declaration }
udp_body
endprimitive [ : udp_identifier ]
| udp_ansi_declaration
udp_body
endprimitive [ : udp_identifier ]
| extern udp_nonansi_declaration
| extern udp_ansi_declaration
| { attribute_instance } primitive udp_identifier ( .* ) ;
{ udp_port_declaration }
udp_body
endprimitive [ : udp_identifier ]
A.5.2 UDP ports
udp_port_list ::= output_port_identifier , input_port_identifier { , input_port_identifier }
udp_declaration_port_list ::= udp_output_declaration , udp_input_declaration { , udp_input_declaration }
udp_port_declaration ::=
udp_output_declaration ;
| udp_input_declaration ;
| udp_reg_declaration ;
udp_output_declaration ::=
{ attribute_instance } output port_identifier
| { attribute_instance } output reg port_identifier [ = constant_expression ]
udp_input_declaration ::= { attribute_instance } input list_of_udp_port_identifiers
udp_reg_declaration ::= { attribute_instance } reg variable_identifier
A.5.3 UDP body
udp_body ::= combinational_body | sequential_body
combinational_body ::= table combinational_entry { combinational_entry } endtable
combinational_entry ::= level_input_list : output_symbol ;
sequential_body ::= [ udp_initial_statement ] table sequential_entry { sequential_entry } endtable
udp_initial_statement ::= initial output_port_identifier = init_val ;
init_val ::= 1’b0 | 1’b1 | 1’bx | 1’bX | 1’B0 | 1’B1 | 1’Bx | 1’BX | 1 | 0
sequential_entry ::= seq_input_list : current_state : next_state ;
seq_input_list ::= level_input_list | edge_input_list
level_input_list ::= level_symbol { level_symbol }
edge_input_list ::= { level_symbol } edge_indicator { level_symbol }
edge_indicator ::= ( level_symbol level_symbol ) | edge_symbol
current_state ::= level_symbol
next_state ::= output_symbol... more
A.5.4 UDP instantiation
udp_instantiation ::= udp_identifier [ drive_strength ] [ delay2 ] udp_instance { , udp_instance } ;
udp_instance ::= [ name_of_instance ] ( output_terminal , input_terminal { , input_terminal } )
链接
附录A 形式语法, 主题


A.5.1 UDP declaration

链接
A.5 UDP declaration and instantiation
SystemVerilog 3.1a语言参考手册
A.5.1 UDP declaration
A.5 UDP declaration and instantiation

udp_nonansi_declaration ::=

{ attribute_instance } primitive udp_identifier ( udp_port_list ) ;

udp_ansi_declaration ::=

{ attribute_instance } primitive udp_identifier ( udp_declaration_port_list ) ;

udp_declaration ::=

udp_nonansi_declaration udp_port_declaration { udp_port_declaration }

udp_body

endprimitive [ : udp_identifier ]

| udp_ansi_declaration

udp_body

endprimitive [ : udp_identifier ]

| extern udp_nonansi_declaration

| extern udp_ansi_declaration

| { attribute_instance } primitive udp_identifier ( .* ) ;

{ udp_port_declaration }

udp_body

endprimitive [ : udp_identifier ]

Group

A.5 UDP declaration and instantiation

链接
A.5 UDP declaration and instantiation


A.5.2 UDP ports

链接
A.5 UDP declaration and instantiation
SystemVerilog 3.1a语言参考手册
A.5.2 UDP ports
A.5 UDP declaration and instantiation

udp_port_list ::= output_port_identifier , input_port_identifier { , input_port_identifier }

udp_declaration_port_list ::= udp_output_declaration , udp_input_declaration { , udp_input_declaration }

udp_port_declaration ::=

udp_output_declaration ;

| udp_input_declaration ;

| udp_reg_declaration ;

udp_output_declaration ::=

{ attribute_instance } output port_identifier

| { attribute_instance } output reg port_identifier [ = constant_expression ]

udp_input_declaration ::= { attribute_instance } input list_of_udp_port_identifiers

udp_reg_declaration ::= { attribute_instance } reg variable_identifier

Group

A.5 UDP declaration and instantiation

链接
A.5 UDP declaration and instantiation


A.5.3 UDP body

链接
A.5 UDP declaration and instantiation
SystemVerilog 3.1a语言参考手册
A.5.3 UDP body
A.5 UDP declaration and instantiation

udp_body ::= combinational_body | sequential_body

combinational_body ::= table combinational_entry { combinational_entry } endtable

combinational_entry ::= level_input_list : output_symbol ;

sequential_body ::= [ udp_initial_statement ] table sequential_entry { sequential_entry } endtable

udp_initial_statement ::= initial output_port_identifier = init_val ;

init_val ::= 1’b0 | 1’b1 | 1’bx | 1’bX | 1’B0 | 1’B1 | 1’Bx | 1’BX | 1 | 0

sequential_entry ::= seq_input_list : current_state : next_state ;

seq_input_list ::= level_input_list | edge_input_list

level_input_list ::= level_symbol { level_symbol }

edge_input_list ::= { level_symbol } edge_indicator { level_symbol }

edge_indicator ::= ( level_symbol level_symbol ) | edge_symbol

current_state ::= level_symbol

next_state ::= output_symbol | -

output_symbol ::= 0 | 1 | x | X

level_symbol ::= 0 | 1 | x | X | ? | b | B

edge_symbol ::= r | R | f | F | p | P | n | N | *

Group

A.5 UDP declaration and instantiation

链接
A.5 UDP declaration and instantiation


A.5.4 UDP instantiation

链接
A.5 UDP declaration and instantiation
SystemVerilog 3.1a语言参考手册
A.5.4 UDP instantiation
A.5 UDP declaration and instantiation

udp_instantiation ::= udp_identifier [ drive_strength ] [ delay2 ] udp_instance { , udp_instance } ;

udp_instance ::= [ name_of_instance ] ( output_terminal , input_terminal { , input_terminal } )

Group

A.5 UDP declaration and instantiation

链接
A.5 UDP declaration and instantiation


A.6 Behavioral statements

链接
附录A 形式语法, 主题
SystemVerilog 3.1a语言参考手册
A.6 Behavioral statements
附录A 形式语法 | 主题
Group

附录A 形式语法

主题
主题
描述
A.6.1 Continuous assignment and net alias statements
continuous_assign ::=
assign [ drive_strength ] [ delay3 ] list_of_net_assignments ;
| assign [ delay_control ] list_of_variable_assignments ;
list_of_net_assignments ::= net_assignment { , net_assignment }
list_of_variable_assignments ::= variable_assignment { , variable_assignment }
net_alias ::= alias net_lvalue = net_lvalue { = net_lvalue } ;
net_assignment ::= net_lvalue = expression
A.6.2 Procedural blocks and assignments
initial_construct ::= initial statement_or_null
always_construct ::= always_keyword statement
always_keyword ::= always | always_comb | always_latch | always_ff
blocking_assignment ::=
variable_lvalue = delay_or_event_control expression
| hierarchical_dynamic_array_variable_identifier = dynamic_array_new
| [ implicit_class_handle . | class_scope | package_scope ] hierarchical_variable_identifier
select = class_new
| operator_assignment
operator_assignment ::= variable_lvalue assignment_operator expression
assignment_operator ::=
= | += | -= | *= | /= | %= | &= | |= | ^= | <<= | >>= | <<<= | >>>=
nonblocking_assignment ::= variable_lvalue <= [ delay_or_event_control ] expression
procedural_continuous_assignment ::=
assign variable_assignment
| deassign variable_lvalue
| force variable_assignment
| force net_assignment
| release variable_lvalue
| release... more
A.6.3 Parallel and sequential blocks
action_block ::=
statement_or_null
| [ statement ] else statement_or_null
seq_block ::=
begin [ : block_identifier ] { block_item_declaration } { statement_or_null }
end [ : block_identifier ]
par_block ::=
fork [ : block_identifier ] { block_item_declaration } { statement_or_null }
join_keyword [ : block_identifier ]
join_keyword ::= join | join_any | join_none
A.6.4 Statements
statement_or_null ::=
statement
| { attribute_instance } ;
statement ::= [ block_identifier : ] { attribute_instance } statement_item
statement_item ::=
blocking_assignment ;
| nonblocking_assignment ;
| procedural_continuous_assignment ;
| case_statement
| conditional_statement
| inc_or_dec_expression ;
| subroutine_call_statement
| disable_statement
| event_trigger
| loop_statement
| jump_statement
| par_block
| procedural_timing_control_statement
| seq_block
| wait_statement
| procedural_assertion_statement
| clocking_drive ;
| randsequence_statement
| randcase_statement
| expect_property_statement
function_statement ::= statement
function_statement_or_null ::=
function_statement
| { attribute_instance } ;
variable_identifier_list ::= variable_identifier { , variable_identifier }
A.6.5 Timing control statements
procedural_timing_control_statement ::=
procedural_timing_control statement_or_null
delay_or_event_control ::=
delay_control
| event_control
| repeat ( expression ) event_control
delay_control ::=
# delay_value
| # ( mintypmax_expression )
event_control ::=
@hierarchical_event_identifier
| @ ( event_expression )
| @*
| @ (*)
| @ sequence_instance
event_expression ::=
[ edge_identifier ] expression [ iff expression ]
| sequence_instance [ iff expression ]
| event_expression or event_expression
| event_expression , event_expression
procedural_timing_control ::=
delay_control
| event_control
| cycle_delay
jump_statement ::=
return [ expression ] ;
| break ;
| continue ;
wait_statement ::=
wait ( expression ) statement_or_null
| wait fork ;
| wait_order ( hierarchical_identifier [... more
A.6.6 Conditional statements
conditional_statement ::=
if ( cond_predicate ) statement_or_null [ else statement_or_null ]
| unique_priority_if_statement
unique_priority_if_statement ::=
[ unique_priority ] if ( cond_predicate ) statement_or_null
{ else if ( cond_predicate ) statement_or_null }
[ else statement_or_null ]
unique_priority ::= unique | priority
cond_predicate ::=
expression_or_cond_pattern { && expression_or_cond_pattern }
expression_or_cond_pattern ::=
expression | cond_pattern
cond_pattern ::= expression matches pattern
A.6.7 Case statements
case_statement ::=
[ unique_priority ] case_keyword ( expression ) case_item { case_item } endcase
| [ unique_priority ] case_keyword ( expression ) matches case_pattern_item { case_pattern_item }
endcase
case_keyword ::= case | casez | casex
case_item ::=
expression { , expression } : statement_or_null
| default [ : ] statement_or_null
case_pattern_item ::=
pattern [ && expression ] : statement_or_null
| default [ : ] statement_or_null
randcase_statement ::=
randcase randcase_item { randcase_item } endcase
randcase_item ::= expression : statement_or_null
A.6.8 Looping statements
loop_statement ::=
forever statement_or_null
| repeat ( expression ) statement_or_null
| while ( expression ) statement_or_null
| for ( for_initialization ; expression ; for_step )
statement_or_null
| do statement_or_null while ( expression ) ;
| foreach ( array_identifier [ loop_variables ] ) statement
for_initialization ::=
list_of_variable_assignments
| data_type list_of_variable_assignments { , data_type list_of_variable_assignments }
for_step ::= for_step_assignment { , for_step_assignment }
for_step_assignment ::=
operator_assignment
| inc_or_dec_expression
loop_variables ::= [ index_variable_identifier ] { , [ index_variable_identifier ] }
A.6.9 Subroutine call statements
subroutine_call_statement :=
subroutine_call ;
| void ’ ( function_subroutine_call ) ;
A.6.10 Assertion statements
procedural_assertion_statement ::=
concurrent_assertion_statement
| immediate_assert_statement
immediate_assert_statement ::=
assert ( expression ) action_block
A.6.11 Clocking block
clocking_declaration ::= [ default ] clocking [ clocking_identifier ] clocking_event ;
{ clocking_item }
endclocking [ : clocking_identifier ]
clocking_event ::=
@identifier
| @ ( event_expression )
clocking_item :=
default default_skew ;
| clocking_direction list_of_clocking_decl_assign ;
| { attribute_instance } concurrent_assertion_item_declaration
default_skew ::=
input clocking_skew
| output clocking_skew
| input clocking_skew output clocking_skew
clocking_direction ::=
input [ clocking_skew ]
| output [ clocking_skew ]
| input [ clocking_skew ] output [ clocking_skew ]
| inout
list_of_clocking_decl_assign ::= clocking_decl_assign { , clocking_decl_assign }
clocking_decl_assign ::= signal_identifier [ = hierarchical_identifier ]
clocking_skew ::=
edge_identifier [ delay_control ]
| delay_control
clocking_drive ::=
clockvar_expression... more
A.6.12 Randsequence
randsequence_statement ::= randsequence ( [ production_ identifier ] )
production { production }
endsequence
production ::= [ function_data_type ] production_name [ ( tf_port_list ) ] : rs_rule { | rs_rule } ;
rs_rule ::= rs_production_list [ := expression [ rs_code_block ] ]
rs_production_list ::=
rs_prod { rs_prod }
| rand join [ ( expression ) ] production_item production_item { production_item }
rs_code_block ::= { { data_declaration } { statement_or_null } }
rs_prod ::=
production_item
| rs_code_block
| rs_if_else
| rs_repeat
| rs_case
production_item ::= production_identifier [ ( list_of_arguments ) ]
rs_if_else ::= if ( expression ) production_item [ else production_item... more
链接
附录A 形式语法, 主题


A.6.1 Continuous assignment and net alias statements

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.1 Continuous assignment and net alias statements
A.6 Behavioral statements

continuous_assign ::=

assign [ drive_strength ] [ delay3 ] list_of_net_assignments ;

| assign [ delay_control ] list_of_variable_assignments ;

list_of_net_assignments ::= net_assignment { , net_assignment }

list_of_variable_assignments ::= variable_assignment { , variable_assignment }

net_alias ::= alias net_lvalue = net_lvalue { = net_lvalue } ;

net_assignment ::= net_lvalue = expression

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.6.2 Procedural blocks and assignments

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.2 Procedural blocks and assignments
A.6 Behavioral statements

initial_construct ::= initial statement_or_null

always_construct ::= always_keyword statement

always_keyword ::= always | always_comb | always_latch | always_ff

blocking_assignment ::=

variable_lvalue = delay_or_event_control expression

| hierarchical_dynamic_array_variable_identifier = dynamic_array_new

| [ implicit_class_handle . | class_scope | package_scope ] hierarchical_variable_identifier

select = class_new

| operator_assignment

operator_assignment ::= variable_lvalue assignment_operator expression

assignment_operator ::=

= | += | -= | *= | /= | %= | &= | |= | ^= | <<= | >>= | <<<= | >>>=

nonblocking_assignment ::= variable_lvalue <= [ delay_or_event_control ] expression

procedural_continuous_assignment ::=

assign variable_assignment

| deassign variable_lvalue

| force variable_assignment

| force net_assignment

| release variable_lvalue

| release net_lvalue

variable_assignment ::= variable_lvalue = expression

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.6.3 Parallel and sequential blocks

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.3 Parallel and sequential blocks
A.6 Behavioral statements

action_block ::=

statement_or_null

| [ statement ] else statement_or_null

seq_block ::=

begin [ : block_identifier ] { block_item_declaration } { statement_or_null }

end [ : block_identifier ]

par_block ::=

fork [ : block_identifier ] { block_item_declaration } { statement_or_null }

join_keyword [ : block_identifier ]

join_keyword ::= join | join_any | join_none

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.6.4 Statements

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.4 Statements
A.6 Behavioral statements

statement_or_null ::=

statement

| { attribute_instance } ;

statement ::= [ block_identifier : ] { attribute_instance } statement_item

statement_item ::=

blocking_assignment ;

| nonblocking_assignment ;

| procedural_continuous_assignment ;

| case_statement

| conditional_statement

| inc_or_dec_expression ;

| subroutine_call_statement

| disable_statement

| event_trigger

| loop_statement

| jump_statement

| par_block

| procedural_timing_control_statement

| seq_block

| wait_statement

| procedural_assertion_statement

| clocking_drive ;

| randsequence_statement

| randcase_statement

| expect_property_statement

function_statement ::= statement

function_statement_or_null ::=

function_statement

| { attribute_instance } ;

variable_identifier_list ::= variable_identifier { , variable_identifier }

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.6.5 Timing control statements

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.5 Timing control statements
A.6 Behavioral statements

procedural_timing_control_statement ::=

procedural_timing_control statement_or_null

delay_or_event_control ::=

delay_control

| event_control

| repeat ( expression ) event_control

delay_control ::=

# delay_value

| # ( mintypmax_expression )

event_control ::=

@hierarchical_event_identifier

| @ ( event_expression )

| @*

| @ (*)

| @ sequence_instance

event_expression ::=

[ edge_identifier ] expression [ iff expression ]

| sequence_instance [ iff expression ]

| event_expression or event_expression

| event_expression , event_expression

procedural_timing_control ::=

delay_control

| event_control

| cycle_delay

jump_statement ::=

return [ expression ] ;

| break ;

| continue ;

wait_statement ::=

wait ( expression ) statement_or_null

| wait fork ;

| wait_order ( hierarchical_identifier [ , hierarchical_identifier ] ) action_block

event_trigger ::=

-> hierarchical_event_identifier ;

|->> [ delay_or_event_control ] hierarchical_event_identifier ;

disable_statement ::=

disable hierarchical_task_identifier ;

| disable hierarchical_block_identifier ;

| disable fork ;

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.6.6 Conditional statements

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.6 Conditional statements
A.6 Behavioral statements

conditional_statement ::=

if ( cond_predicate ) statement_or_null [ else statement_or_null ]

| unique_priority_if_statement

unique_priority_if_statement ::=

[ unique_priority ] if ( cond_predicate ) statement_or_null

{ else if ( cond_predicate ) statement_or_null }

[ else statement_or_null ]

unique_priority ::= unique | priority

cond_predicate ::=

expression_or_cond_pattern { && expression_or_cond_pattern }

expression_or_cond_pattern ::=

expression | cond_pattern

cond_pattern ::= expression matches pattern

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.6.7 Case statements

链接
A.6 Behavioral statements, 主题
SystemVerilog 3.1a语言参考手册
A.6.7 Case statements
A.6 Behavioral statements | 主题

case_statement ::=

[ unique_priority ] case_keyword ( expression ) case_item { case_item } endcase

| [ unique_priority ] case_keyword ( expression ) matches case_pattern_item { case_pattern_item }

endcase

case_keyword ::= case | casez | casex

case_item ::=

expression { , expression } : statement_or_null

| default [ : ] statement_or_null

case_pattern_item ::=

pattern [ && expression ] : statement_or_null

| default [ : ] statement_or_null

randcase_statement ::=

randcase randcase_item { randcase_item } endcase

randcase_item ::= expression : statement_or_null

Group

A.6 Behavioral statements

主题
主题 | 描述
A.6.7.1 Patterns | pattern ::= variable_identifier | .* | . constant_expression | tagged member_identifier [ pattern ] | { pattern { , pattern } } | { member_identifier : pattern { , member_identifier : pattern } }
链接
A.6 Behavioral statements, 主题


A.6.7.1 Patterns

链接
A.6.7 Case statements
SystemVerilog 3.1a语言参考手册
A.6.7.1 Patterns
A.6.7 Case statements

pattern ::=

variable_identifier

| .*

| . constant_expression

| tagged member_identifier [ pattern ]

| { pattern { , pattern } }

| { member_identifier : pattern { , member_identifier : pattern } }

Group

A.6.7 Case statements

链接
A.6.7 Case statements


A.6.8 Looping statements

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.8 Looping statements
A.6 Behavioral statements

loop_statement ::=

forever statement_or_null

| repeat ( expression ) statement_or_null

| while ( expression ) statement_or_null

| for ( for_initialization ; expression ; for_step )

statement_or_null

| do statement_or_null while ( expression ) ;

| foreach ( array_identifier [ loop_variables ] ) statement

for_initialization ::=

list_of_variable_assignments

| data_type list_of_variable_assignments { , data_type list_of_variable_assignments }

for_step ::= for_step_assignment { , for_step_assignment }

for_step_assignment ::=

operator_assignment

| inc_or_dec_expression

loop_variables ::= [ index_variable_identifier ] { , [ index_variable_identifier ] }

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.6.9 Subroutine call statements

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.9 Subroutine call statements
A.6 Behavioral statements

subroutine_call_statement :=

subroutine_call ;

| void ’ ( function_subroutine_call ) ;

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.6.10 Assertion statements

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.10 Assertion statements
A.6 Behavioral statements

procedural_assertion_statement ::=

concurrent_assertion_statement

| immediate_assert_statement

immediate_assert_statement ::=

assert ( expression ) action_block

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.6.11 Clocking block

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.11 Clocking block
A.6 Behavioral statements

clocking_declaration ::= [ default ] clocking [ clocking_identifier ] clocking_event ;

{ clocking_item }

endclocking [ : clocking_identifier ]

clocking_event ::=

@identifier

| @ ( event_expression )

clocking_item :=

default default_skew ;

| clocking_direction list_of_clocking_decl_assign ;

| { attribute_instance } concurrent_assertion_item_declaration

default_skew ::=

input clocking_skew

| output clocking_skew

| input clocking_skew output clocking_skew

clocking_direction ::=

input [ clocking_skew ]

| output [ clocking_skew ]

| input [ clocking_skew ] output [ clocking_skew ]

| inout

list_of_clocking_decl_assign ::= clocking_decl_assign { , clocking_decl_assign }

clocking_decl_assign ::= signal_identifier [ = hierarchical_identifier ]

clocking_skew ::=

edge_identifier [ delay_control ]

| delay_control

clocking_drive ::=

clockvar_expression <= [ cycle_delay ] expression

| cycle_delay clockvar_expression <= expression

cycle_delay ::=

## integral_number

| ## identifier

| ## ( expression )

clockvar ::= hierarchical_identifier

clockvar_expression ::= clockvar select

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.6.12 Randsequence

链接
A.6 Behavioral statements
SystemVerilog 3.1a语言参考手册
A.6.12 Randsequence
A.6 Behavioral statements

randsequence_statement ::= randsequence ( [ production_ identifier ] )

production { production }

endsequence

production ::= [ function_data_type ] production_name [ ( tf_port_list ) ] : rs_rule { | rs_rule } ;

rs_rule ::= rs_production_list [ := expression [ rs_code_block ] ]

rs_production_list ::=

rs_prod { rs_prod }

| rand join [ ( expression ) ] production_item production_item { production_item }

rs_code_block ::= { { data_declaration } { statement_or_null } }

rs_prod ::=

production_item

| rs_code_block

| rs_if_else

| rs_repeat

| rs_case

production_item ::= production_identifier [ ( list_of_arguments ) ]

rs_if_else ::= if ( expression ) production_item [ else production_item ]

rs_repeat ::= repeat ( expression ) production_item

rs_case ::= case ( expression ) rs_case_item { rs_case_item } endcase

rs_case_item ::=

expression { , expression } : production_item

| default [ : ] production_item

Group

A.6 Behavioral statements

链接
A.6 Behavioral statements


A.7 Specify section

链接
附录A 形式语法, 主题
SystemVerilog 3.1a语言参考手册
A.7 Specify section
附录A 形式语法 | 主题
Group

附录A 形式语法

主题
主题
描述
A.7.1 Specify block declaration
specify_block ::= specify { specify_item } endspecify
specify_item ::=
specparam_declaration
| pulsestyle_declaration
| showcancelled_declaration
| path_declaration
| system_timing_check
pulsestyle_declaration ::=
pulsestyle_onevent list_of_path_outputs ;
| pulsestyle_ondetect list_of_path_outputs ;
showcancelled_declaration ::=
showcancelled list_of_path_outputs ;
| noshowcancelled list_of_path_outputs ;
A.7.2 Specify path declarations
path_declaration ::=
simple_path_declaration ;
| edge_sensitive_path_declaration ;
| state_dependent_path_declaration ;
simple_path_declaration ::=
parallel_path_description = path_delay_value
| full_path_description = path_delay_value
parallel_path_description ::=
( specify_input_terminal_descriptor [ polarity_operator ] => specify_output_terminal_descriptor )
full_path_description ::=
( list_of_path_inputs [ polarity_operator ] *> list_of_path_outputs )
list_of_path_inputs ::=
specify_input_terminal_descriptor { , specify_input_terminal_descriptor }
list_of_path_outputs ::=
specify_output_terminal_descriptor { , specify_output_terminal_descriptor }
A.7.3 Specify block terminals
specify_input_terminal_descriptor ::=
input_identifier [ [ constant_range_expression ] ]
specify_output_terminal_descriptor ::=
output_identifier [ [ constant_range_expression ] ]
input_identifier ::= input_port_identifier | inout_port_identifier | interface_identifier.port_identifier
output_identifier ::= output_port_identifier | inout_port_identifier | interface_identifier.port_identifier
A.7.4 Specify path delays
path_delay_value ::=
list_of_path_delay_expressions
| ( list_of_path_delay_expressions )
list_of_path_delay_expressions ::=
t_path_delay_expression
| trise_path_delay_expression , tfall_path_delay_expression
| trise_path_delay_expression , tfall_path_delay_expression , tz_path_delay_expression
| t01_path_delay_expression , t10_path_delay_expression , t0z_path_delay_expression ,
tz1_path_delay_expression , t1z_path_delay_expression , tz0_path_delay_expression
| t01_path_delay_expression , t10_path_delay_expression , t0z_path_delay_expression ,
tz1_path_delay_expression , t1z_path_delay_expression , tz0_path_delay_expression ,
t0x_path_delay_expression , tx1_path_delay_expression , t1x_path_delay_expression ,
tx0_path_delay_expression , txz_path_delay_expression , tzx_path_delay_expression
t_path_delay_expression ::= path_delay_expression
trise_path_delay_expression ::= path_delay_expression
tfall_path_delay_expression ::= path_delay_expression
tz_path_delay_expression ::= path_delay_expression
t01_path_delay_expression ::= path_delay_expression
t10_path_delay_expression ::= path_delay_expression
t0z_path_delay_expression ::= path_delay_expression
tz1_path_delay_expression ::= path_delay_expression
t1z_path_delay_expression ::= path_delay_expression
tz0_path_delay_expression ::= path_delay_expression
t0x_path_delay_expression ::= path_delay_expression
tx1_path_delay_expression ::= path_delay_expression
t1x_path_delay_expression ::= path_delay_expression
tx0_path_delay_expression ::= path_delay_expression
txz_path_delay_expression ::=... more
A.7.5 System timing checks
链接
附录A 形式语法, 主题


A.7.1 Specify block declaration

链接
A.7 Specify section
SystemVerilog 3.1a语言参考手册
A.7.1 Specify block declaration
A.7 Specify section

specify_block ::= specify { specify_item } endspecify

specify_item ::=

specparam_declaration

| pulsestyle_declaration

| showcancelled_declaration

| path_declaration

| system_timing_check

pulsestyle_declaration ::=

pulsestyle_onevent list_of_path_outputs ;

| pulsestyle_ondetect list_of_path_outputs ;

showcancelled_declaration ::=

showcancelled list_of_path_outputs ;

| noshowcancelled list_of_path_outputs ;

Group

A.7 Specify section

链接
A.7 Specify section


A.7.2 Specify path declarations

链接
A.7 Specify section
SystemVerilog 3.1a语言参考手册
A.7.2 Specify path declarations
A.7 Specify section

path_declaration ::=

simple_path_declaration ;

| edge_sensitive_path_declaration ;

| state_dependent_path_declaration ;

simple_path_declaration ::=

parallel_path_description = path_delay_value

| full_path_description = path_delay_value

parallel_path_description ::=

( specify_input_terminal_descriptor [ polarity_operator ] => specify_output_terminal_descriptor )

full_path_description ::=

( list_of_path_inputs [ polarity_operator ] *> list_of_path_outputs )

list_of_path_inputs ::=

specify_input_terminal_descriptor { , specify_input_terminal_descriptor }

list_of_path_outputs ::=

specify_output_terminal_descriptor { , specify_output_terminal_descriptor }

Group

A.7 Specify section

链接
A.7 Specify section


A.7.3 Specify block terminals

链接
A.7 Specify section
SystemVerilog 3.1a语言参考手册
A.7.3 Specify block terminals
A.7 Specify section

specify_input_terminal_descriptor ::=

input_identifier [ [ constant_range_expression ] ]

specify_output_terminal_descriptor ::=

output_identifier [ [ constant_range_expression ] ]

input_identifier ::= input_port_identifier | inout_port_identifier | interface_identifier.port_identifier

output_identifier ::= output_port_identifier | inout_port_identifier | interface_identifier.port_identifier

Group

A.7 Specify section

链接
A.7 Specify section


A.7.4 Specify path delays

链接
A.7 Specify section
SystemVerilog 3.1a语言参考手册
A.7.4 Specify path delays
A.7 Specify section

path_delay_value ::=

list_of_path_delay_expressions

| ( list_of_path_delay_expressions )

list_of_path_delay_expressions ::=

t_path_delay_expression

| trise_path_delay_expression , tfall_path_delay_expression

| trise_path_delay_expression , tfall_path_delay_expression , tz_path_delay_expression

| t01_path_delay_expression , t10_path_delay_expression , t0z_path_delay_expression ,

tz1_path_delay_expression , t1z_path_delay_expression , tz0_path_delay_expression

| t01_path_delay_expression , t10_path_delay_expression , t0z_path_delay_expression ,

tz1_path_delay_expression , t1z_path_delay_expression , tz0_path_delay_expression ,

t0x_path_delay_expression , tx1_path_delay_expression , t1x_path_delay_expression ,

tx0_path_delay_expression , txz_path_delay_expression , tzx_path_delay_expression

t_path_delay_expression ::= path_delay_expression

trise_path_delay_expression ::= path_delay_expression

tfall_path_delay_expression ::= path_delay_expression

tz_path_delay_expression ::= path_delay_expression

t01_path_delay_expression ::= path_delay_expression

t10_path_delay_expression ::= path_delay_expression

t0z_path_delay_expression ::= path_delay_expression

tz1_path_delay_expression ::= path_delay_expression

t1z_path_delay_expression ::= path_delay_expression

tz0_path_delay_expression ::= path_delay_expression

t0x_path_delay_expression ::= path_delay_expression

tx1_path_delay_expression ::= path_delay_expression

t1x_path_delay_expression ::= path_delay_expression

tx0_path_delay_expression ::= path_delay_expression

txz_path_delay_expression ::= path_delay_expression

tzx_path_delay_expression ::= path_delay_expression

path_delay_expression ::= constant_mintypmax_expression

edge_sensitive_path_declaration ::=

parallel_edge_sensitive_path_description = path_delay_value

| full_edge_sensitive_path_description = path_delay_value

parallel_edge_sensitive_path_description ::=

( [ edge_identifier ] specify_input_terminal_descriptor =>

( specify_output_terminal_descriptor [ polarity_operator ] : data_source_expression ) )

full_edge_sensitive_path_description ::=

( [ edge_identifier ] list_of_path_inputs *>

( list_of_path_outputs [ polarity_operator ] : data_source_expression ) )

data_source_expression ::= expression

edge_identifier ::= posedge | negedge

state_dependent_path_declaration ::=

if ( module_path_expression ) simple_path_declaration

| if ( module_path_expression ) edge_sensitive_path_declaration

| ifnone simple_path_declaration

polarity_operator ::= + |

Group

A.7 Specify section

链接
A.7 Specify section


A.7.5 System timing checks

链接
A.7 Specify section, 主题
SystemVerilog 3.1a语言参考手册
A.7.5 System timing checks
A.7 Specify section | 主题
Group

A.7 Specify section

主题
主题
描述
A.7.5.1 System timing check commands
system_timing_check ::=
$setup_timing_check
| $hold_timing_check
| $setuphold_timing_check
| $recovery_timing_check
| $removal_timing_check
| $recrem_timing_check
| $skew_timing_check
| $timeskew_timing_check
| $fullskew_timing_check
| $period_timing_check
| $width_timing_check
| $nochange_timing_check
$setup_timing_check ::=
$setup ( data_event , reference_event , timing_check_limit [ , [ notifier ] ] ) ;
$hold_timing_check ::=
$hold ( reference_event , data_event , timing_check_limit [ , [ notifier ] ] ) ;
$setuphold_timing_check ::=
$setuphold ( reference_event , data_event , timing_check_limit , timing_check_limit
[ , [ notifier ] [ , [ stamptime_condition ] [ , [ checktime_condition ]
[ , [ delayed_reference ] [ , [ delayed_data ] ] ] ] ] ]... more
A.7.5.2 System timing check command arguments
checktime_condition ::= mintypmax_expression
controlled_reference_event ::= controlled_timing_check_event
data_event ::= timing_check_event
delayed_data ::=
terminal_identifier
| terminal_identifier [ constant_mintypmax_expression ]
delayed_reference ::=
terminal_identifier
| terminal_identifier [ constant_mintypmax_expression ]
end_edge_offset ::= mintypmax_expression
event_based_flag ::= constant_expression
notifier ::= variable_identifier
reference_event ::= timing_check_event
remain_active_flag ::= constant_mintypmax_expression
stamptime_condition ::= mintypmax_expression
start_edge_offset ::= mintypmax_expression
threshold ::=constant_expression
timing_check_limit ::= expression
A.7.5.3 System timing check event definitions
timing_check_event ::=
[timing_check_event_control] specify_terminal_descriptor [ &&& timing_check_condition ]
controlled_timing_check_event ::=
timing_check_event_control specify_terminal_descriptor [ &&& timing_check_condition ]
timing_check_event_control ::=
posedge
| negedge
| edge_control_specifier
specify_terminal_descriptor ::=
specify_input_terminal_descriptor
| specify_output_terminal_descriptor
edge_control_specifier ::= edge [ edge_descriptor { , edge_descriptor } ]
edge_descriptor1 ::= 01 | 10 | z_or_x zero_or_one | zero_or_one z_or_x
zero_or_one ::= 0 | 1
z_or_x ::= x | X | z | Z
timing_check_condition ::=
scalar_timing_check_condition
| ( scalar_timing_check_condition )
scalar_timing_check_condition ::=
expression
| ~ expression
| expression == scalar_constant
| expression === scalar_constant
| expression != scalar_constant
| expression !== scalar_constant
scalar_constant ::= 1’b0 | 1’b1 | 1’B0 |... more
链接
A.7 Specify section, 主题


A.7.5.1 System timing check commands

链接
A.7.5 System timing checks
SystemVerilog 3.1a语言参考手册
A.7.5.1 System timing check commands
A.7.5 System timing checks

system_timing_check ::=

$setup_timing_check

| $hold_timing_check

| $setuphold_timing_check

| $recovery_timing_check

| $removal_timing_check

| $recrem_timing_check

| $skew_timing_check

| $timeskew_timing_check

| $fullskew_timing_check

| $period_timing_check

| $width_timing_check

| $nochange_timing_check

$setup_timing_check ::=

$setup ( data_event , reference_event , timing_check_limit [ , [ notifier ] ] ) ;

$hold_timing_check ::=

$hold ( reference_event , data_event , timing_check_limit [ , [ notifier ] ] ) ;

$setuphold_timing_check ::=

$setuphold ( reference_event , data_event , timing_check_limit , timing_check_limit

[ , [ notifier ] [ , [ stamptime_condition ] [ , [ checktime_condition ]

[ , [ delayed_reference ] [ , [ delayed_data ] ] ] ] ] ] ) ;

$recovery_timing_check ::=

$recovery ( reference_event , data_event , timing_check_limit [ , [ notifier ] ] ) ;

$removal_timing_check ::=

$removal ( reference_event , data_event , timing_check_limit [ , [ notifier ] ] ) ;

$recrem_timing_check ::=

$recrem ( reference_event , data_event , timing_check_limit , timing_check_limit

[ , [ notifier ] [ , [ stamptime_condition ] [ , [ checktime_condition ]

[ , [ delayed_reference ] [ , [ delayed_data ] ] ] ] ] ] ) ;

$skew_timing_check ::=

$skew ( reference_event , data_event , timing_check_limit [ , [ notifier ] ] ) ;

$timeskew_timing_check ::=

$timeskew ( reference_event , data_event , timing_check_limit

[ , [ notifier ] [ , [ event_based_flag ] [ , [ remain_active_flag ] ] ] ] ) ;

$fullskew_timing_check ::=

$fullskew ( reference_event , data_event , timing_check_limit , timing_check_limit

[ , [ notifier ] [ , [ event_based_flag ] [ , [ remain_active_flag ] ] ] ] ) ;

$period_timing_check ::=

$period ( controlled_reference_event , timing_check_limit [ , [ notifier ] ] ) ;

$width_timing_check ::=

$width ( controlled_reference_event , timing_check_limit , threshold [ , [ notifier ] ] ) ;

$nochange_timing_check ::=

$nochange ( reference_event , data_event , start_edge_offset ,

end_edge_offset [ , [ notifier ] ] ) ;

Group

A.7.5 System timing checks

链接
A.7.5 System timing checks


A.7.5.2 System timing check command arguments

链接
A.7.5 System timing checks
SystemVerilog 3.1a语言参考手册
A.7.5.2 System timing check command arguments
A.7.5 System timing checks

checktime_condition ::= mintypmax_expression

controlled_reference_event ::= controlled_timing_check_event

data_event ::= timing_check_event

delayed_data ::=

terminal_identifier

| terminal_identifier [ constant_mintypmax_expression ]

delayed_reference ::=

terminal_identifier

| terminal_identifier [ constant_mintypmax_expression ]

end_edge_offset ::= mintypmax_expression

event_based_flag ::= constant_expression

notifier ::= variable_identifier

reference_event ::= timing_check_event

remain_active_flag ::= constant_mintypmax_expression

stamptime_condition ::= mintypmax_expression

start_edge_offset ::= mintypmax_expression

threshold ::=constant_expression

timing_check_limit ::= expression

Group

A.7.5 System timing checks

链接
A.7.5 System timing checks


A.7.5.3 System timing check event definitions

链接
A.7.5 System timing checks
SystemVerilog 3.1a语言参考手册
A.7.5.3 System timing check event definitions
A.7.5 System timing checks

timing_check_event ::=

[timing_check_event_control] specify_terminal_descriptor [ &&& timing_check_condition ]

controlled_timing_check_event ::=

timing_check_event_control specify_terminal_descriptor [ &&& timing_check_condition ]

timing_check_event_control ::=

posedge

| negedge

| edge_control_specifier

specify_terminal_descriptor ::=

specify_input_terminal_descriptor

| specify_output_terminal_descriptor

edge_control_specifier ::= edge [ edge_descriptor { , edge_descriptor } ]

edge_descriptor1 ::= 01 | 10 | z_or_x zero_or_one | zero_or_one z_or_x

zero_or_one ::= 0 | 1

z_or_x ::= x | X | z | Z

timing_check_condition ::=

scalar_timing_check_condition

| ( scalar_timing_check_condition )

scalar_timing_check_condition ::=

expression

| ~ expression

| expression == scalar_constant

| expression === scalar_constant

| expression != scalar_constant

| expression !== scalar_constant

scalar_constant ::= 1’b0 | 1’b1 | 1’B0 | 1’B1 | ’b0 | ’b1 | ’B0 | ’B1 | 1 | 0

Group

A.7.5 System timing checks

链接
A.7.5 System timing checks


A.8 Expressions

链接
附录A 形式语法, 主题
SystemVerilog 3.1a语言参考手册
A.8 Expressions
附录A 形式语法 | 主题
Group

附录A 形式语法

主题
主题
描述
A.8.1 Concatenations
concatenation ::=
{ expression { , expression } }
| { struct_member_label : expression { , struct_member_label : expression } }
| { array_member_label : expression { , array_member_label : expression } }
constant_concatenation ::=
{ constant_expression { , constant_expression } }
| { struct_member_label : constant_expression { , struct_member_label : constant_expression } }
| { array_member_label : constant_expression { , array_member_label : constant_expression } }
struct_member_label ::=
default
| type_identifier
| variable_identifier
array_member_label ::=
default
| type_identifier
| constant_expression
constant_multiple_concatenation ::= { constant_expression constant_concatenation }
module_path_concatenation ::= { module_path_expression { , module_path_expression } }
module_path_multiple_concatenation ::= { constant_expression module_path_concatenation... more
A.8.2 Subroutine calls
constant_function_call ::= function_subroutine_call25
tf_call ::= ps_or_hierarchical_tf_identifier { attribute_instance } [ ( list_of_arguments ) ]
system_tf_call ::= system_tf_identifier [ ( list_of_arguments ) ]
subroutine_call ::=
tf_call
| system_tf_call
| method_call
| randomize_call
function_subroutine_call ::= subroutine_call
list_of_arguments ::=
[ expression ] { , [ expression ] } { , . identifier ( [ expression ] ) }
| . identifier ( [ expression ] ) { , . identifier ( [ expression ] ) }
method_call ::= method_call_root . method_call_body
method_call_body ::=
method_identifier { attribute_instance } [ ( list_of_arguments ) ]
| built_in_method_call
built_in_method_call ::=
array_manipulation_call
| randomize_call
array_manipulation_call ::=
array_method_name {... more
A.8.3 Expressions
inc_or_dec_expression ::=
inc_or_dec_operator { attribute_instance } variable_lvalue
| variable_lvalue { attribute_instance } inc_or_dec_operator
conditional_expression ::= cond_predicate ? { attribute_instance } expression : expression
constant_expression ::=
constant_primary
| unary_operator { attribute_instance } constant_primary
| constant_expression binary_operator { attribute_instance } constant_expression
| constant_expression ? { attribute_instance } constant_expression : constant_expression
constant_mintypmax_expression ::=
constant_expression
| constant_expression : constant_expression : constant_expression
constant_param_expression ::=
constant_mintypmax_expression | data_type | $
param_expression ::= mintypmax_expression | data_type
constant_range_expression ::=
constant_expression
| constant_part_select_range
constant_part_select_range ::=
constant_range
| constant_indexed_range
constant_range ::= constant_expression : constant_expression
constant_indexed_range ::=
constant_expression +: constant_expression
| constant_expression -: constant_expression
expression ::=
primary
| unary_operator { attribute_instance... more
A.8.4 Primaries
constant_primary ::=
primary_literal
| ps_parameter_identifier
| ps_specparam_identifier
| genvar_identifier
| [ package_scope | class_scope ] enum_identifier
| constant_concatentation
| constant_multiple_concatenation
| constant_function_call
| ( constant_mintypmax_expression )
| constant_cast
module_path_primary ::=
number
| identifier
| module_path_concatenation
| module_path_multiple_concatenation
| function_subroutine_call
| ( module_path_mintypmax_expression )
primary ::=
primary_literal
| [ implicit_class_handle . | class_scope | package_scope ] hierarchical_identifier select
| empty_queue
| concatenation
| multiple_concatenation
| function_subroutine_call
| ( mintypmax_expression )
| cast
| streaming_expression
| sequence_method_call
| $23
| null
time_literal5 ::=
unsigned_number time_unit
| fixed_point_number time_unit
time_unit ::= s | ms | us | ns | ps | fs |... more
A.8.5 Expression left-side values
net_lvalue ::=
ps_or_hierarchical_net_identifier constant_select
| { net_lvalue { , net_lvalue } }
variable_lvalue ::=
[ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select
| { variable_lvalue { , variable_lvalue } }
A.8.6 Operators
unary_operator ::=
+ | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
binary_operator ::=
+ | - | * | / | % | == | != | === | !== | =?= | !?= | && | || | **
| < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<
inc_or_dec_operator ::= ++ | --
unary_module_path_operator ::=
! | ~ | & | ~& | | | ~| | ^ | ~^... more
A.8.7 Numbers
number ::=
integral_number
| real_number
integral_number ::=
decimal_number
| octal_number
| binary_number
| hex_number
decimal_number ::=
unsigned_number
| [ size ] decimal_base unsigned_number
| [ size ] decimal_base x_digit { _ }
| [ size ] decimal_base z_digit { _ }
binary_number ::= [ size ] binary_base binary_value
octal_number ::= [ size ] octal_base octal_value
hex_number ::= [ size ] hex_base hex_value
sign ::= + | -
size ::= non_zero_unsigned_number
non_zero_unsigned_number1 ::= non_zero_decimal_digit { _ | decimal_digit}
real_number1 ::=
fixed_point_number
| unsigned_number [ . unsigned_number ] exp [ sign ] unsigned_number
fixed_point_number1 ::= unsigned_number . unsigned_number
exp ::= e |... more
A.8.8 Strings
string_literal ::= " { Any_ASCII_Characters }
链接
附录A 形式语法, 主题


A.8.1 Concatenations

链接
A.8 Expressions
SystemVerilog 3.1a语言参考手册
A.8.1 Concatenations
A.8 Expressions

concatenation ::=

{ expression { , expression } }

| { struct_member_label : expression { , struct_member_label : expression } }

| { array_member_label : expression { , array_member_label : expression } }

constant_concatenation ::=

{ constant_expression { , constant_expression } }

| { struct_member_label : constant_expression { , struct_member_label : constant_expression } }

| { array_member_label : constant_expression { , array_member_label : constant_expression } }

struct_member_label ::=

default

| type_identifier

| variable_identifier

array_member_label ::=

default

| type_identifier

| constant_expression

constant_multiple_concatenation ::= { constant_expression constant_concatenation }

module_path_concatenation ::= { module_path_expression { , module_path_expression } }

module_path_multiple_concatenation ::= { constant_expression module_path_concatenation }

multiple_concatenation ::= { expression concatenation }19

streaming_expression ::= { stream_operator [ slice_size ] stream_concatenation }

stream_operator ::= >> | <<

slice_size ::= ps_type_identifier | constant_expression

stream_concatenation ::= { stream_expression { , stream_expression } }

stream_expression ::= expression [ with [ array_range_expression ] ]

array_range_expression ::=

expression

| expression : expression

| expression +: expression

| expression -: expression

empty_queue22 ::= { }

Group

A.8 Expressions

链接
A.8 Expressions


A.8.2 Subroutine calls

链接
A.8 Expressions
SystemVerilog 3.1a语言参考手册
A.8.2 Subroutine calls
A.8 Expressions

constant_function_call ::= function_subroutine_call25

tf_call ::= ps_or_hierarchical_tf_identifier { attribute_instance } [ ( list_of_arguments ) ]

system_tf_call ::= system_tf_identifier [ ( list_of_arguments ) ]

subroutine_call ::=

tf_call

| system_tf_call

| method_call

| randomize_call

function_subroutine_call ::= subroutine_call

list_of_arguments ::=

[ expression ] { , [ expression ] } { , . identifier ( [ expression ] ) }

| . identifier ( [ expression ] ) { , . identifier ( [ expression ] ) }

method_call ::= method_call_root . method_call_body

method_call_body ::=

method_identifier { attribute_instance } [ ( list_of_arguments ) ]

| built_in_method_call

built_in_method_call ::=

array_manipulation_call

| randomize_call

array_manipulation_call ::=

array_method_name { attribute_instance }

[ ( list_of_arguments ) ]

[ with ( expression ) ]

randomize_call ::=

randomize { attribute_instance }

[ ( [ variable_identifier_list | null ] ) ]

[ with constraint_block ]

method_call_root ::= expression | implicit_class_handle

array_method_name ::=

method_identifier | unique | and | or | xor

Group

A.8 Expressions

链接
A.8 Expressions


A.8.3 Expressions

链接
A.8 Expressions
SystemVerilog 3.1a语言参考手册
A.8.3 Expressions
A.8 Expressions

inc_or_dec_expression ::=

inc_or_dec_operator { attribute_instance } variable_lvalue

| variable_lvalue { attribute_instance } inc_or_dec_operator

conditional_expression ::= cond_predicate ? { attribute_instance } expression : expression

constant_expression ::=

constant_primary

| unary_operator { attribute_instance } constant_primary

| constant_expression binary_operator { attribute_instance } constant_expression

| constant_expression ? { attribute_instance } constant_expression : constant_expression

constant_mintypmax_expression ::=

constant_expression

| constant_expression : constant_expression : constant_expression

constant_param_expression ::=

constant_mintypmax_expression | data_type | $

param_expression ::= mintypmax_expression | data_type

constant_range_expression ::=

constant_expression

| constant_part_select_range

constant_part_select_range ::=

constant_range

| constant_indexed_range

constant_range ::= constant_expression : constant_expression

constant_indexed_range ::=

constant_expression +: constant_expression

| constant_expression -: constant_expression

expression ::=

primary

| unary_operator { attribute_instance } primary

| inc_or_dec_expression

| ( operator_assignment )

| expression binary_operator { attribute_instance } expression

| conditional_expression

| inside_expression

| tagged_union_expression

tagged_union_expression ::=

tagged member_identifier [ expression ]

inside_expression ::= expression inside { open_range_list }

value_range ::=

expression

| [ expression : expression ]

mintypmax_expression ::=

expression

| expression : expression : expression

module_path_conditional_expression ::= module_path_expression ? { attribute_instance }

module_path_expression : module_path_expression

module_path_expression ::=

module_path_primary

| unary_module_path_operator { attribute_instance } module_path_primary

| module_path_expression binary_module_path_operator { attribute_instance }

module_path_expression

| module_path_conditional_expression

module_path_mintypmax_expression ::=

module_path_expression

| module_path_expression : module_path_expression : module_path_expression

range_expression ::= expression | part_select_range

part_select_range ::= constant_range | indexed_range

indexed_range ::=

expression +: constant_expression

| expression -: constant_expression

Group

A.8 Expressions

链接
A.8 Expressions


A.8.4 Primaries

链接
A.8 Expressions
SystemVerilog 3.1a语言参考手册
A.8.4 Primaries
A.8 Expressions

constant_primary ::=

primary_literal

| ps_parameter_identifier

| ps_specparam_identifier

| genvar_identifier

| [ package_scope | class_scope ] enum_identifier

| constant_concatentation

| constant_multiple_concatenation

| constant_function_call

| ( constant_mintypmax_expression )

| constant_cast

module_path_primary ::=

number

| identifier

| module_path_concatenation

| module_path_multiple_concatenation

| function_subroutine_call

| ( module_path_mintypmax_expression )

primary ::=

primary_literal

| [ implicit_class_handle . | class_scope | package_scope ] hierarchical_identifier select

| empty_queue

| concatenation

| multiple_concatenation

| function_subroutine_call

| ( mintypmax_expression )

| cast

| streaming_expression

| sequence_method_call

| $23

| null

time_literal5 ::=

unsigned_number time_unit

| fixed_point_number time_unit

time_unit ::= s | ms | us | ns | ps | fs | step

implicit_class_handle6 ::= this | super | this . super

select ::= { [ expression ] } [ [ part_select_range ] ]

constant_select ::= { [ constant_expression ] } [ [ constant_part_select_range ] ]

primary_literal ::= number | time_literal | unbased_unsized_literal | string_literal

constant_cast ::=

casting_type ’ ( constant_expression )

| casting_type ’ constant_concatenation

| casting_type ’ constant_multiple_concatentation

cast ::=

casting_type ’ ( expression )

| casting_type ’ concatenation

| casting_type ’ multiple_concatentation

Group

A.8 Expressions

链接
A.8 Expressions


A.8.5 Expression left-side values

链接
A.8 Expressions
SystemVerilog 3.1a语言参考手册
A.8.5 Expression left-side values
A.8 Expressions

net_lvalue ::=

ps_or_hierarchical_net_identifier constant_select

| { net_lvalue { , net_lvalue } }

variable_lvalue ::=

[ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select

| { variable_lvalue { , variable_lvalue } }

Group

A.8 Expressions

链接
A.8 Expressions


A.8.6 Operators

链接
A.8 Expressions
SystemVerilog 3.1a语言参考手册
A.8.6 Operators
A.8 Expressions

unary_operator ::=

+ | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~

binary_operator ::=

+ | - | * | / | % | == | != | === | !== | =?= | !?= | && | || | **

| < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<

inc_or_dec_operator ::= ++ | --

unary_module_path_operator ::=

! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~

binary_module_path_operator ::=

== | != | && | || | & | | | ^ | ^~ | ~^

Group

A.8 Expressions

链接
A.8 Expressions


A.8.7 Numbers

链接
A.8 Expressions
SystemVerilog 3.1a语言参考手册
A.8.7 Numbers
A.8 Expressions

number ::=

integral_number

| real_number

integral_number ::=

decimal_number

| octal_number

| binary_number

| hex_number

decimal_number ::=

unsigned_number

| [ size ] decimal_base unsigned_number

| [ size ] decimal_base x_digit { _ }

| [ size ] decimal_base z_digit { _ }

binary_number ::= [ size ] binary_base binary_value

octal_number ::= [ size ] octal_base octal_value

hex_number ::= [ size ] hex_base hex_value

sign ::= + | -

size ::= non_zero_unsigned_number

non_zero_unsigned_number1 ::= non_zero_decimal_digit { _ | decimal_digit}

real_number1 ::=

fixed_point_number

| unsigned_number [ . unsigned_number ] exp [ sign ] unsigned_number

fixed_point_number1 ::= unsigned_number . unsigned_number

exp ::= e | E

unsigned_number1 ::= decimal_digit { _ | decimal_digit }

binary_value1 ::= binary_digit { _ | binary_digit }

octal_value1 ::= octal_digit { _ | octal_digit }

hex_value1 ::= hex_digit { _ | hex_digit }

decimal_base1 ::= ’[s|S]d | ’[s|S]D

binary_base1 ::= ’[s|S]b | ’[s|S]B

octal_base1 ::= ’[s|S]o | ’[s|S]O

hex_base1 ::= ’[s|S]h | ’[s|S]H

non_zero_decimal_digit ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

decimal_digit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

binary_digit ::= x_digit | z_digit | 0 | 1

octal_digit ::= x_digit | z_digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7

hex_digit ::= x_digit | z_digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | A | B | C | D | E | F

x_digit ::= x | X

z_digit ::= z | Z | ?

unbased_unsized_literal ::= '0 | '1 | 'z_or_x 10

Group

A.8 Expressions

链接
A.8 Expressions


A.8.8 Strings

链接
A.8 Expressions
SystemVerilog 3.1a语言参考手册
A.8.8 Strings
A.8 Expressions

string_literal ::= " { Any_ASCII_Characters }

Group

A.8 Expressions

链接
A.8 Expressions


A.9 General

链接
附录A 形式语法, 主题
SystemVerilog 3.1a语言参考手册
A.9 General
附录A 形式语法 | 主题
Group

附录A 形式语法

主题
主题
描述
A.9.1 Attributes
attribute_instance ::= (* attr_spec { , attr_spec } *)
attr_spec ::= attr_name [ = constant_expression ]
attr_name ::= identifier
A.9.2 Comments
comment ::=
one_line_comment
| block_comment
one_line_comment ::= // comment_text \n
block_comment ::= /* comment_text */
comment_text ::= { Any_ASCII_character }
A.9.3 Identifiers
array_identifier ::= identifier
block_identifier ::= identifier
bin_identifier ::= identifier
c_identifier2 ::= [ a-zA-Z_ ] { [ a-zA-Z0-9_ ] }
cell_identifier ::= identifier
class_identifier ::= identifier
class_variable_identifier ::= variable_identifier
clocking_identifier ::= identifier
config_identifier ::= identifier
constraint_identifier ::= identifier
covergroup_identifier ::= identifier
covergroup_variable_identifier ::= variable_identifier
cover_point_identifier ::= identifier
dynamic_array_variable_identifier ::= variable_identifier
enum_identifier ::= identifier
escaped_identifier ::= \ {any_ASCII_character_except_white_space} white_space
formal_identifier ::= identifier
function_identifier ::= identifier
generate_block_identifier ::= identifier
genvar_identifier ::= identifier
hierarchical_block_identifier ::= hierarchical_identifier
hierarchical_dynamic_array_variable_identifier ::= hierarchical_variable_identifier
hierarchical_event_identifier ::= hierarchical_identifier
hierarchical_identifier ::= [ $root . ] { identifier { [ constant_expression ] } . } identifier
hierarchical_net_identifier ::= hierarchical_identifier
hierarchical_parameter_identifier ::= hierarchical_identifier... more
A.9.4 White space
white_space ::= space | tab | newline | eof4
链接
附录A 形式语法, 主题


A.9.1 Attributes

链接
A.9 General
SystemVerilog 3.1a语言参考手册
A.9.1 Attributes
A.9 General

attribute_instance ::= (* attr_spec { , attr_spec } *)

attr_spec ::= attr_name [ = constant_expression ]

attr_name ::= identifier

Group

A.9 General

链接
A.9 General


A.9.2 Comments

链接
A.9 General
SystemVerilog 3.1a语言参考手册
A.9.2 Comments
A.9 General

comment ::=

one_line_comment

| block_comment

one_line_comment ::= // comment_text \n

block_comment ::= /* comment_text */

comment_text ::= { Any_ASCII_character }

Group

A.9 General

链接
A.9 General


A.9.3 Identifiers

链接
A.9 General
SystemVerilog 3.1a语言参考手册
A.9.3 Identifiers
A.9 General

array_identifier ::= identifier

block_identifier ::= identifier

bin_identifier ::= identifier

c_identifier2 ::= [ a-zA-Z_ ] { [ a-zA-Z0-9_ ] }

cell_identifier ::= identifier

class_identifier ::= identifier

class_variable_identifier ::= variable_identifier

clocking_identifier ::= identifier

config_identifier ::= identifier

constraint_identifier ::= identifier

covergroup_identifier ::= identifier

covergroup_variable_identifier ::= variable_identifier

cover_point_identifier ::= identifier

dynamic_array_variable_identifier ::= variable_identifier

enum_identifier ::= identifier

escaped_identifier ::= \ {any_ASCII_character_except_white_space} white_space

formal_identifier ::= identifier

function_identifier ::= identifier

generate_block_identifier ::= identifier

genvar_identifier ::= identifier

hierarchical_block_identifier ::= hierarchical_identifier

hierarchical_dynamic_array_variable_identifier ::= hierarchical_variable_identifier

hierarchical_event_identifier ::= hierarchical_identifier

hierarchical_identifier ::= [ $root . ] { identifier { [ constant_expression ] } . } identifier

hierarchical_net_identifier ::= hierarchical_identifier

hierarchical_parameter_identifier ::= hierarchical_identifier

hierarchical_task_identifier ::= hierarchical_identifier

hierarchical_tf_identifier ::= hierarchical_identifier

hierarchical_variable_identifier ::= hierarchical_identifier

identifier ::=

simple_identifier

| escaped_identifier

index_variable_identifier ::= identifier

interface_identifier ::= identifier

interface_instance_identifier ::= identifier

inout_port_identifier ::= identifier

input_port_identifier ::= identifier

instance_identifier ::= identifier

library_identifier ::= identifier

member_identifier ::= identifier

method_identifier ::= identifier

modport_identifier ::= identifier

module_identifier ::= identifier

net_identifier ::= identifier

output_port_identifier ::= identifier

package_identifier ::= identifier

package_scope ::=

package_identifier ::

| $unit ::

parameter_identifier ::= identifier

port_identifier ::= identifier

program_identifier ::= identifier

property_identifier ::= identifier

ps_class_identifier ::= [ package_scope ] class_identifier

ps_covergroup_identifier ::= [ package_scope ] covergroup_identifier

ps_identifier ::= [ package_scope ] identifier

ps_or_hierarchical_net_identifier ::= [ package_scope ] net_identifier | hierarchical_net_identifier

ps_or_hierarchical_tf_identifier ::= [ package_scope ] tf_identifier | hierarchical_tf_identifier

ps_parameter_identifier ::= [ package_scope ] parameter_identifier

ps_property_identifier ::= [ package_scope ] property_identifier

ps_sequence_identifier ::= [ package_scope ] sequence_identifier

ps_specparam_identifier ::= [ package_scope ] specparam_identifier

ps_type_identifier ::= [ package_scope ] type_identifier

sequence_identifier ::= identifier

signal_identifier ::= identifier

simple_identifier2 ::= [ a-zA-Z_ ] { [ a-zA-Z0-9_$ ] }

specparam_identifier ::= identifier

system_tf_identifier3 ::= $[ a-zA-Z0-9_$ ]{ [ a-zA-Z0-9_$ ] }

task_identifier ::= identifier

tf_identifier ::= identifier

terminal_identifier ::= identifier

topmodule_identifier ::= identifier

type_identifier ::= identifier

udp_identifier ::= identifier

variable_identifier ::= identifier

Group

A.9 General

链接
A.9 General


A.9.4 White space

链接
A.9 General
SystemVerilog 3.1a语言参考手册
A.9.4 White space
A.9 General

white_space ::= space | tab | newline | eof4

Group

A.9 General

链接
A.9 General


A.10 Footnotes (normative)

链接
附录A 形式语法
SystemVerilog 3.1a语言参考手册
A.10 Footnotes (normative)
附录A 形式语法

  1. Embedded spaces are illegal.
  2. A simple_identifier, c_identifier, and arrayed_reference shall start with an alpha or underscore ( _ ) character, shall have at least one character, and shall not have any spaces.
  3. The $ character in a system_tf_identifier shall not be followed by white_space. A system_tf_identifier shall not be escaped.
  4. End of file.
  5. The unsigned number or fixed point number in time_literal shall not be followed by a white_space.
  6. implicit_class_handle shall only appear within the scope of a class_declaration or out-of-block method declaration.
  7. In any one declaration, only one of protected or local is allowed, only one of rand or randc is allowed, and static and/or virtual can appear only once.
  8. dpi_function_proto return types are restricted to small values, as per 27.4.5.
  9. Formals of dpi_function_proto and dpi_task_proto cannot use pass by reference mode and class types cannot be passed at all; for the complete set of restrictions see 27.4.6.
  10. The apostrophe ( ‘ ) in unbased_unsized_literal shall not be followed by white_space.
  11. unsized_dimension is permitted only in declarations of import DPI functions, see dpi_function_proto.
  12. More than one unsized dimension is permitted only in declarations of import DPI functions, see dpi_function_proto.
  13. When a packed dimension is used with the struct or union keyword, the packed keyword shall also be used.
  14. A charge strength shall only be used with the trireg keyword. When the vectored or scalared keyword is used, there shall be at least one packed dimension.
  15. In a data_declaration that is not within the procedural context, it shall be illegal to use the automatic keyword.
  16. It shall be legal to omit the covergroup_variable_identifer from a covergroup instantiation only if this implicit instantiation is within a class that has no other instantiation of the covergroup.
  17. The .* token shall appear at most once in a list of port connections.
  18. A timeunits_declaration shall be legal as a non_port_module_item, non_port_interface_item, non_port_program_item, package_item or class_item only if it repeats and matches a previous timeunits_declaration within the same time scope.
  19. In a multiple_concatenation, it shall be illegal for the multiplier not to be a constant_expression unless the type of the concatenation is string.
  20. In a shallow copy the expression must evaluate to an object handle.
  21. It shall be legal to use the $ primary in an open_value_range of the form [ expression : $ ] or [ $ : expression ].
  22. { } shall only be legal in the context of a queue.
  23. The $ primary shall be legal only in a select for a queue variable or in an open_value_range.
  24. A type_identifier shall be legal as an enum_base_type if it denotes an integer_atom_type, with which an additional packed dimension is not permitted, or an integer_vector_type.
  25. In a constant_function_call, all arguments shall be constant_expressions.
  26. The list_of_port_declarations syntax is explained in Section 18.8, which also imposes various semantic restrictions, e.g., a ref port must be of a variable type and an inout port must not be. It shall be illegal to initialize a port that is not a variable output port.
  27. It shall be legal to declare a void struct_union_member only within tagged unions.

Group

附录A 形式语法

链接
附录A 形式语法


附录B 关键字

附录B 关键字

SystemVerilog reserves the keywords listed in Table .

Legend:

— ? keywords added to the IEEE 1364 Verilog-2001 standard as part of SystemVerilog 3.0

— ? keywords added to the IEEE 1364 Verilog-2001 standard as part of SystemVerilog 3.1

— * keywords added to the IEEE 1364 Verilog-2001 standard as part of SystemVerilog 3.1a

Table B-1: Reserved keywords

Note: The keyword var is reserved for future extensions.


附录C 标准包

链接
主题
SystemVerilog 3.1a语言参考手册
附录C 标准包
主题

标准包包含了系统类型（参见7.10.1节）。std内建包提供了下列类型。这些类型的语义描述在相应的章节描述。

主题
主题 | 描述
C.1 semaphore | semaphore类在13.2节中描述，它的原型如下：
C.2 mailbox | mailbox类在13.3节中描述，它的原型如下：
C.3 randomize | 随机化函数在12.11节中描述，它的原形如下：
C.4 进程 | 进程类在9.9节中描述，它的原型如下：
链接
主题


C.1 semaphore

链接
附录C 标准包
SystemVerilog 3.1a语言参考手册
C.1 semaphore
附录C 标准包

semaphore类在13.2节中描述，它的原型如下：

Copy Code
class semaphore;
    function new(int keyCount = 0);
    task put(int keyCount = 1);
    task put(int keyCount = 1);
    function int try_get(int keyCount = 1);
endclass
Group

附录C 标准包

链接
附录C 标准包


C.2 mailbox

链接
附录C 标准包
SystemVerilog 3.1a语言参考手册
C.2 mailbox
附录C 标准包

mailbox类在13.3节中描述，它的原型如下：

Copy Code
class mailbox #(type T = dynamic_singular_type);
    function new(int bound = 0);
    function int num();
    task put(T message);
    function int try_put(T message);
    task get(ref T message);
    function int try_get(ref T message);
    task peek(ref T message);
    function int try_peek(ref T message);
endclass

注意：上面的dynamic_singular_type代表了一个特殊的类型，它能够执行运行时的类型检查。

Group

附录C 标准包

链接
附录C 标准包


C.3 randomize

链接
附录C 标准包
SystemVerilog 3.1a语言参考手册
C.3 randomize
附录C 标准包

随机化函数在12.11节中描述，它的原形如下：

Copy Code
function int randomize(...);

随机化函数的语法如下：

Copy Code
randomize(variable_identifier{, variable_identifier})
    [with constraint_block];
Group

附录C 标准包

链接
附录C 标准包


C.4 进程

链接
附录C 标准包
SystemVerilog 3.1a语言参考手册
C.4 进程
附录C 标准包

进程类在9.9节中描述，它的原型如下：

Copy Code
class process;
    enum state {FINISHED, RUNNING, WAITING, SUSPENDED, KILLED};
    static function process self();
    function state status();
    task kill();
    task await();
    task suspend();
    task resume();
endclass
Group

附录C 标准包

链接
附录C 标准包


附录D 链表

链接
主题
SystemVerilog 3.1a语言参考手册
附录D 链表
主题

The List package implements a classic list data-structure, and is analogous to the STL (Standard Template Library) List container that is popular with C++ programmers. The container is defined as a parameterized class, meaning that it can be customized to hold data of any type.

主题
主题 | 描述
D.1 List definitions | list—A list is a doubly linked list, where every element has a predecessor and successor. A list is a sequence that supports both forward and backward traversal, as well as amortized constant time insertion and removal of elements at the beginning, end, or middle. container—A container is a collection of data of the same type. Containers are objects that contain and manage other data. Containers provide an associated iterator that allows access to the contained data. iterator—Iterators are objects that represent positions of elements in a container. They play a role similar to that of an array subscript, and allow... more
D.2 List declaration | The List package supports lists of any arbitrary predefined type, such as integer, string, or class object. Any iterator that refers to the position of an element that is removed from a list becomes invalid, thus, unable to iterate over the list. To declare a specific list, users must first include the generic List class declaration from the standard include area and then declare the specialized list type: ‘include <List.vh> ... List#(type) dl; // dl is a List of 'type' elements
D.3 Linked list class prototypes | The following class prototypes describe the generic List and List_Iterator classes. Only the public interface is included here.
D.4 List_Iterator methods | The List_Iterator class provides methods to iterate over the elements of lists. These methods are described below.
D.5 List methods | The List class provides methods to query the size of the list, obtain iterators to the head or tail of the list,retrieve the data stored in the list, and methods to add, remove, and reorder the elements of the list.
链接
主题


D.1 List definitions

链接
附录D 链表
SystemVerilog 3.1a语言参考手册
D.1 List definitions
附录D 链表

list—A list is a doubly linked list, where every element has a predecessor and successor. A list is a sequence that supports both forward and backward traversal, as well as amortized constant time insertion and removal of elements at the beginning, end, or middle.

container—A container is a collection of data of the same type. Containers are objects that contain and manage other data. Containers provide an associated iterator that allows access to the contained data.

iterator—Iterators are objects that represent positions of elements in a container. They play a role similar to that of an array subscript, and allow users to access a particular element, and to traverse through the container.

Group

附录D 链表

链接
附录D 链表


D.2 List declaration

链接
附录D 链表, 主题
SystemVerilog 3.1a语言参考手册
D.2 List declaration
附录D 链表 | 主题

The List package supports lists of any arbitrary predefined type, such as integer, string, or class object.

Any iterator that refers to the position of an element that is removed from a list becomes invalid, thus, unable to iterate over the list.

To declare a specific list, users must first include the generic List class declaration from the standard include area and then declare the specialized list type:

‘include <List.vh>

...

List#(type) dl; // dl is a List of 'type' elements

Group

附录D 链表

主题
主题 | 描述
D.2.1 Declaring list variables | List variables are declared by providing a specialization of the generic list class:
D.2.2 Declaring list iterators | List iterators are declared by providing a specialization of the generic List_Iterator class:
链接
附录D 链表, 主题


D.2.1 Declaring list variables

链接
D.2 List declaration
SystemVerilog 3.1a语言参考手册
D.2.1 Declaring list variables
D.2 List declaration

List variables are declared by providing a specialization of the generic list class:

Copy Code
List#(integer) il; // Object il is a list of integer
typedef List#(Packet) PList; // Class Plist is a list of Packet objects

The List specialization declares a list of the indicated type. The type used in the list declaration determines the type of the data stored in the list elements.

Group

D.2 List declaration

链接
D.2 List declaration


D.2.2 Declaring list iterators

链接
D.2 List declaration
SystemVerilog 3.1a语言参考手册
D.2.2 Declaring list iterators
D.2 List declaration

List iterators are declared by providing a specialization of the generic List_Iterator class:

Copy Code
List_Iterator#(string) s; // Object s is a list-of-string iterator
List_Iterator#(Packet) p, q; // p and q are iterators to a list-of-Packet
Group

D.2 List declaration

链接
D.2 List declaration


D.3 Linked list class prototypes

链接
附录D 链表, 主题
SystemVerilog 3.1a语言参考手册
D.3 Linked list class prototypes
附录D 链表 | 主题

The following class prototypes describe the generic List and List_Iterator classes. Only the public interface is included here.

Group

附录D 链表

主题
主题
描述
D.3.1 List_Iterator class prototype
D.3.2 List class prototype
class List#(parameter type T);
extern function new();
extern function int size();
extern function int empty();
extern function void push_front( T value );
extern function void push_back( T value );
extern function T front();
extern function T back();
extern function void pop_front();
extern function void pop_back();
extern function List_Iterator#(T) start();
extern function List_Iterator#(T) finish();
extern function void insert( List_Iterator#(T) position, T value );
extern function void insert_range( List_Iterator#(T) position,
first, last );
extern function void erase( List_Iterator#(T) position );
extern function void erase_range( List_Iterator#(T) first, last );
extern function void set( List_Iterator#(T) first, last );
extern function void swap( List#(T) lst... more
链接
附录D 链表, 主题


D.3.1 List_Iterator class prototype

链接
D.3 Linked list class prototypes
SystemVerilog 3.1a语言参考手册
D.3.1 List_Iterator class prototype
D.3 Linked list class prototypes
Copy Code
class List_Iterator#(parameter type T);
extern function void next();
extern function void prev();
extern function int neq( List_Iterator#(T) iter );
extern function int eq( List_Iterator#(T) iter );
extern function T data();
endclass
Group

D.3 Linked list class prototypes

链接
D.3 Linked list class prototypes


D.3.2 List class prototype

链接
D.3 Linked list class prototypes
SystemVerilog 3.1a语言参考手册
D.3.2 List class prototype
D.3 Linked list class prototypes

class List#(parameter type T);

extern function new();

extern function int size();

extern function int empty();

extern function void push_front( T value );

extern function void push_back( T value );

extern function T front();

extern function T back();

extern function void pop_front();

extern function void pop_back();

extern function List_Iterator#(T) start();

extern function List_Iterator#(T) finish();

extern function void insert( List_Iterator#(T) position, T value );

extern function void insert_range( List_Iterator#(T) position,

first, last );

extern function void erase( List_Iterator#(T) position );

extern function void erase_range( List_Iterator#(T) first, last );

extern function void set( List_Iterator#(T) first, last );

extern function void swap( List#(T) lst );

extern function void clear();

extern function void purge();

endclass

Group

D.3 Linked list class prototypes

链接
D.3 Linked list class prototypes


D.4 List_Iterator methods

链接
附录D 链表, 主题
SystemVerilog 3.1a语言参考手册
D.4 List_Iterator methods
附录D 链表 | 主题

The List_Iterator class provides methods to iterate over the elements of lists. These methods are described below.

Group

附录D 链表

主题
主题
描述
D.4.1 next()
function void next();
next changes the iterator so that it refers to the next element in the list.
D.4.2 prev()
function void prev();
prev changes the iterator so that it refers to the previous element in the list.
D.4.3 eq()
function int eq( List_Iterator#(T) iter );
eq compares two iterators, and returns 1 if both iterators refer to the same list element. Otherwise, it returns 0.
if( i1.eq(i2) ) $display("both iterators refer to the same element");
D.4.4 neq()
D.4.5 data()
function T data();
data returns the data stored in the element at the given iterator location.
链接
附录D 链表, 主题


D.4.1 next()

链接
D.4 List_Iterator methods
SystemVerilog 3.1a语言参考手册
D.4.1 next()
D.4 List_Iterator methods

function void next();

next changes the iterator so that it refers to the next element in the list.

Group

D.4 List_Iterator methods

链接
D.4 List_Iterator methods


D.4.2 prev()

链接
D.4 List_Iterator methods
SystemVerilog 3.1a语言参考手册
D.4.2 prev()
D.4 List_Iterator methods

function void prev();

prev changes the iterator so that it refers to the previous element in the list.

Group

D.4 List_Iterator methods

链接
D.4 List_Iterator methods


D.4.3 eq()

链接
D.4 List_Iterator methods
SystemVerilog 3.1a语言参考手册
D.4.3 eq()
D.4 List_Iterator methods

function int eq( List_Iterator#(T) iter );

eq compares two iterators, and returns 1 if both iterators refer to the same list element. Otherwise, it returns 0.

if( i1.eq(i2) ) $display("both iterators refer to the same element");

Group

D.4 List_Iterator methods

链接
D.4 List_Iterator methods


D.4.4 neq()

链接
D.4 List_Iterator methods
SystemVerilog 3.1a语言参考手册
D.4.4 neq()
D.4 List_Iterator methods
Copy Code
function int neq( List_Iterator#(T) iter );

neq is the negation of eq(); it compares two iterators, and returns 0 if both iterators refer to the same list element. Otherwise, it returns 1.

Group

D.4 List_Iterator methods

链接
D.4 List_Iterator methods


D.4.5 data()

链接
D.4 List_Iterator methods
SystemVerilog 3.1a语言参考手册
D.4.5 data()
D.4 List_Iterator methods

function T data();

data returns the data stored in the element at the given iterator location.

Group

D.4 List_Iterator methods

链接
D.4 List_Iterator methods


D.5 List methods

链接
附录D 链表, 主题
SystemVerilog 3.1a语言参考手册
D.5 List methods
附录D 链表 | 主题

The List class provides methods to query the size of the list, obtain iterators to the head or tail of the list,retrieve the data stored in the list, and methods to add, remove, and reorder the elements of the list.

Group

附录D 链表

主题
主题
描述
D.5.1 size()
function int size();
size returns the number of elements stored in the list.
while ( list1.size > 0 ) begin // loop while still elements in the list
...
end
D.5.2 empty()
function int empty();
empty returns 1 if the number elements stored in the list is zero, 0 otherwise.
if ( list1.empty )
$display( "list is empty" );
D.5.3 push_front()
function void push_front( T value );
push_front inserts the specified value at the front of the list.
List#(int) numbers;
numbers.push_front(10);
numbers.push_front(5); // numbers contains { 5 , 10 }
D.5.4 push_back()
function void push_back( T value );
push_back inserts the specified value at the end of the list.
List#(string) names;
names.push_back("Donald");
names.push_back("Mickey"); // names contains { "Donald", "Mickey" }
D.5.5 front()
function T front();
front returns the data stored in the first element of the list (valid only if the list is not empty).
D.5.6 back()
function T back();
back returns the data stored in the last element of the list (valid only if the list is not empty).
List#(int) numbers;
numbers.push_front(3);
numbers.push_front(2);
numbers.push_front(1);
$display( numbers.front, numbers.back ); // displays 1 3
D.5.7 pop_front()
function void pop_front();
pop_front removes the first element of the list. If the list is empty, this method is illegal and can generate an error.
D.5.8 pop_back()
function void pop_back();
pop_back removes the last element of the list. If the list is empty, this method is illegal and can generate an error.
while ( lp.size > 1 ) begin // remove all but the center element from
// an odd-sized list lp
lp.pop_front();
lp.pop_back();
end
D.5.9 start()
function List_Iterator#(T) start();
start returns an iterator to the position of the first element in the list.
D.5.10 finish()
function List_Iterator#(T) finish();
finish returns an iterator to a position just past the last element in the list. The last element in the last can be accessed using finish.prev.
List#(int) lst; // display contents of list lst in position order
for ( List_Iterator#(int) p = lst.start; p.neq(lst.finish); p.next )
$display( p.data );
D.5.11 insert()
function void insert( List_Iterator#(T) position, T value );
insert inserts the given data (value) into the list at the position specified by the iterator (before the element, if any, that was previously at the iterator’s position). If the iterator is not a valid position within the list, then this operation is illegal and can generate an error.
function void add_sort( List#(byte) L, byte value );
for ( List_Iterator#(byte) p = L.start; p.neq(L.finish) ; p.next )
if ( p.data > value ) begin
lst.insert( p, value ); // Add to sorted list (ascending order)
return;
end
endfunction
D.5.12 insert_range()
function void insert_range( List_Iterator#(T) position, first, last );
insert_range inserts the elements contained in the list range specified by the iterators first and last at the specified list position (before the element, if any, that was previously at the position iterator). All the elements from first up to, but not including, last are inserted into the list. If the last iterator refers to an element before the first iterator, the range wraps around the end of the list. The range iterators can specify a range either in another list or in the same list as being inserted.

If the position... more
D.5.13 erase()
function void erase( List_Iterator#(T) position );
erase removes form the list the element at the specified position. After erase() returns, the position iterator becomes invalid.
list1.erase( list1.start ); // same as pop_front
If the position iterator is not a valid position within the list, this operation is illegal and can generate an error.
D.5.14 erase_range()
function void erase_range( List_Iterator#(T) first, last );
erase_range removes from a list the range of elements specified by the first and last iterators. This operation removes elements from the first iterator’s position up to, but not including, the last iterator’s position. If the last iterator refers to an element before the first iterator, the range wraps around the end of the list.
list1.erase_range( list1.start, list1.finish ); // Remove all elements from
// list1
If the range iterators are invalid (i.e., they refer to different lists or to invalid positions), then this operation is illegal and can generate an error.
D.5.15 set()
function void set( List_Iterator#(T) first, last );
set assigns to the list object the elements that lie in the range specified by the first and last iterators. After this method returns, the modified list shall have a size equal to the range specified by first and last. This method copies the data from the first iterator’s position up to, but not including, the last iterator’s position. If the last iterator refers to an element before the first iterator, the range wraps around the end of the list.
list2.set( list1.start, list2.finish ); // list2 is a copy of list1
If the... more
D.5.16 swap()
function void swap( List#(T) lst );
swap exchanges the contents of two equal-size lists.
list1.swap( list2 ); // swap the contents of list1 to list2 and vice-versa
Swapping a list with itself has no effect. If the lists are of different sizes, this method can issue a warning.
D.5.17 clear()
function void clear();
clear removes all the elements from a list, but not the list itself (i.e., the list header itself).
list1.clear(); // list1 becomes empty
D.5.18 purge()
function void purge();
purge removes all the list elements (as in clear) and the list itself. This accomplishes the same effect as assigning null to the list. A purged list must be re-created using new before it can be used again.
list1.purge(); // same as list1 = null
链接
附录D 链表, 主题


D.5.1 size()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.1 size()
D.5 List methods

function int size();

size returns the number of elements stored in the list.

while ( list1.size > 0 ) begin // loop while still elements in the list

...

end

Group

D.5 List methods

链接
D.5 List methods


D.5.2 empty()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.2 empty()
D.5 List methods

function int empty();

empty returns 1 if the number elements stored in the list is zero, 0 otherwise.

if ( list1.empty )

$display( "list is empty" );

Group

D.5 List methods

链接
D.5 List methods


D.5.3 push_front()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.3 push_front()
D.5 List methods

function void push_front( T value );

push_front inserts the specified value at the front of the list.

List#(int) numbers;

numbers.push_front(10);

numbers.push_front(5); // numbers contains { 5 , 10 }

Group

D.5 List methods

链接
D.5 List methods


D.5.4 push_back()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.4 push_back()
D.5 List methods

function void push_back( T value );

push_back inserts the specified value at the end of the list.

List#(string) names;

names.push_back("Donald");

names.push_back("Mickey"); // names contains { "Donald", "Mickey" }

Group

D.5 List methods

链接
D.5 List methods


D.5.5 front()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.5 front()
D.5 List methods

function T front();

front returns the data stored in the first element of the list (valid only if the list is not empty).

Group

D.5 List methods

链接
D.5 List methods


D.5.6 back()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.6 back()
D.5 List methods

function T back();

back returns the data stored in the last element of the list (valid only if the list is not empty).

List#(int) numbers;

numbers.push_front(3);

numbers.push_front(2);

numbers.push_front(1);

$display( numbers.front, numbers.back ); // displays 1 3

Group

D.5 List methods

链接
D.5 List methods


D.5.7 pop_front()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.7 pop_front()
D.5 List methods

function void pop_front();

pop_front removes the first element of the list. If the list is empty, this method is illegal and can generate an error.

Group

D.5 List methods

链接
D.5 List methods


D.5.8 pop_back()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.8 pop_back()
D.5 List methods

function void pop_back();

pop_back removes the last element of the list. If the list is empty, this method is illegal and can generate an error.

while ( lp.size > 1 ) begin // remove all but the center element from

// an odd-sized list lp

lp.pop_front();

lp.pop_back();

end

Group

D.5 List methods

链接
D.5 List methods


D.5.9 start()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.9 start()
D.5 List methods

function List_Iterator#(T) start();

start returns an iterator to the position of the first element in the list.

Group

D.5 List methods

链接
D.5 List methods


D.5.10 finish()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.10 finish()
D.5 List methods

function List_Iterator#(T) finish();

finish returns an iterator to a position just past the last element in the list. The last element in the last can be accessed using finish.prev.

List#(int) lst; // display contents of list lst in position order

for ( List_Iterator#(int) p = lst.start; p.neq(lst.finish); p.next )

$display( p.data );

Group

D.5 List methods

链接
D.5 List methods


D.5.11 insert()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.11 insert()
D.5 List methods

function void insert( List_Iterator#(T) position, T value );

insert inserts the given data (value) into the list at the position specified by the iterator (before the element, if any, that was previously at the iterator’s position). If the iterator is not a valid position within the list, then this operation is illegal and can generate an error.

function void add_sort( List#(byte) L, byte value );

for ( List_Iterator#(byte) p = L.start; p.neq(L.finish) ; p.next )

if ( p.data > value ) begin

lst.insert( p, value ); // Add to sorted list (ascending order)

return;

end

endfunction

Group

D.5 List methods

链接
D.5 List methods


D.5.12 insert_range()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.12 insert_range()
D.5 List methods

function void insert_range( List_Iterator#(T) position, first, last );

insert_range inserts the elements contained in the list range specified by the iterators first and last at the specified list position (before the element, if any, that was previously at the position iterator). All the elements from first up to, but not including, last are inserted into the list. If the last iterator refers to an element before the first iterator, the range wraps around the end of the list. The range iterators can specify a range either in another list or in the same list as being inserted.

If the position iterator is not a valid position within the list, or if the range iterators are invalid (i.e., they refer to different lists or to invalid positions), then this operation is illegal and can generate an error.

Group

D.5 List methods

链接
D.5 List methods


D.5.13 erase()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.13 erase()
D.5 List methods

function void erase( List_Iterator#(T) position );

erase removes form the list the element at the specified position. After erase() returns, the position iterator becomes invalid.

list1.erase( list1.start ); // same as pop_front

If the position iterator is not a valid position within the list, this operation is illegal and can generate an error.

Group

D.5 List methods

链接
D.5 List methods


D.5.14 erase_range()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.14 erase_range()
D.5 List methods

function void erase_range( List_Iterator#(T) first, last );

erase_range removes from a list the range of elements specified by the first and last iterators. This operation removes elements from the first iterator’s position up to, but not including, the last iterator’s position. If the last iterator refers to an element before the first iterator, the range wraps around the end of the list.

list1.erase_range( list1.start, list1.finish ); // Remove all elements from

// list1

If the range iterators are invalid (i.e., they refer to different lists or to invalid positions), then this operation is illegal and can generate an error.

Group

D.5 List methods

链接
D.5 List methods


D.5.15 set()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.15 set()
D.5 List methods

function void set( List_Iterator#(T) first, last );

set assigns to the list object the elements that lie in the range specified by the first and last iterators. After this method returns, the modified list shall have a size equal to the range specified by first and last. This method copies the data from the first iterator’s position up to, but not including, the last iterator’s position. If the last iterator refers to an element before the first iterator, the range wraps around the end of the list.

list2.set( list1.start, list2.finish ); // list2 is a copy of list1

If the range iterators are invalid (i.e., they refer to different lists or to invalid positions), then this operation is illegal and can generate an error.

Group

D.5 List methods

链接
D.5 List methods


D.5.16 swap()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.16 swap()
D.5 List methods

function void swap( List#(T) lst );

swap exchanges the contents of two equal-size lists.

list1.swap( list2 ); // swap the contents of list1 to list2 and vice-versa

Swapping a list with itself has no effect. If the lists are of different sizes, this method can issue a warning.

Group

D.5 List methods

链接
D.5 List methods


D.5.17 clear()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.17 clear()
D.5 List methods

function void clear();

clear removes all the elements from a list, but not the list itself (i.e., the list header itself).

list1.clear(); // list1 becomes empty

Group

D.5 List methods

链接
D.5 List methods


D.5.18 purge()

链接
D.5 List methods
SystemVerilog 3.1a语言参考手册
D.5.18 purge()
D.5 List methods

function void purge();

purge removes all the list elements (as in clear) and the list itself. This accomplishes the same effect as assigning null to the list. A purged list must be re-created using new before it can be used again.

list1.purge(); // same as list1 = null

Group

D.5 List methods

链接
D.5 List methods


附录E DPI C-layer

链接
主题
SystemVerilog 3.1a语言参考手册
附录E DPI C-layer
主题
主题
主题
描述
E.1 概述
The SystemVerilog Direct Programming Interface (DPI) allows direct inter-language function calls between SystemVerilog and any foreign programming language with a C function call protocol and linking model:
  • Functions implemented in C and given import declarations in SystemVerilog can be called from System- Verilog; such functions are referred to as imported functions.
  • Functions implemented in SystemVerilog and specified in export declarations can be called from C; such functions are referred to as exported functions.
  • Tasks implemented in SystemVerilog and specified in export declarations can be called from C; such functions are referred to as exported tasks.
  • Functions implemented in C which... more
E.2 Naming conventions
All names introduced by this interface shall conform to the following conventions.
  • All names defined in this interface are prefixed with sv or SV_.
  • Function and type names start with sv, followed by initially capitalized words with no separators, e.g., svBitPackedArrRef.
  • Names of symbolic constants start with sv_, e.g., sv_x.
  • Names of macro definitions start with SV_, followed by all upper-case words separated by a underscore (_), e.g., SV_CANONICAL_SIZE.
E.3 Portability
Depending on the data types used for imported or exported tasks or functions, the C code can be binary-level or source-level compatible. Applications that do not use SystemVerilog packed types are always binary compatible. Applications that don’t mix SystemVerilog packed and unpacked types in the same data type can be written to guarantee binary compatibility. Open arrays with both packed and unpacked parts are also binary compatible.

The values of SystemVerilog packed types can be accessed via interface tasks or functions using the canonical representation of 2-state and 4-state packed arrays, or directly through pointers using the implementation representation. The... more
E.4 Include files
The C-layer of the Direct Programming Interface defines two include files corresponding to these two levels of compatibility: svdpi.h and svdpi_src.h.

Binary compatibility of an application depends on the data types of the values passed through the interface. If all corresponding type definitions can be written in C without the need to include the svdpi_src.h file, then an application is binary compatible. If the svdpi_src.h file is required, then the application is not binary compatible and needs to be recompiled for each simulator of choice.

Applications that pass solely C-compatible data types or standalone packed arrays (both 2-state and 4-state)... more
E.5 Semantic constraints
Formal and actual arguments of both imported tasks or functions and exported tasks or functions are bound by the principle “What You Specify Is What You Get.” This principle is binding both for the caller and for the callee, in C code and in SystemVerilog code. For the callee, it guarantees the actual arguments are as specified for the formal ones. For the caller, it means the function call arguments shall conform with the types of the formal arguments, which might require type-coercion on the caller side.

Another way to state this is that no compiler (either C or SystemVerilog)... more
E.6 Data types
This section defines the data types of the C-layer of the Direct Programming Interface.
E.7 Argument passing modes
This section defines the ways to pass arguments in the C-layer of the Direct Programming Interface.
E.8 Context tasks and functions
Some DPI imported tasks and functions require that the context of their call is known. For example, those calls can be associated with instances of C models that have a one-to-one correspondence with instances of SystemVerilog modules that are making the calls. Alternatively, a DPI imported task or function might need to access or modify simulator data structures using PLI or VPI calls, or by making a call back into SystemVerilog via an export task or function. Context knowledge is required for such calls to function properly. It can take special instrumentation of their call to provide such context.

To... more
E.9 Include files
The C-layer of the Direct Programming Interface defines two include files. The main include file, svdpi.h, is implementation-independent and defines the canonical representation, all basic types, and all interface functions. The second include file, svdpi_src.h, defines only the actual representation of packed arrays and, hence, is implementation-dependent. Both files are shown in Annex B.

Applications which do not need to include svdpi_src.h are binary-level compatible.
E.10 Arrays
Normalized ranges are used for accessing SystemVerilog arrays, with the exception of formal arguments specified as open arrays.
E.11 Open arrays
Formal arguments specified as open arrays allows passing actual arguments of different sizes (i.e., different range and/or different number of elements), which facilitates writing more general C code that can handle SystemVerilog arrays of different sizes. The elements of an open array can be accessed in C by using the same range of indices and the same indexing as in SystemVerilog. Plus, inquiries about the dimensions and the original boundaries of SystemVerilog actual arguments are supported for open arrays.

NOTE—Both packed and unpacked array dimensions can be unsized.

All formal arguments declared in SystemVerilog as open arrays are passed by... more
链接
主题


E.1 概述

链接
附录E DPI C-layer
SystemVerilog 3.1a语言参考手册
E.1 概述
附录E DPI C-layer

The SystemVerilog Direct Programming Interface (DPI) allows direct inter-language function calls between SystemVerilog and any foreign programming language with a C function call protocol and linking model:

  • Functions implemented in C and given import declarations in SystemVerilog can be called from System- Verilog; such functions are referred to as imported functions.
  • Functions implemented in SystemVerilog and specified in export declarations can be called from C; such functions are referred to as exported functions.
  • Tasks implemented in SystemVerilog and specified in export declarations can be called from C; such functions are referred to as exported tasks.
  • Functions implemented in C which can be called from SystemVerilog, and can in turn call exported tasks, are referred to as imported tasks.
The SystemVerilog DPI supports only SystemVerilog data types, which are the sole data types that can cross the boundary between SystemVerilog and a foreign language in either direction. On the other hand, the data types used in C code shall be C types; hence, the duality of types.

A value that is passed through the Direct Programming Interface is specified in SystemVerilog code as a value of SystemVerilog type, while the same value shall be specified in C code as a value of C type. Therefore, a pair of matching type definitions is required to pass a value through DPI: the SystemVerilog definition and the C definition.

It is the user’s responsibility to provide these matching definitions. A tool (such as a SystemVerilog compiler) can facilitate this by generating C type definitions for the SystemVerilog definitions used in DPI for imported and exported functions.

Some SystemVerilog types are directly compatible with C types; defining a matching C type for them is straightforward. There are, however, SystemVerilog-specific types, namely packed types (arrays, structures, and unions), 2-state or 4-state, which have no natural correspondence in C. DPI does not require any particular representation of such types and does not impose any restrictions on SystemVerilog implementations. This allows implementers to choose the layout and representation of packed types that best suits their simulation performance.

While not specifying the actual representation of packed types, this C-layer interface defines a canonical representation of packed 2-state and 4-state arrays. This canonical representation is actually based on legacy Verilog Programming Language Interface’s (PLI’s) avalue/bvalue representation of 4-state vectors. Library functions provide the translation between the representation used in a simulator and the canonical representation of packed arrays. There are also functions for bit selects and limited part selects for packed arrays, which do not require the use of the canonical representation.

Formal arguments in SystemVerilog can be specified as open arrays solely in import declarations; exported SystemVerilog functions cannot have formal arguments specified as open arrays. A formal argument is an open array when a range of one or more of its dimensions is unspecified (denoted in SystemVerilog by using empty square brackets ([])). This corresponds to a relaxation of the DPI argument-matching rules (Section 27.5.1). An actual argument shall match the corresponding formal argument regardless of the range(s) for its corresponding dimension(s), which facilitates writing generalized C code that can handle SystemVerilog arrays of different sizes.

The C-layer of DPI basically uses normalized ranges. Normalized ranges mean [n-1:0] indexing for the packed part (packed arrays are restricted to one dimension) and [0:n-1] indexing for a dimension in the unpacked part of an array. Normalized ranges are used for the canonical representation of packed arrays in C and for System Verilog arrays passed as actual arguments to C, with the exception of actual arguments for open arrays. The elements of an open array can be accessed in C by using the same range of indices as defined in System Verilog for the actual argument for that open array and the same indexing as in SystemVerilog.

Function arguments are generally passed by some form of reference or by value. All formal arguments, except open arrays, are passed by direct reference or value, and, therefore, are directly accessible in C code. Only small values of SystemVerilog input arguments (see Annex E.7.7) are passed by value. Formal arguments declared in SystemVerilog as open arrays are passed by a handle (type svOpenArrayHandle) and are accessible via library functions. Array-querying functions are provided for open arrays.

Depending on the data types used for imported or exported functions, either binary level or C-source level compatibility is granted. Binary level is granted for all data types that do not mix SystemVerilog packed and unpacked types and for open arrays which can have both packed and unpacked parts. If a data type that mixes SystemVerilog packed and unpacked types is used, then the C code needs to be re-compiled using the implementation-dependent definitions provided by the vendor.

The C-layer of the Direct Programming Interface provides two include files. The main include file, svdpi.h, is implementation-independent and defines the canonical representation, all basic types, and all interface functions. The second include file, svdpi_src.h, defines only the actual representation of packed arrays and, hence, its contents are implementation-dependent. Applications that do not need to include this file are binarylevel compatible.

Group

附录E DPI C-layer

链接
附录E DPI C-layer


E.2 Naming conventions

链接
附录E DPI C-layer
SystemVerilog 3.1a语言参考手册
E.2 Naming conventions
附录E DPI C-layer

All names introduced by this interface shall conform to the following conventions.

  • All names defined in this interface are prefixed with sv or SV_.
  • Function and type names start with sv, followed by initially capitalized words with no separators, e.g., svBitPackedArrRef.
  • Names of symbolic constants start with sv_, e.g., sv_x.
  • Names of macro definitions start with SV_, followed by all upper-case words separated by a underscore (_), e.g., SV_CANONICAL_SIZE.

Group

附录E DPI C-layer

链接
附录E DPI C-layer


E.3 Portability

链接
附录E DPI C-layer, 主题
SystemVerilog 3.1a语言参考手册
E.3 Portability
附录E DPI C-layer | 主题

Depending on the data types used for imported or exported tasks or functions, the C code can be binary-level or source-level compatible. Applications that do not use SystemVerilog packed types are always binary compatible. Applications that don’t mix SystemVerilog packed and unpacked types in the same data type can be written to guarantee binary compatibility. Open arrays with both packed and unpacked parts are also binary compatible.

The values of SystemVerilog packed types can be accessed via interface tasks or functions using the canonical representation of 2-state and 4-state packed arrays, or directly through pointers using the implementation representation. The former mode assures binary level compatibility; the latter one allows for tool-specific, performance-oriented tuning of an application, though it also requires recompiling with the implementation-dependent definitions provided by the vendor and shipped with the simulator.

Group

附录E DPI C-layer

主题
主题 | 描述
E.3.1 Binary compatibility | Binary compatibility means an application compiled for a given platform shall work with every SystemVerilog simulator on that platform.
E.3.2 Source-level compatibility | Source-level compatibility means an application needs to be re-compiled for each SystemVerilog simulator andimplementation-specific definitions shall be required for the compilation.
链接
附录E DPI C-layer, 主题


E.3.1 Binary compatibility

链接
E.3 Portability
SystemVerilog 3.1a语言参考手册
E.3.1 Binary compatibility
E.3 Portability

Binary compatibility means an application compiled for a given platform shall work with every SystemVerilog simulator on that platform.

Group

E.3 Portability

链接
E.3 Portability


E.3.2 Source-level compatibility

链接
E.3 Portability
SystemVerilog 3.1a语言参考手册
E.3.2 Source-level compatibility
E.3 Portability

Source-level compatibility means an application needs to be re-compiled for each SystemVerilog simulator andimplementation-specific definitions shall be required for the compilation.

Group

E.3 Portability

链接
E.3 Portability


E.4 Include files

链接
附录E DPI C-layer, 主题
SystemVerilog 3.1a语言参考手册
E.4 Include files
附录E DPI C-layer | 主题

The C-layer of the Direct Programming Interface defines two include files corresponding to these two levels of compatibility: svdpi.h and svdpi_src.h.

Binary compatibility of an application depends on the data types of the values passed through the interface. If all corresponding type definitions can be written in C without the need to include the svdpi_src.h file, then an application is binary compatible. If the svdpi_src.h file is required, then the application is not binary compatible and needs to be recompiled for each simulator of choice.

Applications that pass solely C-compatible data types or standalone packed arrays (both 2-state and 4-state) require only the svdpi.h file and, therefore, are binary compatible with all simulators. Applications that use complex data types which are constructed of both SystemVerilog packed arrays and C-compatible types also require the svdpi_src.h file and, therefore, are not binary compatible with all simulators. They are sourcelevel compatible, however. If an application is tuned for a particular vendor-specific representation of packed arrays and therefore needs vendor specific include files, then such an application is not source-level compatible.

Group

附录E DPI C-layer

主题
主题 | 描述
E.4.1 svdpi.h include file | Applications which use the Direct Programming Interface with C code usually need this main include file. The include file svdpi.h defines the types for canonical representation of 2-state (bit) and 4-state (logic) values and passing references to SystemVerilog data objects. The file also provides function headers and defines a number of helper macros and constants. This document fully defines the svdpi.h file. The content of svdpi.h does not depend on any particular implementation or platform; all simulators shall use the same file. For more details on svdpi.h, see Annex E.9.1. Applications which only use svdpi.h shall be binary-compatible with all... more
E.4.2 svdpi_src.h include file | This is an auxiliary include file. svdpi_src.h defines data structures for implementation-specific representation of 2-state and 4-state SystemVerilog packed arrays. The interface specifies the contents of this file, i.e., what symbols are defined. The actual definitions of those symbols, however, are implementation-specific and shall be provided by vendors. Applications that require the svdpi_src.h file are only source-level compatible, i.e., they need to be compiled with the version of svdpi_src.h provided for a particular implementation of SystemVerilog. If, however, an application makes use of the details of the implementation-specific representation of packed arrays and thus it requires vendor specific include files,... more
链接
附录E DPI C-layer, 主题


E.4.1 svdpi.h include file

链接
E.4 Include files
SystemVerilog 3.1a语言参考手册
E.4.1 svdpi.h include file
E.4 Include files

Applications which use the Direct Programming Interface with C code usually need this main include file. The include file svdpi.h defines the types for canonical representation of 2-state (bit) and 4-state (logic) values and passing references to SystemVerilog data objects. The file also provides function headers and defines a number of helper macros and constants.

This document fully defines the svdpi.h file. The content of svdpi.h does not depend on any particular implementation or platform; all simulators shall use the same file. For more details on svdpi.h, see Annex E.9.1.

Applications which only use svdpi.h shall be binary-compatible with all SystemVerilog simulators.

Group

E.4 Include files

链接
E.4 Include files


E.4.2 svdpi_src.h include file

链接
E.4 Include files
SystemVerilog 3.1a语言参考手册
E.4.2 svdpi_src.h include file
E.4 Include files

This is an auxiliary include file. svdpi_src.h defines data structures for implementation-specific representation of 2-state and 4-state SystemVerilog packed arrays. The interface specifies the contents of this file, i.e., what symbols are defined. The actual definitions of those symbols, however, are implementation-specific and shall be provided by vendors.

Applications that require the svdpi_src.h file are only source-level compatible, i.e., they need to be compiled with the version of svdpi_src.h provided for a particular implementation of SystemVerilog. If, however, an application makes use of the details of the implementation-specific representation of packed arrays and thus it requires vendor specific include files, then such an application is not source-level compatible.

Group

E.4 Include files

链接
E.4 Include files


E.5 Semantic constraints

链接
附录E DPI C-layer, 主题
SystemVerilog 3.1a语言参考手册
E.5 Semantic constraints
附录E DPI C-layer | 主题

Formal and actual arguments of both imported tasks or functions and exported tasks or functions are bound by the principle “What You Specify Is What You Get.” This principle is binding both for the caller and for the callee, in C code and in SystemVerilog code. For the callee, it guarantees the actual arguments are as specified for the formal ones. For the caller, it means the function call arguments shall conform with the types of the formal arguments, which might require type-coercion on the caller side.

Another way to state this is that no compiler (either C or SystemVerilog) can make argument coercions between a caller’s declared formals and the callee’s declared the formals. This is because the callee’s formal arguments are declared in a different language than the caller’s formal arguments; hence there is no visible relationship between the two sets of formals. Users are expected to understand all argument relationships and provide properly matched types on both sides of the interface (see Annex E.6.2).

In SystemVerilog code, the compiler can change the formal arguments of a native SystemVerilog task or function and modify its code accordingly, because of optimizations, compiler pragmas, or command line switches. The situation is different for imported tasks and functions. A SystemVerilog compiler cannot modify the C code, perform any coercions, or make any changes whatsoever to the formal arguments of an imported task or function.

A SystemVerilog compiler shall provide any necessary coercions for the actual arguments of every imported task and function call. For example, a SystemVerilog compiler might truncate or extend bits of a packed array if the widths of the actual and formal arguments are different. Similarly, a C compiler can provide coercion for C types based on the relationship of the arguments in the exported task’s and function’s C prototype (formals) and the exported task’s and function’s C call site (actuals). However, a C compiler cannot provide such coercion for SystemVerilog types.

Thus, in each case of an inter-language function call, either C to SystemVerilog or SystemVerilog to C, the compilers expect but cannot enforce that the types on either side are compatible. It is therefore the user’s responsibility to ensure that the imported/exported function types exactly match the types of the corresponding tasks or functions in the foreign language.

Group

附录E DPI C-layer

主题
主题 | 描述
E.5.1 Types of formal arguments | The principle “What You Specify Is What You Get” guarantees the types of formal arguments of imported functions — an actual argument is guaranteed to be of the type specified for the formal argument, with the exception of open arrays (for which unspecified ranges are statically unknown). Formal arguments, other than open arrays, are fully defined by imported declaration; they shall have ranges of packed or unpacked arrays exactly as specified in the imported declaration. Only the SystemVerilog declaration site of the imported function is relevant for such formal arguments. Formal arguments defined as open arrays have the size and... more
E.5.2 input arguments | Formal arguments specified in SystemVerilog as input must not be modified by the foreign language code. See also Section 27.4.1.2.
E.5.3 output arguments | The initial values of formal arguments specified in SystemVerilog as output are undetermined and implementation-dependent. See also Section 27.4.1.2.
E.5.4 Value changes for output and inout arguments | The SystemVerilog simulator is responsible for handling value changes for output and inout arguments. Such changes shall be detected and handled after the control returns from C code to SystemVerilog code.
E.5.5 context and non-context tasks and functions | Also refer to Section 27.4.3. Some DPI imported tasks or functions or other interface functions called from them require that the context of their call be known. It takes special instrumentation of their call instances to provide such context; for example, a variable referring to the “current instance” might need to be set. To avoid any unnecessary overhead, imported tasks and function calls in SystemVerilog code are not instrumented unless the imported tasks or function is specified as context in its SystemVerilog import declaration. All DPI export tasks and functions require that the context of their call is known. This... more
E.5.6 pure functions | See also Section 27.4.2. Only non-void functions with no output or inout arguments can be specified as pure. Functions specified as pure in their corresponding SystemVerilog import declarations shall have no side effects; their results need to depend solely on the values of their input arguments. Calls to such functions can be removed by SystemVerilog compiler optimizations or replaced with the values previously computed for the same values of the input arguments. Specifically, a pure function is assumed not to directly or indirectly (i.e., by calling other functions): — perform any file operations — read or write anything in the... more
E.5.7 Memory management | See also Section 27.4.1.4. The memory spaces owned and allocated by C code and SystemVerilog code are disjoined. Each side is responsible for its own allocated memory. Specifically, C code shall not free the memory allocated by SystemVerilog code (or the SystemVerilog compiler) nor expect SystemVerilog code to free the memory allocated by C code (or the C compiler). This does not exclude scenarios in which C code allocates a block of memory, then passes a handle (i.e., a pointer) to that block to SystemVerilog code, which in turn calls a C function that directly (if it is the standard... more
链接
附录E DPI C-layer, 主题


E.5.1 Types of formal arguments

链接
E.5 Semantic constraints
SystemVerilog 3.1a语言参考手册
E.5.1 Types of formal arguments
E.5 Semantic constraints

The principle “What You Specify Is What You Get” guarantees the types of formal arguments of imported functions — an actual argument is guaranteed to be of the type specified for the formal argument, with the exception of open arrays (for which unspecified ranges are statically unknown). Formal arguments, other than open arrays, are fully defined by imported declaration; they shall have ranges of packed or unpacked arrays exactly as specified in the imported declaration. Only the SystemVerilog declaration site of the imported function is relevant for such formal arguments.

Formal arguments defined as open arrays have the size and ranges of the actual argument, i.e., have the ranges of packed or unpacked arrays exactly as that of the actual argument. The unsized ranges of open arrays are determined at a call site; the rest of the type information is specified at the import declaration. See also Annex E.6.1.

So, if a formal argument is declared as bit [15:8] b [], then it is the import declaration which specifies the formal argument is an unpacked array of packed bit array with bounds 15 to 8, while the actual argument used at a particular call site defines the bounds for the unpacked part for that call.

Group

E.5 Semantic constraints

链接
E.5 Semantic constraints


E.5.2 input arguments

链接
E.5 Semantic constraints
SystemVerilog 3.1a语言参考手册
E.5.2 input arguments
E.5 Semantic constraints

Formal arguments specified in SystemVerilog as input must not be modified by the foreign language code. See also Section 27.4.1.2.

Group

E.5 Semantic constraints

链接
E.5 Semantic constraints


E.5.3 output arguments

链接
E.5 Semantic constraints
SystemVerilog 3.1a语言参考手册
E.5.3 output arguments
E.5 Semantic constraints

The initial values of formal arguments specified in SystemVerilog as output are undetermined and implementation-dependent. See also Section 27.4.1.2.

Group

E.5 Semantic constraints

链接
E.5 Semantic constraints


E.5.4 Value changes for output and inout arguments

链接
E.5 Semantic constraints
SystemVerilog 3.1a语言参考手册
E.5.4 Value changes for output and inout arguments
E.5 Semantic constraints

The SystemVerilog simulator is responsible for handling value changes for output and inout arguments. Such changes shall be detected and handled after the control returns from C code to SystemVerilog code.

Group

E.5 Semantic constraints

链接
E.5 Semantic constraints


E.5.5 context and non-context tasks and functions

链接
E.5 Semantic constraints
SystemVerilog 3.1a语言参考手册
E.5.5 context and non-context tasks and functions
E.5 Semantic constraints

Also refer to Section 27.4.3.

Some DPI imported tasks or functions or other interface functions called from them require that the context of their call be known. It takes special instrumentation of their call instances to provide such context; for example, a variable referring to the “current instance” might need to be set. To avoid any unnecessary overhead, imported tasks and function calls in SystemVerilog code are not instrumented unless the imported tasks or function is specified as context in its SystemVerilog import declaration.

All DPI export tasks and functions require that the context of their call is known. This occurs since SystemVerilog task and function declarations always occur in instantiable scopes, hence allowing a multiplicity of unique task and function instances in the simulator’s elaborated database. Thus, there is no such thing as a non-context export task or function.

For the sake of simulation performance, a non-context imported task or function call shall not block System- Verilog compiler optimizations. An imported task or function not specified as context shall not access any data objects from SystemVerilog other then its actual arguments. Only the actual arguments can be affected (read or written) by its call. Therefore, a call of non-context imported task or function is not a barrier for optimizations. A context imported task or function, however, can access (read or write) any SystemVerilog data objects by calling PLI/VPI, nor by calling an embedded export task or function. Therefore, a call to a context task or function is a barrier for SystemVerilog compiler optimizations.

Only the calls of context imported tasks and functions are properly instrumented and cause conservative optimizations; therefore, only those tasks and functions can safely call all functions from other APIs, including PLI and VPI functions or exported SystemVerilog functions. For imported task or functions not specified as context, the effects of calling PLI, VPI, or SystemVerilog functions can be unpredictable and such calls can crash if the callee requires a context that has not been properly set.

Special DPI utility functions exist that allow imported task and functions to retrieve and operate on their context. For example, the C implementation of an imported task or function can use svGetScope() to retrieve an svScope corresponding to the instance scope of its corresponding SystemVerilog import declaration. See Annex E.8 for more details.

Group

E.5 Semantic constraints

链接
E.5 Semantic constraints


E.5.6 pure functions

链接
E.5 Semantic constraints
SystemVerilog 3.1a语言参考手册
E.5.6 pure functions
E.5 Semantic constraints

See also Section 27.4.2.

Only non-void functions with no output or inout arguments can be specified as pure. Functions specified as pure in their corresponding SystemVerilog import declarations shall have no side effects; their results need to depend solely on the values of their input arguments. Calls to such functions can be removed by SystemVerilog compiler optimizations or replaced with the values previously computed for the same values of the input arguments.

Specifically, a pure function is assumed not to directly or indirectly (i.e., by calling other functions):

— perform any file operations

— read or write anything in the broadest possible meaning, includes i/o, environment variables, objects from the operating system or from the program or other processes, shared memory, sockets, etc.

— access any persistent data, like global or static variables.

If a pure function does not obey the above restrictions, SystemVerilog compiler optimizations can lead to unexpected behavior, due to eliminated calls or incorrect results being used.

Group

E.5 Semantic constraints

链接
E.5 Semantic constraints


E.5.7 Memory management

链接
E.5 Semantic constraints
SystemVerilog 3.1a语言参考手册
E.5.7 Memory management
E.5 Semantic constraints

See also Section 27.4.1.4.

The memory spaces owned and allocated by C code and SystemVerilog code are disjoined. Each side is responsible for its own allocated memory. Specifically, C code shall not free the memory allocated by SystemVerilog code (or the SystemVerilog compiler) nor expect SystemVerilog code to free the memory allocated by C code (or the C compiler). This does not exclude scenarios in which C code allocates a block of memory, then passes a handle (i.e., a pointer) to that block to SystemVerilog code, which in turn calls a C function that directly (if it is the standard function free) or indirectly frees that block.

NOTE—In this last scenario, a block of memory is allocated and freed in C code, even when the standard functions malloc and free are called directly from SystemVerilog code.

Group

E.5 Semantic constraints

链接
E.5 Semantic constraints


E.6 Data types

链接
附录E DPI C-layer, 主题
SystemVerilog 3.1a语言参考手册
E.6 Data types
附录E DPI C-layer | 主题

This section defines the data types of the C-layer of the Direct Programming Interface.

Group

附录E DPI C-layer

主题
主题
描述
E.6.1 Limitations
Packed arrays can have an arbitrary number of dimensions; though they are eventually always equivalent to a one-dimensional packed array and treated as such. If the packed part of an array in the type of a formal argument in SystemVerilog is specified as multi-dimensional, the SystemVerilog compiler linearizes it. Although the original ranges are generally preserved for open arrays, if the actual argument has a multidimensional packed part of the array, it shall be normalized into an equivalent one-dimensional packed array.

NOTE—The actual argument can have both packed and unpacked parts of an array; either can be multidimensional.
E.6.2 Duality of types: SystemVerilog types vs. C types
A value that crosses the Direct Programming Interface is specified in SystemVerilog code as a value of SystemVerilog type, while the same value shall be specified in C code as a value of C type. Therefore, each data type that is passed through the Direct Programming Interface requires two matching type definitions: the SystemVerilog definition and C definition.

The user needs to provide such matching definitions. Specifically, for each SystemVerilog type used in the import declarations or export declarations in SystemVerilog code, the user shall provide the equivalent type definition in C reflecting the argument passing mode for the particular... more
E.6.3 Data representation
DPI imposes the following additional restrictions on the representation of SystemVerilog data types.
  • SystemVerilog types that are not packed and that do not contained packed elements have C compatible representation.
  • Basic integer and real data types are represented as defined in Annex E.6.4.
  • Enumeration types are represented as the types associated with them. Enumerated names are not available on C side of interface.
  • Representation of packed types is implementation-dependent.
  • Unpacked arrays embedded in a structure have C compatible layout regardless of the type of elements. Similarly, standalone arrays passed as actuals to a sized formal argument have C compatible representation.... more
E.6.4 Basic types
Table E-1 defines the mapping between the basic SystemVerilog data types and the corresponding C types.

Table E-1: Mapping data types

?Encodings for bit and logic are given in file svdpi.h. Refer to Annex E.9.1.1.

The DPI interface also supports the SystemVerilog and C unsigned integer data types that correspond to the mappings Table E-1 shows for their signed equivalents.

Note that input mode arguments of type byte unsigned and shortint unsigned are not equivalent to bit[7:0] or bit[15:0], respectively, since the former are passed as C types unsigned char and unsigned short and the latter are passed as C... more

E.6.5 Normalized ranges
Packed arrays are treated as one-dimensional; the unpacked part of an array can have an arbitrary number of dimensions. Normalized ranges mean [n-1:0] indexing for the packed part and [0:n-1] indexing for a dimension of the unpacked part of an array. Normalized ranges are used for accessing all arguments but open arrays. The canonical representation of packed arrays also uses normalized ranges.
E.6.6 Mapping between SystemVerilog ranges and normalized ranges
The SystemVerilog ranges for a formal argument specified as an open array are those of the actual argument for a particular call. Open arrays are accessible, however, by using their original ranges and the same indexing as in the SystemVerilog code.

For all other types of arguments, i.e., all arguments but open arrays, the SystemVerilog ranges are defined in the corresponding SystemVerilog import or export declaration. Normalized ranges are used for accessing such arguments in C code. The mapping between SystemVerilog ranges and normalized ranges is defined as follows.
  1. If a packed part of an array has more than one... more
E.6.7 Canonical representation of packed arrays
The Direct Programming Interface defines the canonical representation of packed 2-state (type svBitVec32) and 4-state arrays (type svLogicVec32). This canonical representation is derived from on the Verilog legacy PLI’s avalue/bvalue representation of 4-state vectors. Library functions provide the translation between the representation used in a simulator and the canonical representation of packed arrays.

A packed array is represented as an array of one or more elements (of type svBitVec32 for 2-state values and svLogicVec32 for 4-state values), each element representing a group of 32 bits.The first element of an array contains the 32 least-significant bits, next element contains the 32... more
链接
附录E DPI C-layer, 主题


E.6.1 Limitations

链接
E.6 Data types
SystemVerilog 3.1a语言参考手册
E.6.1 Limitations
E.6 Data types

Packed arrays can have an arbitrary number of dimensions; though they are eventually always equivalent to a one-dimensional packed array and treated as such. If the packed part of an array in the type of a formal argument in SystemVerilog is specified as multi-dimensional, the SystemVerilog compiler linearizes it. Although the original ranges are generally preserved for open arrays, if the actual argument has a multidimensional packed part of the array, it shall be normalized into an equivalent one-dimensional packed array.

NOTE—The actual argument can have both packed and unpacked parts of an array; either can be multidimensional.

Group

E.6 Data types

链接
E.6 Data types


E.6.2 Duality of types: SystemVerilog types vs. C types

链接
E.6 Data types
SystemVerilog 3.1a语言参考手册
E.6.2 Duality of types: SystemVerilog types vs. C types
E.6 Data types

A value that crosses the Direct Programming Interface is specified in SystemVerilog code as a value of SystemVerilog type, while the same value shall be specified in C code as a value of C type. Therefore, each data type that is passed through the Direct Programming Interface requires two matching type definitions: the SystemVerilog definition and C definition.

The user needs to provide such matching definitions. Specifically, for each SystemVerilog type used in the import declarations or export declarations in SystemVerilog code, the user shall provide the equivalent type definition in C reflecting the argument passing mode for the particular type of SystemVerilog value and the direction (input, output, or inout) of the formal SystemVerilog argument. For values passed by reference, a generic pointer void * can be used (conveniently typedefed in svdpi.h or svdpi_src.h) without knowing the actual representation of the value.

Group

E.6 Data types

链接
E.6 Data types


E.6.3 Data representation

链接
E.6 Data types
SystemVerilog 3.1a语言参考手册
E.6.3 Data representation
E.6 Data types

DPI imposes the following additional restrictions on the representation of SystemVerilog data types.

  • SystemVerilog types that are not packed and that do not contained packed elements have C compatible representation.
  • Basic integer and real data types are represented as defined in Annex E.6.4.
  • Enumeration types are represented as the types associated with them. Enumerated names are not available on C side of interface.
  • Representation of packed types is implementation-dependent.
  • Unpacked arrays embedded in a structure have C compatible layout regardless of the type of elements. Similarly, standalone arrays passed as actuals to a sized formal argument have C compatible representation.
  • Standalone array passed as an actual to an open array formal
  • if the element type is scalar or packed then the representation is implementation dependent
  • otherwise the representation is C compatible. Therefore an element of an array shall have the same representation as an individual value of the same type. Hence, an array’s elements can be accessed from C code via normal C array indexing similarly to doing so for individual values.
  • The natural order of elements for each dimension in the layout of an unpacked array shall be used, i.e., elements with lower indices go first. For SystemVerilog range [L:R], the element with SystemVerilog index min(L,R) has the C index 0 and the element with SystemVerilog index max(L,R) has the C index abs(L-R).
NOTE—This does not actually impose any restrictions on how unpacked arrays are implemented; it only says an array that does not satisfy this condition shall not be passed as an actual argument for a formal argument which is a sized array; it can be passed, however, for a formal argument which is an unsized (i.e., open) array. Therefore, the correctness of an actual argument might be implementation-dependent. Nevertheless, an open array provides an implementation-independent solution; this seems to be a reasonable trade-off.

Group

E.6 Data types

链接
E.6 Data types


E.6.4 Basic types

链接
E.6 Data types
SystemVerilog 3.1a语言参考手册
E.6.4 Basic types
E.6 Data types

Table E-1 defines the mapping between the basic SystemVerilog data types and the corresponding C types.

Table E-1: Mapping data types

?Encodings for bit and logic are given in file svdpi.h. Refer to Annex E.9.1.1.

The DPI interface also supports the SystemVerilog and C unsigned integer data types that correspond to the mappings Table E-1 shows for their signed equivalents.

Note that input mode arguments of type byte unsigned and shortint unsigned are not equivalent to bit[7:0] or bit[15:0], respectively, since the former are passed as C types unsigned char and unsigned short and the latter are passed as C unsigned int (i.e., svBitVec32). A similar lack of equivalence applies to passing such parameters by reference for output and inout modes.

The representation of SystemVerilog-specific data types like packed bit and logic arrays is implementation-dependent and generally transparent to the user. Nevertheless, for the sake of performance, applications can be tuned for a specific implementation and make use of the actual representation used by that implementation; such applications shall not be binary compatible, however.

Group

E.6 Data types

链接
E.6 Data types


E.6.5 Normalized ranges

链接
E.6 Data types
SystemVerilog 3.1a语言参考手册
E.6.5 Normalized ranges
E.6 Data types

Packed arrays are treated as one-dimensional; the unpacked part of an array can have an arbitrary number of dimensions. Normalized ranges mean [n-1:0] indexing for the packed part and [0:n-1] indexing for a dimension of the unpacked part of an array. Normalized ranges are used for accessing all arguments but open arrays. The canonical representation of packed arrays also uses normalized ranges.

Group

E.6 Data types

链接
E.6 Data types


E.6.6 Mapping between SystemVerilog ranges and normalized ranges

链接
E.6 Data types
SystemVerilog 3.1a语言参考手册
E.6.6 Mapping between SystemVerilog ranges and normalized ranges
E.6 Data types

The SystemVerilog ranges for a formal argument specified as an open array are those of the actual argument for a particular call. Open arrays are accessible, however, by using their original ranges and the same indexing as in the SystemVerilog code.

For all other types of arguments, i.e., all arguments but open arrays, the SystemVerilog ranges are defined in the corresponding SystemVerilog import or export declaration. Normalized ranges are used for accessing such arguments in C code. The mapping between SystemVerilog ranges and normalized ranges is defined as follows.

  1. If a packed part of an array has more than one dimension, it is linearized as specified by the equivalence of packed types (see Section 4.2).
  2. A packed array of range [L:R] is normalized as [abs(L-R):0]; its most significant bit has a normalized index abs(L-R) and its least significant bit has a normalized index 0.
  3. The natural order of elements for each dimension in the layout of an unpacked array shall be used, i.e., elements with lower indices go first. For SystemVerilog range [L:R], the element with SystemVerilog index min(L,R) has the C index 0 and the element with SystemVerilog index max(L,R) has the C index abs(L-R).
NOTE—The above range mapping from SystemVerilog to C applies to calls made in both directions, i.e., SystemVerilogcalls to C and C-calls to SystemVerilog.

For example, if logic [2:3][1:3][2:0] b [1:10] [31:0] is used in SystemVerilog, it needs to be defined in C as if it were declared in SystemVerilog in the following normalized form: logic [17:0] b[0:9] [0:31].

Group

E.6 Data types

链接
E.6 Data types


E.6.7 Canonical representation of packed arrays

链接
E.6 Data types
SystemVerilog 3.1a语言参考手册
E.6.7 Canonical representation of packed arrays
E.6 Data types

The Direct Programming Interface defines the canonical representation of packed 2-state (type svBitVec32) and 4-state arrays (type svLogicVec32). This canonical representation is derived from on the Verilog legacy PLI’s avalue/bvalue representation of 4-state vectors. Library functions provide the translation between the representation used in a simulator and the canonical representation of packed arrays.

A packed array is represented as an array of one or more elements (of type svBitVec32 for 2-state values and svLogicVec32 for 4-state values), each element representing a group of 32 bits.The first element of an array contains the 32 least-significant bits, next element contains the 32 more-significant bits, and so on. The last element can contain a number of unused bits. The contents of these unused bits is undetermined and the user is responsible for the masking or the sign extension (depending on the sign) for the unused bits.

Table E-2 defines the encoding used for a packed logic array represented as svLogicVec32.

Table E-2: Encoding of bits in svLogicVec32

Group

E.6 Data types

链接
E.6 Data types


E.7 Argument passing modes

链接
附录E DPI C-layer, 主题
SystemVerilog 3.1a语言参考手册
E.7 Argument passing modes
附录E DPI C-layer | 主题

This section defines the ways to pass arguments in the C-layer of the Direct Programming Interface.

Group

附录E DPI C-layer

主题
主题
描述
E.7.1 Overview
Imported and exported function arguments are generally passed by some form of a reference, with the exception of small values of SystemVerilog input arguments (see Annex E.11.7), which are passed by value. Similarly, the function result, which is restricted to small values, is passed by value, i.e., directly returned.

Actual arguments passed by reference typically are passed without changing their representation from the one used by a simulator. There is no inherent copying of arguments (other than any copying resulting from coercing).

Access to packed arrays via canonical representation involves copying arguments and does incur some overhead, however. Alternatively, for... more
E.7.2 Calling SystemVerilog tasks and functions from C
There is no difference in argument passing between calls from SystemVerilog to C and calls from C to System- Verilog. Tasks and functions exported from SystemVerilog cannot have open arrays as arguments. Apart from this restriction, the same types of formal arguments can be declared in SystemVerilog for exported tasks and functions and imported tasks and functions. A task or function exported from SystemVerilog shall have the same function header in C as would an imported function with the same function result type and same formal argument list. In the case of arguments passed by reference, an actual argument to... more
E.7.3 Argument passing by value
Only small values of formal input arguments (see Annex E.11.7) are passed by value. Function results are also directly passed by value. The user needs to provide the C-type equivalent to the SystemVerilog type of a formal argument if an argument is passed by value.
E.7.4 Argument passing by reference
For arguments passed by reference, their original simulator-defined representation shall be used and a reference (a pointer) to the actual data object is passed. The actual argument is usually allocated by a caller. The caller can also pass a reference to an object already allocated somewhere else, for example, its own formal argument passed by reference.

If an argument of type T is passed by reference, the formal argument shall be of type T*. However, packed arrays can also be passed using generic pointers void* (typedefed accordingly to svBitPackedArrRef or svLogicPackedArrRef).
E.7.5 Allocating actual arguments for SystemVerilog-specific types
This is relevant only for calling exported SystemVerilog functions from C code. The caller is responsible for allocating any actual arguments that are passed by reference.

Static allocation requires knowledge of the relevant data type. If such a type involves SystemVerilog packed arrays, their actual representation needs to be known to C code; thus, the file svdpi_src.h needs to be included, which makes the C code implementation-dependent and not binary compatible.

Sometimes binary compatibility can be achieved by using dynamic allocation functions. The functions svSizeOfLogicPackedArr() and svSizeOfBitPackedArr() provide the size of the actual representation of a packed array, which can... more
E.7.6 Argument passing by handle—open arrays
Arguments specified as open (unsized) arrays are always passed by a handle, regardless of direction of the SystemVerilog formal argument, and are accessible via library functions. The actual implementation of a handle is simulator-specific and transparent to the user. A handle is represented by the generic pointer void * (typedefed to svOpenArrayHandle). Arguments passed by handle shall always have a const qualifier, because the user shall not modify the contents of a handle.
E.7.7 input arguments
input arguments of imported functions implemented in C shall always have a const qualifier.

input arguments, with the exception of open arrays, are passed by value or by reference, depending on the size. ‘Small’ values of formal input arguments are passed by value. The following data types are considered small:
  • byte, shortint, int, longint, real, shortreal
  • chandle, string
  • bit (i.e., 2-state) packed arrays up to 32 bits (canonical representation shall be used, like for a function result; thus a small packed bit array shall be represented as const svBitVec32) input arguments of other types are passed by reference.
If an... more
E.7.8 inout and output arguments
inout and output arguments, with the exception of open arrays, are always passed by reference. Specifically, packed arrays are passed, accordingly, as svBitPackedArrRef or svLogicPackedArrRef. The same rules about unused bits apply as in Annex E.11.7.
E.7.9 Function result
Types of a function result are restricted to the following SystemVerilog data types (see Table E-1 for the corresponding C type):
  • byte, shortint, int, longint, real, shortreal, chandle, string
  • packed bit arrays up to 32 bits
  • scalar values of type bit and logic
Encodings for bit and logic are given in file svdpi.h. Refer to Annex E.9.1.1.

If the function result type is a packed bit array, the returned value shall be represented using the canonical representation svBitVec32. If a packed bit array is smaller than 32 bits, the most significant bits are unused and their contents are undetermined.
链接
附录E DPI C-layer, 主题


E.7.1 Overview

链接
E.7 Argument passing modes
SystemVerilog 3.1a语言参考手册
E.7.1 Overview
E.7 Argument passing modes

Imported and exported function arguments are generally passed by some form of a reference, with the exception of small values of SystemVerilog input arguments (see Annex E.11.7), which are passed by value. Similarly, the function result, which is restricted to small values, is passed by value, i.e., directly returned.

Actual arguments passed by reference typically are passed without changing their representation from the one used by a simulator. There is no inherent copying of arguments (other than any copying resulting from coercing).

Access to packed arrays via canonical representation involves copying arguments and does incur some overhead, however. Alternatively, for the sake of performance the application can be tuned for a particular tool and access the packed arrays directly through pointers using implementation representation, which could compromise binary and/or source compatibility. Data can be, however, moved around (copied, stored, retrieved) without using canonical representation while preserving binary or source level compatibility at the same time. This is possible by using pointers and size of data and when the detailed knowledge of the data representation is not required.

NOTE—This provides some degree of flexibility and allows the user to control the trade-off of performance vs. portability.

Formal arguments, except open arrays, are passed by direct reference or value, and, therefore, are directly accessible in C code. Formal arguments declared in SystemVerilog as open arrays are passed by a handle (type svOpenArrayHandle) and are accessible via library functions.

Group

E.7 Argument passing modes

链接
E.7 Argument passing modes


E.7.2 Calling SystemVerilog tasks and functions from C

链接
E.7 Argument passing modes
SystemVerilog 3.1a语言参考手册
E.7.2 Calling SystemVerilog tasks and functions from C
E.7 Argument passing modes

There is no difference in argument passing between calls from SystemVerilog to C and calls from C to System- Verilog. Tasks and functions exported from SystemVerilog cannot have open arrays as arguments. Apart from this restriction, the same types of formal arguments can be declared in SystemVerilog for exported tasks and functions and imported tasks and functions. A task or function exported from SystemVerilog shall have the same function header in C as would an imported function with the same function result type and same formal argument list. In the case of arguments passed by reference, an actual argument to SystemVerilog task and function called from C shall be allocated using the same layout of data as SystemVerilog uses for that type of argument; the caller is responsible for the allocation. It can be done while preserving the binary compatibility, see Annex E.11.5 and Annex E.11.11.

Calling a SystemVerilog task from C is the same as calling a SystemVerilog function from C with the exception that the return type of an exported task is an int value which has a special meaning related to disable statements. Please see Section 27.8 for details on disable processing by DPI imported tasks and functions.

Group

E.7 Argument passing modes

链接
E.7 Argument passing modes


E.7.3 Argument passing by value

链接
E.7 Argument passing modes
SystemVerilog 3.1a语言参考手册
E.7.3 Argument passing by value
E.7 Argument passing modes

Only small values of formal input arguments (see Annex E.11.7) are passed by value. Function results are also directly passed by value. The user needs to provide the C-type equivalent to the SystemVerilog type of a formal argument if an argument is passed by value.

Group

E.7 Argument passing modes

链接
E.7 Argument passing modes


E.7.4 Argument passing by reference

链接
E.7 Argument passing modes
SystemVerilog 3.1a语言参考手册
E.7.4 Argument passing by reference
E.7 Argument passing modes

For arguments passed by reference, their original simulator-defined representation shall be used and a reference (a pointer) to the actual data object is passed. The actual argument is usually allocated by a caller. The caller can also pass a reference to an object already allocated somewhere else, for example, its own formal argument passed by reference.

If an argument of type T is passed by reference, the formal argument shall be of type T*. However, packed arrays can also be passed using generic pointers void* (typedefed accordingly to svBitPackedArrRef or svLogicPackedArrRef).

Group

E.7 Argument passing modes

链接
E.7 Argument passing modes


E.7.5 Allocating actual arguments for SystemVerilog-specific types

链接
E.7 Argument passing modes
SystemVerilog 3.1a语言参考手册
E.7.5 Allocating actual arguments for SystemVerilog-specific types
E.7 Argument passing modes

This is relevant only for calling exported SystemVerilog functions from C code. The caller is responsible for allocating any actual arguments that are passed by reference.

Static allocation requires knowledge of the relevant data type. If such a type involves SystemVerilog packed arrays, their actual representation needs to be known to C code; thus, the file svdpi_src.h needs to be included, which makes the C code implementation-dependent and not binary compatible.

Sometimes binary compatibility can be achieved by using dynamic allocation functions. The functions svSizeOfLogicPackedArr() and svSizeOfBitPackedArr() provide the size of the actual representation of a packed array, which can be used for the dynamic allocation of an actual argument without compromising the portability (see Annex E.11.11). Such a technique does not work if a packed array is a part of another type.

Group

E.7 Argument passing modes

链接
E.7 Argument passing modes


E.7.6 Argument passing by handle—open arrays

链接
E.7 Argument passing modes
SystemVerilog 3.1a语言参考手册
E.7.6 Argument passing by handle—open arrays
E.7 Argument passing modes

Arguments specified as open (unsized) arrays are always passed by a handle, regardless of direction of the SystemVerilog formal argument, and are accessible via library functions. The actual implementation of a handle is simulator-specific and transparent to the user. A handle is represented by the generic pointer void * (typedefed to svOpenArrayHandle). Arguments passed by handle shall always have a const qualifier, because the user shall not modify the contents of a handle.

Group

E.7 Argument passing modes

链接
E.7 Argument passing modes


E.7.7 input arguments

链接
E.7 Argument passing modes
SystemVerilog 3.1a语言参考手册
E.7.7 input arguments
E.7 Argument passing modes

input arguments of imported functions implemented in C shall always have a const qualifier.

input arguments, with the exception of open arrays, are passed by value or by reference, depending on the size. ‘Small’ values of formal input arguments are passed by value. The following data types are considered small:

  • byte, shortint, int, longint, real, shortreal
  • chandle, string
  • bit (i.e., 2-state) packed arrays up to 32 bits (canonical representation shall be used, like for a function result; thus a small packed bit array shall be represented as const svBitVec32) input arguments of other types are passed by reference.
If an input argument is a packed bit array passed by value, its value shall be represented using the canonical representation svBitVec32. If the size is smaller than 32 bits, the most significant bits are unused and their contents are undetermined. The user is responsible for the masking or the sign extension, depending on the sign, for the unused bits.

Group

E.7 Argument passing modes

链接
E.7 Argument passing modes


E.7.8 inout and output arguments

链接
E.7 Argument passing modes
SystemVerilog 3.1a语言参考手册
E.7.8 inout and output arguments
E.7 Argument passing modes

inout and output arguments, with the exception of open arrays, are always passed by reference. Specifically, packed arrays are passed, accordingly, as svBitPackedArrRef or svLogicPackedArrRef. The same rules about unused bits apply as in Annex E.11.7.

Group

E.7 Argument passing modes

链接
E.7 Argument passing modes


E.7.9 Function result

链接
E.7 Argument passing modes
SystemVerilog 3.1a语言参考手册
E.7.9 Function result
E.7 Argument passing modes

Types of a function result are restricted to the following SystemVerilog data types (see Table E-1 for the corresponding C type):

  • byte, shortint, int, longint, real, shortreal, chandle, string
  • packed bit arrays up to 32 bits
  • scalar values of type bit and logic
Encodings for bit and logic are given in file svdpi.h. Refer to Annex E.9.1.1.

If the function result type is a packed bit array, the returned value shall be represented using the canonical representation svBitVec32. If a packed bit array is smaller than 32 bits, the most significant bits are unused and their contents are undetermined.

Group

E.7 Argument passing modes

链接
E.7 Argument passing modes


E.8 Context tasks and functions

链接
附录E DPI C-layer, 主题
SystemVerilog 3.1a语言参考手册
E.8 Context tasks and functions
附录E DPI C-layer | 主题

Some DPI imported tasks and functions require that the context of their call is known. For example, those calls can be associated with instances of C models that have a one-to-one correspondence with instances of SystemVerilog modules that are making the calls. Alternatively, a DPI imported task or function might need to access or modify simulator data structures using PLI or VPI calls, or by making a call back into SystemVerilog via an export task or function. Context knowledge is required for such calls to function properly. It can take special instrumentation of their call to provide such context.

To avoid any unnecessary overhead, imported task and function calls in SystemVerilog code are not instrumented unless the imported task or function is specified as context in its SystemVerilog import declaration. A small set of DPI utility functions are available to assist programmers when working with context tasks or functions (see Annex E.8.3). If those utility functions are used with any non-context function, a system error shall result.

Group

附录E DPI C-layer

主题
主题 | 描述
E.8.1 Overview of DPI and VPI context | Both DPI task and functions and VPI/PLI functions might need to understand their context. However, the meaning of the term is different for the two categories of task and functions. DPI imported tasks and functions are essentially proxies for native SystemVerilog tasks and functions. Native SystemVerilog tasks and functions always operate in the scope of their declaration site. For example, a native SystemVerilog function f() can be declared in a module m which is instantiated as top.i1_m. The top.i1_m instance of f() can be called via hierarchical reference from code in a distant design region. Function f() is said to... more
E.8.2 Context of imported and export tasks and functions | DPI imported and export tasks and functions can be declared anywhere a normal SystemVerilog task or function can be declared. Specifically, this means that they can be declared in module, program, interface, or generate declarative scope. A context imported task or function executes in the context of the instantiated scope surrounding its declaration. This means that such tasks and functions can see other variables in that scope without qualification. As explained in Annex E.8.1, this should not be confused with the context of the task’s or function’s call site, which can actually be anywhere in the SystemVerilog design hierarchy. The... more
E.8.3 Working with DPI context tasks and functions in C code | DPI defines a small set of functions to help programmers work with DPI context tasks and functions. The term scope is used in the task or function names for consistency with other SystemVerilog terminology. The terms scope and context are equivalent for DPI tasks and functions. There are functions that allow the user to retrieve and manipulate the current operational scope. It is an error to use these functions with any C code that is not executing under a call to a DPI context imported task or function. There are also functions that provide users with the power to set... more
E.8.4 Example 1 — Using DPI context functions | SV Side:
E.8.5 Relationship between DPI and VPI/PLI interfaces | DPI allows C code to run in the context of a SystemVerilog simulation, thus it is natural for users to consider using VPI/PLI C code from within imported tasks and functions. There is no specific relationship defined between DPI and the existing Verilog programming interfaces (VPI and PLI). Programmers must make no assumptions about how DPI and the other interfaces interact. In particular, note that a vpiHandle is not equivalent to an svOpenArrayHandle, and the two must not be interchanged and passed between functions defined in two different interface standards. If a user wants to call VPI or PLI functions... more
链接
附录E DPI C-layer, 主题


E.8.1 Overview of DPI and VPI context

链接
E.8 Context tasks and functions
SystemVerilog 3.1a语言参考手册
E.8.1 Overview of DPI and VPI context
E.8 Context tasks and functions

Both DPI task and functions and VPI/PLI functions might need to understand their context. However, the meaning of the term is different for the two categories of task and functions.

DPI imported tasks and functions are essentially proxies for native SystemVerilog tasks and functions. Native SystemVerilog tasks and functions always operate in the scope of their declaration site. For example, a native SystemVerilog function f() can be declared in a module m which is instantiated as top.i1_m. The top.i1_m instance of f() can be called via hierarchical reference from code in a distant design region. Function f() is said to execute in the context (aka. instantiated scope) of top.i1_m, since it has unqualified visibility only for variables local to that specific instance of m. Function f() does not have unqualified visibility for any variables in the calling code’s scope.

DPI imported tasks and functions follow the same model as native SystemVerilog tasks and functions. They execute in the context of their surrounding declarative scope, rather than the context of their call sites. This type of context is termed DPI context.

This is in contrast to VPI and PLI functions. Such functions execute in a context associated with their call sites. The VPI/PLI programming model relies on C code’s ability to retrieve a context handle associated with the associated system task’s call site, and then work with the context handle to glean information about arguments, items in the call site’s surrounding declarative scope, etc. This type of context is termed VPI context.

Note that all DPI export tasks and functions require that the context of their call is known. This occurs since SystemVerilog task and function declarations always occur in instantiable scopes, hence giving rise to a multiplicity of associated task or function instances in the simulator’s database. Thus, there is no such thing as a non-context export tasks or function. All export task and function calls must have their execution scope specified in advance by use of a context-setting API function.

Group

E.8 Context tasks and functions

链接
E.8 Context tasks and functions


E.8.2 Context of imported and export tasks and functions

链接
E.8 Context tasks and functions
SystemVerilog 3.1a语言参考手册
E.8.2 Context of imported and export tasks and functions
E.8 Context tasks and functions

DPI imported and export tasks and functions can be declared anywhere a normal SystemVerilog task or function can be declared. Specifically, this means that they can be declared in module, program, interface, or generate declarative scope.

A context imported task or function executes in the context of the instantiated scope surrounding its declaration. This means that such tasks and functions can see other variables in that scope without qualification. As explained in Annex E.8.1, this should not be confused with the context of the task’s or function’s call site, which can actually be anywhere in the SystemVerilog design hierarchy. The context of an imported or exported task or function corresponds to the fully qualified name of the task or function, minus the task or function name itself.

Note that context is transitive through imported and export context tasks and functions declared in the same scope. That is, if an imported task or function is running in a certain context, and if it in turn calls an exported task or function that is available in the same context, the exported task or function can be called without any use of svSetScope(). For example, consider a SystemVerilog call to a native function f(), which in turn calls a native function g(). Now replace the native function f() with an equivalent imported context C function, f’(). The system shall behave identically regardless if f() or f’() is in the call chain above g(). g() has the proper execution context in both cases.

Group

E.8 Context tasks and functions

链接
E.8 Context tasks and functions


E.8.3 Working with DPI context tasks and functions in C code

链接
E.8 Context tasks and functions
SystemVerilog 3.1a语言参考手册
E.8.3 Working with DPI context tasks and functions in C code
E.8 Context tasks and functions

DPI defines a small set of functions to help programmers work with DPI context tasks and functions. The term scope is used in the task or function names for consistency with other SystemVerilog terminology. The terms scope and context are equivalent for DPI tasks and functions.

There are functions that allow the user to retrieve and manipulate the current operational scope. It is an error to use these functions with any C code that is not executing under a call to a DPI context imported task or function.

There are also functions that provide users with the power to set data specific to C models into the SystemVerilog simulator for later retrieval. These are the “put” and “get” user data functions, which are similar to facilities provided in VPI and PLI.

The put and get user data functions are flexible and allow for a number of use models. Users might wish to share user data across multiple context imported functions defined in the same SV scope. Users might wish to have unique data storage on a per function basis. Shared or unique data storage is controllable by a userdefined key.

To achieve shared data storage, a related set of context imported tasks and functions should all use the same userKey. To achieve unique data storage, a context import task or function should use a unique key. Note that it is a requirement on the user that such a key be truly unique from all other keys that could possibly be used by C code. This includes completely unknown C code that could be running in the same simulation. It is suggested that taking addresses of static C symbols (such as a function pointer, or address of some static C data) always be done for user key generation. Generating keys based on arbitrary integers is not a safe practice.

Note that it is never possible to share user data storage across different contexts. For example, if a Verilog module m declares a context imported task or function f, and m is instantiated more than once in the System- Verilog design, then f shall execute under different values of svScope. No such executing instances of f can share user data with each other, at least not using the system-provided user data storage area accessible via svPutUserData().

A user wanting to share a data area across multiple contexts must do so by allocating the common data area, then storing the pointer to it individually for each of the contexts in question via multiple calls to svPutUser- Data(). This is because, although a common user key can be used, the data must be associated with the individual scopes (denoted by svScope) of those contexts.

Copy Code
/* Functions for working with DPI context functions */
/* Retrieve the active instance scope currently associated with the executing
* imported function.
* Unless a prior call to svSetScope has occurred, this is the scope of the
* function’s declaration site, not call site.
* The return value is undefined if this function is invoked from a non-context
* imported function.
*/
svScope svGetScope();
/* Set context for subsequent export function execution.
* This function must be called before calling an export function, unless
* the export function is called while executing an extern function. In that
* case the export function shall inherit the scope of the surrounding extern
* function. This is known as the “default scope”.
* The return is the previous active scope (as per svGetScope)
*/
svScope svSetScope(const svScope scope);
/* Gets the fully qualified name of a scope handle */
const char* svGetNameFromScope(const svScope);
/* Retrieve svScope to instance scope of an arbitrary function declaration.
* (can be either module, program, interface, or generate scope)
* The return value shall be NULL for unrecognized scope names.
*/
svScope svGetScopeFromName(const char* scopeName);
/* Store an arbitrary user data pointer for later retrieval by svGetUserData()
* The userKey is generated by the user. It must be guaranteed by the user to
* be unique from all other userKey’s for all unique data storage requirements
* It is recommended that the address of static functions or variables in the
* user’s C code be used as the userKey.
* It is illegal to pass in NULL values for either the scope or userData
* arguments. It is also an error to call svPutUserData() with an invalid
* svScope. This function returns -1 for all error cases, 0 upon success. It is
* suggested that userData values of 0 (NULL) not be used as otherwise it can
* be impossible to discern error status returns when calling svGetUserData()
*/
int svPutUserData(const svScope scope, void *userKey, void* userData);
/* Retrieve an arbitrary user data pointer that was previously
* stored by a call to svPutUserData(). See the comment above
* svPutUserData() for an explanation of userKey, as well as
* restrictions on NULL and illegal svScope and userKey values.
* This function returns NULL for all error cases, and a non-Null
* user data pointer upon success.
* This function also returns NULL in the event that a prior call
* to svPutUserData() was never made.
*/
void* svGetUserData(const svScope scope, void* userKey);
/* Returns the file and line number in the SV code from which the extern call
* was made. If this information available, returns TRUE and updates fileName
* and lineNumber to the appropriate values. Behavior is unpredictable if
* fileName or lineNumber are not appropriate pointers. If this information is
* not available return FALSE and contents of fileName and lineNumber not
* modified. Whether this information is available or not is implementation
* specific. Note that the string provided (if any) is owned by the SV
* implementation and is valid only until the next call to any SV function.
* Applications must not modify this string or free it
*/
int svGetCallerInfo(char **fileName, int *lineNumber);
Group

E.8 Context tasks and functions

链接
E.8 Context tasks and functions


E.8.4 Example 1 — Using DPI context functions

链接
E.8 Context tasks and functions
SystemVerilog 3.1a语言参考手册
E.8.4 Example 1 — Using DPI context functions
E.8 Context tasks and functions

SV Side:

Copy Code
// Declare an imported context sensitive C function with cname "MyCFunc"
import "DPI" context MyCFunc = function integer MapID(int portID);

C Side:

Copy Code
// Define the function and model class on the C++ side:
class MyCModel {
private:
int locallyMapped(int portID); // Does something interesting...
public:
// Constructor
MyCModel(const char* instancePath) {
svScope svScope = svGetScopeByName(instancePath);
// Associate "this" with the corresponding SystemVerilog scope
// for fast retrieval during runtime.
svPutUserData(svScope, (void*) MyCFunc, this);
}
friend int MyCFunc(int portID);
};
// Implementation of imported context function callable in SV
int MyCFunc(int portID) {
// Retrieve SV instance scope (i.e. this function’s context).
svScope = svGetScope();
// Retrieve and make use of user data stored in SV scope
MyCModel* me = (MyCModel*)svGetUserData(svScope, (void*) MyCFunc);
return me->locallyMapped(portID);
}
Group

E.8 Context tasks and functions

链接
E.8 Context tasks and functions


E.8.5 Relationship between DPI and VPI/PLI interfaces

链接
E.8 Context tasks and functions
SystemVerilog 3.1a语言参考手册
E.8.5 Relationship between DPI and VPI/PLI interfaces
E.8 Context tasks and functions

DPI allows C code to run in the context of a SystemVerilog simulation, thus it is natural for users to consider using VPI/PLI C code from within imported tasks and functions.

There is no specific relationship defined between DPI and the existing Verilog programming interfaces (VPI and PLI). Programmers must make no assumptions about how DPI and the other interfaces interact. In particular, note that a vpiHandle is not equivalent to an svOpenArrayHandle, and the two must not be interchanged and passed between functions defined in two different interface standards.

If a user wants to call VPI or PLI functions from within an imported task or function, the imported task or function must be flagged with the context qualifier.

Not all VPI or PLI functionality is available from within DPI context imported tasks and functions. For example, a SystemVerilog imported task or function is not a system task, and thus making the following call from within an imported task or function would result in an error:

Copy Code
/* Get handle to system task call site in preparation for argument scan */
vpiHandle myHandle = vpi_handle(vpiSysTfCall, NULL);

Similarly, receiving misctf callbacks and other activities associated with system tasks are not supported inside DPI imported tasks and functions. Users should use VPI or PLI if they wish to accomplish such actions.

However, the following kind of code is guaranteed to work from within DPI context imported tasks and functions:

Copy Code
/* Prepare to scan all top level modules */
vpiHandle myHandle = vpi_iterate(vpiModule, NULL);
Group

E.8 Context tasks and functions

链接
E.8 Context tasks and functions


E.9 Include files

链接
附录E DPI C-layer, 主题
SystemVerilog 3.1a语言参考手册
E.9 Include files
附录E DPI C-layer | 主题

The C-layer of the Direct Programming Interface defines two include files. The main include file, svdpi.h, is implementation-independent and defines the canonical representation, all basic types, and all interface functions. The second include file, svdpi_src.h, defines only the actual representation of packed arrays and, hence, is implementation-dependent. Both files are shown in Annex B.

Applications which do not need to include svdpi_src.h are binary-level compatible.

Group

附录E DPI C-layer

主题
主题 | 描述
E.9.1 Binary compatibility include file svdpi.h | Applications which use the Direct Programming Interface with C code usually need this main include file. The include file svdpi.h defines the types for canonical representation of 2-state (bit) and 4-state (logic) values and passing references to SystemVerilog data objects, provides function headers, and defines a number of helper macros and constants. This document fully defines the svdpi.h file. The content of svdpi.h does not depend on any particular implementation or platform; all simulators shall use the same file. The following subsections (and Annex E.10.3.1) detail the contents of the svdpi.h file.
E.9.2 Source-level compatibility include file svdpi_src.h | Only two symbols are defined: the macros that allow declaring variables to represent the SystemVerilog packed arrays of type bit or logic.
E.9.3 Example 2 — binary compatible application | SystemVerilog:
E.9.4 Example 3— source-level compatible application | SystemVerilog:
链接
附录E DPI C-layer, 主题


E.9.1 Binary compatibility include file svdpi.h

链接
E.9 Include files, 主题
SystemVerilog 3.1a语言参考手册
E.9.1 Binary compatibility include file svdpi.h
E.9 Include files | 主题

Applications which use the Direct Programming Interface with C code usually need this main include file. The include file svdpi.h defines the types for canonical representation of 2-state (bit) and 4-state (logic) values and passing references to SystemVerilog data objects, provides function headers, and defines a number of helper macros and constants.

This document fully defines the svdpi.h file. The content of svdpi.h does not depend on any particular implementation or platform; all simulators shall use the same file. The following subsections (and Annex E.10.3.1) detail the contents of the svdpi.h file.

Group

E.9 Include files

主题
主题
描述
E.9.1.1 Scalars of type bit and logic
/* canonical representation */
#define sv_0 0
#define sv_1 1
#define sv_z 2 /* representation of 4-st scalar z */
#define sv_x 3 /* representation of 4-st scalar x */
/* common type for ’bit’ and ’logic’ scalars. */
typedef unsigned char svScalar;
typedef svScalar svBit; /* scalar */
typedef svScalar svLogic; /* scalar *
E.9.1.2 Canonical representation of packed arrays
/* 2-state and 4-state vectors, modelled upon PLI’s avalue/bvalue */
#define SV_CANONICAL_SIZE(WIDTH) (((WIDTH)+31)>>5)
typedef unsigned int
svBitVec32;/* (a chunk of) packed bit array */
typedef struct { unsigned int c; unsigned int d;}
svLogicVec32; /* (a chunk of) packed logic array */
/* Since the contents of the unused bits is undetermined, the following macros
can be handy */
#define SV_MASK(N) (~(-1<<(N)))
#define SV_GET_UNSIGNED_BITS(VALUE,N)\
((N)==32?(VALUE):((VALUE)&SV_MASK(N)))
#define SV_GET_SIGNED_BITS(VALUE,N)\
((N)==32?(VALUE):\
(((VALUE)&(1<<((N)1)))?((VALUE)|~SV_MASK(N)):((VALUE)&SV_MASK(N))))
E.9.1.3 Implementation-dependent representation
/* a handle to a scope (an instance of a module or an interface) */
typedef void *svScope;
/* a handle to a generic object (actually, unsized array) */
typedef void* svOpenArrayHandle;
/* reference to a standalone packed array */
typedef void* svBitPackedArrRef;
typedef void* svLogicPackedArrRef;
/* total size in bytes of the simulator’s representation of a packed array */
/* width in bits */
int svSizeOfBitPackedArr(int width);
int svSizeOfLogicPackedArr(int width);
E.9.1.4 Translation between the actual representation and the canonical representation
链接
E.9 Include files, 主题


E.9.1.1 Scalars of type bit and logic

链接
E.9.1 Binary compatibility include file svdpi.h
SystemVerilog 3.1a语言参考手册
E.9.1.1 Scalars of type bit and logic
E.9.1 Binary compatibility include file svdpi.h

/* canonical representation */

#define sv_0 0

#define sv_1 1

#define sv_z 2 /* representation of 4-st scalar z */

#define sv_x 3 /* representation of 4-st scalar x */

/* common type for ’bit’ and ’logic’ scalars. */

typedef unsigned char svScalar;

typedef svScalar svBit; /* scalar */

typedef svScalar svLogic; /* scalar *

Group

E.9.1 Binary compatibility include file svdpi.h

链接
E.9.1 Binary compatibility include file svdpi.h


E.9.1.2 Canonical representation of packed arrays

链接
E.9.1 Binary compatibility include file svdpi.h
SystemVerilog 3.1a语言参考手册
E.9.1.2 Canonical representation of packed arrays
E.9.1 Binary compatibility include file svdpi.h

/* 2-state and 4-state vectors, modelled upon PLI’s avalue/bvalue */

#define SV_CANONICAL_SIZE(WIDTH) (((WIDTH)+31)>>5)

typedef unsigned int

svBitVec32;/* (a chunk of) packed bit array */

typedef struct { unsigned int c; unsigned int d;}

svLogicVec32; /* (a chunk of) packed logic array */

/* Since the contents of the unused bits is undetermined, the following macros

can be handy */

#define SV_MASK(N) (~(-1<<(N)))

#define SV_GET_UNSIGNED_BITS(VALUE,N)\

((N)==32?(VALUE):((VALUE)&SV_MASK(N)))

#define SV_GET_SIGNED_BITS(VALUE,N)\

((N)==32?(VALUE):\

(((VALUE)&(1<<((N)1)))?((VALUE)|~SV_MASK(N)):((VALUE)&SV_MASK(N))))

Group

E.9.1 Binary compatibility include file svdpi.h

链接
E.9.1 Binary compatibility include file svdpi.h


E.9.1.3 Implementation-dependent representation

链接
E.9.1 Binary compatibility include file svdpi.h
SystemVerilog 3.1a语言参考手册
E.9.1.3 Implementation-dependent representation
E.9.1 Binary compatibility include file svdpi.h

/* a handle to a scope (an instance of a module or an interface) */

typedef void *svScope;

/* a handle to a generic object (actually, unsized array) */

typedef void* svOpenArrayHandle;

/* reference to a standalone packed array */

typedef void* svBitPackedArrRef;

typedef void* svLogicPackedArrRef;

/* total size in bytes of the simulator’s representation of a packed array */

/* width in bits */

int svSizeOfBitPackedArr(int width);

int svSizeOfLogicPackedArr(int width);

Group

E.9.1 Binary compatibility include file svdpi.h

链接
E.9.1 Binary compatibility include file svdpi.h


E.9.1.4 Translation between the actual representation and the canonical representation

链接
E.9.1 Binary compatibility include file svdpi.h
SystemVerilog 3.1a语言参考手册
E.9.1.4 Translation between the actual representation and the canonical representation
E.9.1 Binary compatibility include file svdpi.h
Copy Code
/* functions for translation between the representation actually used by
simulator and the canonical representation */
/* s=source, d=destination, w=width */
/* actual <-- canonical */
void svPutBitVec32 (svBitPackedArrRef d, const svBitVec32* s, int w);
void svPutLogicVec32 (svLogicPackedArrRef d, const svLogicVec32* s, int w);
/* canonical <-- actual */
void svGetBitVec32 (svBitVec32* d, const svBitPackedArrRef s, int w);
void svGetLogicVec32 (svLogicVec32* d, const svLogicPackedArrRef s, int w);

The above functions copy the whole array in either direction. The user is responsible for providing the correct width and for allocating an array in the canonical representation. The contents of the unused bits is undetermined.

Although the put/get functionality provided for bit and logic packed arrays is sufficient, yet basic, it requires unnecessary copying of the whole packed array when perhaps only some bits are needed. For the sake of convenience and improved performance, bit selects and limited (up to 32 bits) part selects are also supported, see Annex E.10.3.1 and Annex E.10.3.2.

Group

E.9.1 Binary compatibility include file svdpi.h

链接
E.9.1 Binary compatibility include file svdpi.h


E.9.2 Source-level compatibility include file svdpi_src.h

链接
E.9 Include files
SystemVerilog 3.1a语言参考手册
E.9.2 Source-level compatibility include file svdpi_src.h
E.9 Include files

Only two symbols are defined: the macros that allow declaring variables to represent the SystemVerilog packed arrays of type bit or logic.

Copy Code
#define SV_BIT_PACKED_ARRAY(WIDTH,NAME) ...
#define SV_LOGIC_PACKED_ARRAY(WIDTH,NAME) ...

The actual definitions are implementation-specific. For example, a SystemVerilog simulator might define the later macro as follows.

Copy Code
#define SV_LOGIC_PACKED_ARRAY(WIDTH,NAME) \
             svLogicVec32 NAME [ SV_CANONICAL_SIZE(WIDTH) ]
Group

E.9 Include files

链接
E.9 Include files


E.9.3 Example 2 — binary compatible application

链接
E.9 Include files
SystemVerilog 3.1a语言参考手册
E.9.3 Example 2 — binary compatible application
E.9 Include files

SystemVerilog:

Copy Code
typedef struct {int a; int b;} pair;
import "DPI" function void foo(input int i1, pair i2, output logic [63:0] o3);
export "DPI" function exported_sv_func;
function void exported_sv_func(input int i, output int o [0:7]);
begin ... end
endfunction

C:

Copy Code
#include "svdpi.h"
typedef struct {int a; int b;} pair;
extern void exported_sv_func(int, int *); /* imported from SystemVerilog */
void foo(const int i1, const pair *i2, svLogicPackedArrRef o3)
{
svLogicVec32 arr[SV_CANONICAL_SIZE(64)]; /* 2 chunks needed */
int tab[8];
printf("%d\n", i1);
arr[1].c = i2->a;
arr[1].d = 0;
arr[2].c = i2->b;
arr[2].d = 0;
svPutLogicVec32 (o3, arr, 64);
/* call SystemVerilog */
exported_sv_func(i1, tab); /* tab passed by reference */
...
}
Group

E.9 Include files

链接
E.9 Include files


E.9.4 Example 3— source-level compatible application

链接
E.9 Include files
SystemVerilog 3.1a语言参考手册
E.9.4 Example 3— source-level compatible application
E.9 Include files

SystemVerilog:

Copy Code
typedef struct {int a; bit [6:1][1:8] b [65:2]; int c;} triple;
// troublesome mix of C types and packed arrays
import "DPI" function void foo(input triple i);
export "DPI" function exported_sv_func;
function void exported_sv_func(input int i, output logic [63:0] o);
begin ... end
endfunction

C:

Copy Code
#include "svdpi.h"
#include "svdpi_src.h"
typedef struct {
int a;
sv_BIT_PACKED_ARRAY(6*8, b) [64]; /* implementation specific
representation */
int c;
} triple;
/* Note that ’b’ is defined as for ’bit [6*8-1:0] b [63:0]’ */
extern void exported_sv_func(int, svLogicPackedArrRef); /* imported from
SystemVerilog */
void foo(const triple *i)
{
int j;
/* canonical representation */
svBitVec32 arr[SV_CANONICAL_SIZE(6*8)]; /* 6*8 packed bits */
svLogicVec32 aL[SV_CANONICAL_SIZE(64)];
/* implementation specific representation */
SV_LOGIC_PACKED_ARRAY(64, my_tab);
printf("%d %d\n", i->a, i->c);
for (j=0; j<64; j++) {
svGetBitVec32(arr, (svBitPackedArrRef)&(i->b[j]), 6*8);
...
}
...
/* call SystemVerilog */
exported_sv_func(2, (svLogicPackedArrRef)&my_tab); /* by reference */
svGetLogicVec32(aL, (svLogicPackedArrRef)&my_tab, 64); ... }

NOTE—a, b, and c are directly accessed as fields in a structure. In the case of b, which represents unpacked array of packed arrays, the individual element is accessed via the library function svGetBitVec32(), by passing its address to the function.

Group

E.9 Include files

链接
E.9 Include files


E.10 Arrays

链接
附录E DPI C-layer, 主题
SystemVerilog 3.1a语言参考手册
E.10 Arrays
附录E DPI C-layer | 主题

Normalized ranges are used for accessing SystemVerilog arrays, with the exception of formal arguments specified as open arrays.

Group

附录E DPI C-layer

主题
主题 | 描述
E.10.1 Multidimensional arrays | Packed arrays shall be one-dimensional. Unpacked arrays can have an arbitrary number of dimensions.
E.10.2 Direct access to unpacked arrays | Unpacked arrays, with the exception of formal arguments specified as open arrays, shall have the same layout as used by a C compiler; they are accessed using C indexing (see Annex E.6.6).
E.10.3 Access to packed arrays via canonical representation | Packed arrays are accessible via canonical representation; this C-layer interface provides functions for moving data between implementation representation and canonical representation (any necessary conversion is performed on-the-fly (see Annex E.9.1.3)), and for bit selects and limited (up to 32-bit) part selects. (Bit selects do not involve any canonical representation.)
链接
附录E DPI C-layer, 主题


E.10.1 Multidimensional arrays

链接
E.10 Arrays
SystemVerilog 3.1a语言参考手册
E.10.1 Multidimensional arrays
E.10 Arrays

Packed arrays shall be one-dimensional. Unpacked arrays can have an arbitrary number of dimensions.

Group

E.10 Arrays

链接
E.10 Arrays


E.10.2 Direct access to unpacked arrays

链接
E.10 Arrays
SystemVerilog 3.1a语言参考手册
E.10.2 Direct access to unpacked arrays
E.10 Arrays

Unpacked arrays, with the exception of formal arguments specified as open arrays, shall have the same layout as used by a C compiler; they are accessed using C indexing (see Annex E.6.6).

Group

E.10 Arrays

链接
E.10 Arrays


E.10.3 Access to packed arrays via canonical representation

链接
E.10 Arrays, 主题
SystemVerilog 3.1a语言参考手册
E.10.3 Access to packed arrays via canonical representation
E.10 Arrays | 主题

Packed arrays are accessible via canonical representation; this C-layer interface provides functions for moving data between implementation representation and canonical representation (any necessary conversion is performed on-the-fly (see Annex E.9.1.3)), and for bit selects and limited (up to 32-bit) part selects. (Bit selects do not involve any

canonical representation.)

Group

E.10 Arrays

主题
主题 | 描述
E.10.3.1 Bit selects | This subsection defines the bit selects portion of the svdpi.h file (see Annex E.9.1 for more details).
E.10.3.2 Part selects | logic. Array slices are not supported for unpacked arrays. Additionally, 64-bit wide part select can be read as a single value of type unsigned long long. Functions for part selects only allow access (read/write) to a narrow subrange of up to 32 bits. A canonical representation shall be used for such narrow vectors. If the specified range of part select is not fully contained within the normalized range of an array, the behavior is undetermined. For the convenience, bit type part selects are returned as a function result. In addition to a general function for narrow part selects (<= 32-bits),... more
链接
E.10 Arrays, 主题


E.10.3.1 Bit selects

链接
E.10.3 Access to packed arrays via canonical representation
SystemVerilog 3.1a语言参考手册
E.10.3.1 Bit selects
E.10.3 Access to packed arrays via canonical representation

This subsection defines the bit selects portion of the svdpi.h file (see Annex E.9.1 for more details).

Copy Code
/* Packed arrays are assumed to be indexed n-1:0,
where 0 is the index of least significant bit */
/* functions for bit select */
/* s=source, i=bit-index */
svBit svGetSelectBit(const svBitPackedArrRef s, int i);
svLogic svGetSelectLogic(const svLogicPackedArrRef s, int i);
/* d=destination, i=bit-index, s=scalar */
void svPutSelectBit(svBitPackedArrRef d, int i, svBit s);
void svPutSelectLogic(svLogicPackedArrRef d, int i, svLogic s);
Group

E.10.3 Access to packed arrays via canonical representation

链接
E.10.3 Access to packed arrays via canonical representation


E.10.3.2 Part selects

链接
E.10.3 Access to packed arrays via canonical representation
SystemVerilog 3.1a语言参考手册
E.10.3.2 Part selects
E.10.3 Access to packed arrays via canonical representation

logic. Array slices are not supported for unpacked arrays. Additionally, 64-bit wide part select can be read as a single value of type unsigned long long.

Functions for part selects only allow access (read/write) to a narrow subrange of up to 32 bits. A canonical representation shall be used for such narrow vectors. If the specified range of part select is not fully contained within the normalized range of an array, the behavior is undetermined.

For the convenience, bit type part selects are returned as a function result. In addition to a general function for narrow part selects (<= 32-bits), there are two specialized functions for 32 and 64 bits.

Copy Code
/*
* functions for part select
*
* a narrow (<=32 bits) part select is copied between
* the implementation representation and a single chunk of
* canonical representation
* Normalized ranges and indexing [n-1:0] are used for both arrays:
* the array in the implementation representation and the canonical array.
*
* s=source, d=destination, i=starting bit index, w=width
* like for variable part selects; limitations: w <= 32
*
* In part select operations, the data is copied to or from the
* canonical representation part (’chunk’) designated by range [w-1:0]
* and the implementation representation part designated by range [w+i-1:i].
*/

NOTE—For the sake of symmetry, a canonical representation (i.e., an array) is used both for bit and logic, although a simpler int can be used for bit-part selects (<= 32-bits):

Copy Code
/* canonical <-- actual */
void svGetPartSelectBit(svBitVec32* d, const svBitPackedArrRef s, int i,
int w);
svBitVec32 svGetBits(const svBitPackedArrRef s, int i, int w);
svBitVec32 svGet32Bits(const svBitPackedArrRef s, int i); // 32-bits
unsigned long long svGet64Bits(const svBitPackedArrRef s, int i); // 64-bits
void svGetPartSelectLogic(svLogicVec32* d, const svLogicPackedArrRef s, int i,
int w);
/* actual <-- canonical */
void svPutPartSelectBit(svBitPackedArrRef d, const svBitVec32 s, int i,
int w);
void svPutPartSelectLogic(svLogicPackedArrRef d, const svLogicVec32 s, int i,
int w);
Group

E.10.3 Access to packed arrays via canonical representation

链接
E.10.3 Access to packed arrays via canonical representation


E.11 Open arrays

链接
附录E DPI C-layer, 主题
SystemVerilog 3.1a语言参考手册
E.11 Open arrays
附录E DPI C-layer | 主题

Formal arguments specified as open arrays allows passing actual arguments of different sizes (i.e., different range and/or different number of elements), which facilitates writing more general C code that can handle SystemVerilog arrays of different sizes. The elements of an open array can be accessed in C by using the same range of indices and the same indexing as in SystemVerilog. Plus, inquiries about the dimensions and the original boundaries of SystemVerilog actual arguments are supported for open arrays.

NOTE—Both packed and unpacked array dimensions can be unsized.

All formal arguments declared in SystemVerilog as open arrays are passed by handle (type svOpenArray- Handle), regardless of the direction of a SystemVerilog formal argument. Such arguments are accessible via interface functions.

Group

附录E DPI C-layer

主题
主题
描述
E.11.1 Actual ranges
The formal arguments defined as open arrays have the size and ranges of the actual argument, as determined on a per-call basis. The programmer shall always have a choice whether to specify a formal argument as a sized array or as an open (unsized) array.

In the former case, all indices are normalized on the C side (i.e., 0 and up) and the programmer needs to know the size of an array and be capable of determining how the ranges of the actual argument map onto C-style ranges (see Annex E.6.6).

Tip: programmers can decide to use [n:0]name[0:k] style ranges... more
E.11.2 Array querying functions
These functions are modelled upon the SystemVerilog array querying functions and use the same semantics (see Section 23.7).

If the dimension is 0, then the query refers to the packed part (which is one-dimensional) of an array, and dimensions > 0 refer to the unpacked part of an array.
E.11.3 Access functions
Similarly to sized arrays, there are functions for copying data between the simulator representation and the canonical representation and to obtain the actual address of SystemVerilog data object or of an individual element of an unpacked array. This information might be useful for simulator-specific tuning of the application. Depending on the type of an element of an unpacked array, different access methods shall be used when working with elements.
  • Packed arrays ( bit or logic) are accessed via copying to or from the canonical representation.
  • Scalars (1-bit value of type bit or logic) are accessed (read or written) directly.
  • Other... more
E.11.4 Access to the actual representation
The following functions provide an actual address of the whole array or of its individual elements. These functions shall be used for accessing elements of arrays of types compatible with C. These functions are also useful for vendors, because they provide access to the actual representation for all types of arrays.

If the actual layout of the SystemVerilog array passed as an argument for an open unpacked array is different than the C layout, then it is not possible to access such an array as a whole; therefore, the address and size of such an array shall be undefined (zero... more
E.11.5 Access to elements via canonical representation
The following functions copy a single vector from a canonical representation to an element of an open array or other way round. The element of an array is identified by indices, bound by the ranges of the actual argument, i.e., the original SystemVerilog ranges are used for indexing.
E.11.6 Access to scalar elements (bit and logic)
Another group of functions is needed for scalars (i.e., when an element of an array is a simple scalar, bit, or logic):
E.11.7 Access to array elements of other types
If an array’s elements are of a type compatible with C, there is no need to use canonical representation. In such situations, the elements are accessed via pointers, i.e., the actual address of an element shall be computed first and then used to access the desired element.
E.11.8 Example 4— two-dimensional open array
SystemVerilog:
E.11.9 Example 5 — open array
SystemVerilog:
E.11.10 Example 6 — access to packed arrays
SystemVerilog:
E.11.11 Example 7 — binary compatible calls of exported functions
This example demonstrates the source compatibility include file svdpi_src.h is not needed if a C function dynamically allocates the data structure for simulator representation of a packed array to be passed to an exported SystemVerilog function.

SystemVerilog:
链接
附录E DPI C-layer, 主题


E.11.1 Actual ranges

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.1 Actual ranges
E.11 Open arrays

The formal arguments defined as open arrays have the size and ranges of the actual argument, as determined on a per-call basis. The programmer shall always have a choice whether to specify a formal argument as a sized array or as an open (unsized) array.

In the former case, all indices are normalized on the C side (i.e., 0 and up) and the programmer needs to know the size of an array and be capable of determining how the ranges of the actual argument map onto C-style ranges (see Annex E.6.6).

Tip: programmers can decide to use [n:0]name[0:k] style ranges in SystemVerilog.

In the later case, i.e., an open array, individual elements of a packed array are accessible via interface functions, which facilitate the SystemVerilog-style of indexing with the original boundaries of the actual argument.

If a formal argument is specified as a sized array, then it shall be passed by reference, with no overhead, and is directly accessible as a normalized array. If a formal argument is specified as an open (unsized) array, then it shall be passed by handle, with some overhead, and is mostly indirectly accessible, again with some overhead, although it retains the original argument boundaries.

NOTE—This provides some degree of flexibility and allows the programmer to control the trade-off of performance vs. convenience.

The following example shows the use of sized vs. unsized arrays in SystemVerilog code.

Copy Code
// both unpacked arrays are 64 by 8 elements, packed 16-bit each
logic [15: 0] a_64x8 [63:0][7:0];
logic [31:16] b_64x8 [64:1][-1:-8];
import "DPI" function void foo(input logic [] i [][]);
// 2-dimensional unsized unpacked array of unsized packed logic
import "DPI" function void boo(input logic [31:16] i [64:1][-1:-8]);
// 2-dimensional sized unpacked array of sized packed logic
foo(a_64x8);
foo(b_64x8); // C code can use original ranges [31:16][64:1][-1:-8]
boo(b_64x8); // C code must use normalized ranges [15:0][0:63][0:7]
Group

E.11 Open arrays

链接
E.11 Open arrays


E.11.2 Array querying functions

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.2 Array querying functions
E.11 Open arrays

These functions are modelled upon the SystemVerilog array querying functions and use the same semantics (see Section 23.7).

If the dimension is 0, then the query refers to the packed part (which is one-dimensional) of an array, and dimensions > 0 refer to the unpacked part of an array.

Copy Code
/* h= handle to open array, d=dimension */
int svLeft(const svOpenArrayHandle h, int d);
int svRight(const svOpenArrayHandle h, int d);
int svLow(const svOpenArrayHandle h, int d);
int svHigh(const svOpenArrayHandle h, int d);
int svIncrement(const svOpenArrayHandle h, int d);
int svLength(const svOpenArrayHandle h, int d);
int svDimensions(const svOpenArrayHandle h);
Group

E.11 Open arrays

链接
E.11 Open arrays


E.11.3 Access functions

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.3 Access functions
E.11 Open arrays

Similarly to sized arrays, there are functions for copying data between the simulator representation and the canonical representation and to obtain the actual address of SystemVerilog data object or of an individual element of an unpacked array. This information might be useful for simulator-specific tuning of the application. Depending on the type of an element of an unpacked array, different access methods shall be used when working with elements.

  • Packed arrays ( bit or logic) are accessed via copying to or from the canonical representation.
  • Scalars (1-bit value of type bit or logic) are accessed (read or written) directly.
  • Other types of values (e.g., structures) are accessed via generic pointers; a library function calculates an address and the user needs to provide the appropriate casting.
  • Scalars and packed arrays are accessible via pointers only if the implementation supports this functionality (per array), e.g., one array can be represented in a form that allows such access, while another array might use a compacted representation which renders this functionality unfeasible (both occurring within the same simulator).
SystemVerilog allows arbitrary dimensions and, hence, an arbitrary number of indices. To facilitate this, variable argument list functions shall be used. For the sake of performance, specialized versions of all indexing functions are provided for 1, 2, or 3 indices.

Group

E.11 Open arrays

链接
E.11 Open arrays


E.11.4 Access to the actual representation

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.4 Access to the actual representation
E.11 Open arrays

The following functions provide an actual address of the whole array or of its individual elements. These functions shall be used for accessing elements of arrays of types compatible with C. These functions are also useful for vendors, because they provide access to the actual representation for all types of arrays.

If the actual layout of the SystemVerilog array passed as an argument for an open unpacked array is different than the C layout, then it is not possible to access such an array as a whole; therefore, the address and size of such an array shall be undefined (zero (0), to be exact). Nonetheless, the addresses of individual elements of an array shall be always supported.

NOTE—No specific representation of an array is assumed here; hence, all functions use a generic pointer void *.

Copy Code
/* a pointer to the actual representation of the whole array of any type */
/* NULL if not in C layout */
void *svGetArrayPtr(const svOpenArrayHandle);
int svSizeOfArray(const svOpenArrayHandle); /* total size in bytes or 0 if not
in C layout */
/* Return a pointer to an element of the array
or NULL if index outside the range or null pointer */
void *svGetArrElemPtr(const svOpenArrayHandle, int indx1, ...);
/* specialized versions for 1-, 2- and 3-dimensional arrays: */
void *svGetArrElemPtr1(const svOpenArrayHandle, int indx1);
void *svGetArrElemPtr2(const svOpenArrayHandle, int indx1, int indx2);
void *svGetArrElemPtr3(const svOpenArrayHandle, int indx1, int indx2,
int indx3);

Access to an individual array element via pointer makes sense only if the representation of such an element is the same as it would be for an individual value of the same type. Representation of array elements of type scalar or packed value is implementation-dependent; the above functions shall return NULL if the representation of the array elements differs from the representation of individual values of the same type.

Group

E.11 Open arrays

链接
E.11 Open arrays


E.11.5 Access to elements via canonical representation

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.5 Access to elements via canonical representation
E.11 Open arrays

The following functions copy a single vector from a canonical representation to an element of an open array or other way round. The element of an array is identified by indices, bound by the ranges of the actual argument, i.e., the original SystemVerilog ranges are used for indexing.

Copy Code
/* functions for translation between simulator and canonical representations*/
/* s=source, d=destination */
/* actual <-- canonical */
void svPutBitArrElemVec32 (const svOpenArrayHandle d, const svBitVec32* s,
int indx1, ...);
void svPutBitArrElem1Vec32(const svOpenArrayHandle d, const svBitVec32* s,
int indx1);
void svPutBitArrElem2Vec32(const svOpenArrayHandle d, const svBitVec32* s,
int indx1, int indx2);
void svPutBitArrElem3Vec32(const svOpenArrayHandle d, const svBitVec32* s,
int indx1, int indx2, int indx3);
void svPutLogicArrElemVec32 (const svOpenArrayHandle d, const svLogicVec32* s,
int indx1, ...);
void svPutLogicArrElem1Vec32(const svOpenArrayHandle d, const svLogicVec32* s,
int indx1);
void svPutLogicArrElem2Vec32(const svOpenArrayHandle d, const svLogicVec32* s,
int indx1, int indx2);
void svPutLogicArrElem3Vec32(const svOpenArrayHandle d, const svLogicVec32* s,
int indx1, int indx2, int indx3);
/* canonical <-- actual */
void svGetBitArrElemVec32 (svBitVec32* d, const svOpenArrayHandle s,
int indx1, ...);
void svGetBitArrElem1Vec32(svBitVec32* d, const svOpenArrayHandle s,
int indx1);
void svGetBitArrElem2Vec32(svBitVec32* d, const svOpenArrayHandle s,
int indx1, int indx2);
void svGetBitArrElem3Vec32(svBitVec32* d, const svOpenArrayHandle s,
int indx1, int indx2, int indx3);
void svGetLogicArrElemVec32 (svLogicVec32* d, const svOpenArrayHandle s,
int indx1, ...);
void svGetLogicArrElem1Vec32(svLogicVec32* d, const svOpenArrayHandle s,
int indx1);
void svGetLogicArrElem2Vec32(svLogicVec32* d, const svOpenArrayHandle s,
int indx1, int indx2);
void svGetLogicArrElem3Vec32(svLogicVec32* d, const svOpenArrayHandle s,
int indx1, int indx2, int indx3);

The above functions copy the whole packed array in either direction. The user is responsible for allocating an array in the canonical representation.

Group

E.11 Open arrays

链接
E.11 Open arrays


E.11.6 Access to scalar elements (bit and logic)

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.6 Access to scalar elements (bit and logic)
E.11 Open arrays

Another group of functions is needed for scalars (i.e., when an element of an array is a simple scalar, bit, or logic):

Copy Code
svBit svGetBitArrElem (const svOpenArrayHandle s, int indx1, ...);
svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1);
svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
int indx3);
svLogic svGetLogicArrElem (const svOpenArrayHandle s, int indx1, ...);
svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1);
svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
int indx3);
void svPutLogicArrElem (const svOpenArrayHandle d, svLogic value, int indx1,
...);
void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1);
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1,
int indx2);
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1,
int indx2, int indx3);
void svPutBitArrElem (const svOpenArrayHandle d, svBit value, int indx1, ...);
void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1);
void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1,
int indx2);
void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1,
int indx2, int indx3);
Group

E.11 Open arrays

链接
E.11 Open arrays


E.11.7 Access to array elements of other types

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.7 Access to array elements of other types
E.11 Open arrays

If an array’s elements are of a type compatible with C, there is no need to use canonical representation. In such situations, the elements are accessed via pointers, i.e., the actual address of an element shall be computed first and then used to access the desired element.

Group

E.11 Open arrays

链接
E.11 Open arrays


E.11.8 Example 4— two-dimensional open array

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.8 Example 4— two-dimensional open array
E.11 Open arrays

SystemVerilog:

Copy Code
typedef struct {int i; ... } MyType;
import "DPI" function void foo(input MyType i [][]); /* 2-dimensional unsized
unpacked array of MyType */
MyType a_10x5 [11:20][6:2];
MyType a_64x8 [64:1][-1:-8];
foo(a_10x5);
foo(a_64x8);

C:

Copy Code
#include "svdpi.h"
typedef struct {int i; ... } MyType;
void foo(const svOpenArrayHandle h)
{
MyType my_value;
int i, j;
int lo1 = svLow(h, 1);
int hi1 = svHigh(h, 1);
int lo2 = svLow(h, 2);
int hi2 = svHigh(h, 2);
for (i = lo1; i <= hi1; i++) {
for (j = lo2; j <= hi2; j++) {
my_value = *(MyType *)svGetArrElemPtr2(h, i, j);
...
*(MyType *)svGetArrElemPtr2(h, i, j) = my_value;
...
}
...
}
}
Group

E.11 Open arrays

链接
E.11 Open arrays


E.11.9 Example 5 — open array

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.9 Example 5 — open array
E.11 Open arrays

SystemVerilog:

Copy Code
typedef struct { ... } MyType;
import "DPI" function void foo(input MyType i [], output MyType o []);
MyType source [11:20];
MyType target [11:20];
foo(source, target);

C:

Copy Code
#include "svdpi.h"
typedef struct ... } MyType;
void foo(const svOpenArrayHandle hin, const svOpenArrayHandle hout)
{
int count = svLength(hin, 1);
MyType *s = (MyType *)svGetArrayPtr(hin);
MyType *d = (MyType *)svGetArrayPtr(hout);
if (s && d) { /* both arrays have C layout */
/* an efficient solution using pointer arithmetic */
while (count--)
*d++ = *s++;
/* even more efficient:
memcpy(d, s, svSizeOfArray(hin));
*/
} else { /* less efficient yet implementation independent */
int i = svLow(hin, 1);
int j = svLow(hout, 1);
while (i <= svHigh(hin, 1)) {
*(MyType *)svGetArrElemPtr1(hout, j++) =
*(MyType *)svGetArrElemPtr1(hin, i++);
}
}
}
Group

E.11 Open arrays

链接
E.11 Open arrays


E.11.10 Example 6 — access to packed arrays

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.10 Example 6 — access to packed arrays
E.11 Open arrays

SystemVerilog:

Copy Code
import "DPI" function void foo(input logic [127:0]);
import "DPI" function void boo(input logic [127:0] i []); // open array of
// 128-bit

C:

Copy Code
#include "svdpi.h"
/* one 128-bit packed vector */
void foo(const svLogicPackedArrRef packed_vec_128_bit)
{
svLogicVec32 arr[SV_CANONICAL_SIZE(128)]; /* canonical representation */
svGetLogicVec32(arr, packed_vec_128_bit, 128);
...
}
/* open array of 128-bit packed vectors */
void boo(const svOpenArrayHandle h)
{
int i;
svLogicVec32 arr[SV_CANONICAL_SIZE(128)]; /* canonical representation */
for (i = svLow(h, 1); i <= svHigh(h, 1); i++) {
svLogicPackedArrRef ptr = (svLogicPackedArrRef)svGetArrElemPtr1(h, i);
/* user need not know the vendor representation! */
svGetLogicVec32(arr, ptr, 128);
...
}
...
}
Group

E.11 Open arrays

链接
E.11 Open arrays


E.11.11 Example 7 — binary compatible calls of exported functions

链接
E.11 Open arrays
SystemVerilog 3.1a语言参考手册
E.11.11 Example 7 — binary compatible calls of exported functions
E.11 Open arrays

This example demonstrates the source compatibility include file svdpi_src.h is not needed if a C function dynamically allocates the data structure for simulator representation of a packed array to be passed to an exported SystemVerilog function.

SystemVerilog:

Copy Code
export "DPI" function myfunc;
...
function void myfunc (output logic [31:0] r); ...
...

C:

Copy Code
#include "svdpi.h"
extern void myfunc (svLogicPackedArrRef r); /* exported from SV */
/* output logic packed 32-bits */
...
svLogicVec32 my_r[SV_CANONICAL_SIZE(32)];
/* my array, canonical representation */
/* allocate memory for logic packed 32-bits in simulator’s representation */
svLogicPackedArrRef r =
(svLogicPackedArrRef)malloc(svSizeOfLogicPackedArr(32));
myfunc(r);
/* canonical <-- actual */
svGetLogicVec32(my_r, r, 32);
/* shall use only the canonical representation from now on */
free(r); /* don’t need any more */
...
Group

E.11 Open arrays

链接
E.11 Open arrays


附录F 包含文件

链接
主题
SystemVerilog 3.1a语言参考手册
附录F 包含文件
主题

本附录显示了svdpi.h和svdpi_src.h包含文件的内容。

主题
主题 | 描述
F.1 Binary-level compatibility include file svdpi.h |
F.2 源级兼容性包含文件svdpi_src.h |
链接
主题


F.1 Binary-level compatibility include file svdpi.h

链接
附录F 包含文件
SystemVerilog 3.1a语言参考手册
F.1 Binary-level compatibility include file svdpi.h
附录F 包含文件
Copy Code
/* canonical representation */
#define sv_0 0
#define sv_1 1
#define sv_z 2 /* representation of 4-st scalar z */
#define sv_x 3 /* representation of 4-st scalar x */
/* common type for ’bit’ and ’logic’ scalars. */
typedef unsigned char svScalar;
typedef svScalar svBit; /* scalar */
typedef svScalar svLogic; /* scalar */
/* Canonical representation of packed arrays */
/* 2-state and 4-state vectors, modelled upon PLI’s avalue/bvalue */
#define SV_CANONICAL_SIZE(WIDTH) (((WIDTH)+31)>>5)
typedef unsigned int
svBitVec32; /* (a chunk of) packed bit array */
typedef struct { unsigned int c; unsigned int d;}
svLogicVec32; /* (a chunk of) packed logic array */
/* Since the contents of the unused bits is undetermined, the following macros can
be handy */
#define SV_MASK(N) (~(-1<<(N)))
#define SV_GET_UNSIGNED_BITS(VALUE,N)\
((N)==32?(VALUE):((VALUE)&SV_MASK(N)))
#define SV_GET_SIGNED_BITS(VALUE,N)\
((N)==32?(VALUE):\
(((VALUE)&(1<<((N)1)))?((VALUE)|~SV_MASK(N)):((VALUE)&SV_MASK(N))))
/* implementation-dependent representation */
/* a handle to a scope (an instance of a module or interface) */
typedef void* svScope;
/* a handle to a generic object (actually, unsized array) */
typedef void* svOpenArrayHandle;
/* reference to a standalone packed array */
typedef void* svBitPackedArrRef;
typedef void* svLogicPackedArrRef;
/* total size in bytes of the simulator’s representation of a packed array */
/* width in bits */
int svSizeOfBitPackedArr(int width);
int svSizeOfLogicPackedArr(int width);
/* Translation between the actual representation and canonical representation */
/* functions for translation between the representation actually used by
simulator and the canonical representation */
/* s=source, d=destination, w=width */
/* actual <-- canonical */
void svPutBitVec32 (svBitPackedArrRef d, const svBitVec32* s, int w);
void svPutLogicVec32 (svLogicPackedArrRef d, const svLogicVec32* s, int w);
/* canonical <-- actual */
void svGetBitVec32 (svBitVec32* d, const svBitPackedArrRef s, int w);
void svGetLogicVec32 (svLogicVec32* d, const svLogicPackedArrRef s, int w);
/* Bit selects */
/* Packed arrays are assumed to be indexed n-1:0,
where 0 is the index of least significant bit */
/* functions for bit select */
/* s=source, i=bit-index */
svBit svGetSelectBit(const svBitPackedArrRef s, int i);
svLogic svGetSelectLogic(const svLogicPackedArrRef s, int i);
/* d=destination, i=bit-index, s=scalar */
void svPutSelectBit(svBitPackedArrRef d, int i, svBit s);
void svPutSelectLogic(svLogicPackedArrRef d, int i, svLogic s);
/*
* functions for part select
*
* a narrow (<=32 bits) part select is copied between
* the implementation representation and a single chunk of
* canonical representation
* Normalized ranges and indexing [n-1:0] are used for both arrays:
* the array in the implementation representation and the canonical array.
*
* s=source, d=destination, i=starting bit index, w=width
* like for variable part selects; limitations: w <= 32
*
* In part select operations, the data is copied to or from the
* canonical representation part (’chunk’) designated by range [w-1:0]
* and the implementation representation part designated by range [w+i-1:i].
*/
/* canonical <-- actual */
void svGetPartSelectBit(svBitVec32* d, const svBitPackedArrRef s, int i,
int w);
svBitVec32 svGetBits(const svBitPackedArrRef s, int i, int w);
svBitVec32 svGet32Bits(const svBitPackedArrRef s, int i); // 32-bits
unsigned long long svGet64Bits(const svBitPackedArrRef s, int i); // 64-bits
void svGetPartSelectLogic(svLogicVec32* d, const svLogicPackedArrRef s, int i,
int w);
/* actual <-- canonical */
void svPutPartSelectBit(svBitPackedArrRef d, const svBitVec32 s, int i, int w);
void svPutPartSelectLogic(svLogicPackedArrRef d, const svLogicVec32 s, int i,
int w);
/* Array querying functions */
/* These functions are modelled upon the SystemVerilog array querying functions
and use the same semantics*/
/* If the dimension is 0, then the query refers to the packed part (which is onedimensional)
of an array, and dimensions > 0 refer to the unpacked part of an
array.*/
/* h= handle to open array, d=dimension */
int svLeft(const svOpenArrayHandle h, int d);
int svRight(const svOpenArrayHandle h, int d);
int svLow(const svOpenArrayHandle h, int d);
int svHigh(const svOpenArrayHandle h, int d);
int svIncrement(const svOpenArrayHandle h, int d);
int svLength(const svOpenArrayHandle h, int d);
int svDimensions(const svOpenArrayHandle h);
/* a pointer to the actual representation of the whole array of any type */
/* NULL if not in C layout */
void *svGetArrayPtr(const svOpenArrayHandle);
int svSizeOfArray(const svOpenArrayHandle); /* total size in bytes or 0 if not in C
layout */
/* Return a pointer to an element of the array
or NULL if index outside the range or null pointer */
void *svGetArrElemPtr(const svOpenArrayHandle, int indx1, ...);
/* specialized versions for 1-, 2- and 3-dimensional arrays: */
void *svGetArrElemPtr1(const svOpenArrayHandle, int indx1);
void *svGetArrElemPtr2(const svOpenArrayHandle, int indx1, int indx2);
void *svGetArrElemPtr3(const svOpenArrayHandle, int indx1, int indx2, int indx3);
/* Functions for translation between simulator and canonical representations*/
/* These functions copy the whole packed array in either direction. The user is
responsible for allocating an array in the canonical representation. */
/* s=source, d=destination */
/* actual <-- canonical */
void svPutBitArrElemVec32 (const svOpenArrayHandle d, const svBitVec32* s,
int indx1, ...);
void svPutBitArrElem1Vec32(const svOpenArrayHandle d, const svBitVec32* s,
int indx1);
void svPutBitArrElem2Vec32(const svOpenArrayHandle d, const svBitVec32* s,
int indx1, int indx2);
void svPutBitArrElem3Vec32(const svOpenArrayHandle d, const svBitVec32* s,
int indx1, int indx2, int indx3);
void svPutLogicArrElemVec32 (const svOpenArrayHandle d, const svLogicVec32* s,
int indx1, ...);
void svPutLogicArrElem1Vec32(const svOpenArrayHandle d, const svLogicVec32* s,
int indx1);
void svPutLogicArrElem2Vec32(const svOpenArrayHandle d, const svLogicVec32* s,
int indx1, int indx2);
void svPutLogicArrElem3Vec32(const svOpenArrayHandle d, const svLogicVec32* s,
int indx1, int indx2, int indx3);
/* canonical <-- actual */
void svGetBitArrElemVec32 (svBitVec32* d, const svOpenArrayHandle s,
int indx1, ...);
void svGetBitArrElem1Vec32(svBitVec32* d, const svOpenArrayHandle s, int indx1);
void svGetBitArrElem2Vec32(svBitVec32* d, const svOpenArrayHandle s, int indx1,
int indx2);
void svGetBitArrElem3Vec32(svBitVec32* d, const svOpenArrayHandle s,
int indx1, int indx2, int indx3);
void svGetLogicArrElemVec32 (svLogicVec32* d, const svOpenArrayHandle s,
int indx1, ...);
void svGetLogicArrElem1Vec32(svLogicVec32* d, const svOpenArrayHandle s,
int indx1);
void svGetLogicArrElem2Vec32(svLogicVec32* d, const svOpenArrayHandle s,
int indx1,
int indx2);
void svGetLogicArrElem3Vec32(svLogicVec32* d, const svOpenArrayHandle s,
int indx1, int indx2, int indx3);
svBit svGetBitArrElem (const svOpenArrayHandle s, int indx1, ...);
svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1);
svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
int indx3);
svLogic svGetLogicArrElem (const svOpenArrayHandle s, int indx1, ...);
svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1);
svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
int indx3);
void svPutLogicArrElem (const svOpenArrayHandle d, svLogic value, int indx1, ...);
void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1);
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1,
int indx2);
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1,
int indx2, int indx3);
void svPutBitArrElem (const svOpenArrayHandle d, svBit value, int indx1, ...);
void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1);
void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1,
int indx2);
void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1,
int indx2, int indx3);
/* Functions for working with DPI context functions */
/* Retrieve the active instance scope currently associated with the executing
imported function.
Unless a prior call to svSetScope has occurred, this is the scope of the
function’s declaration site, not call site.
Returns NULL if called from C code that is *not* an imported function. */
svScope svGetScope();
/* Set context for subsequent export function execution.
This function must be called before calling an export function, unless
the export function is called while executing an extern function. In that
case the export function shall inherit the scope of the surrounding extern
function. This is known as the "default scope".
The return is the previous active scope (as per svGetScope) */
svScope svSetScope(const svScope scope);
/* Gets the fully qualified name of a scope handle */
const char* svGetNameFromScope(const svScope);
/* Retrieve svScope to instance scope of an arbitrary function declaration.
* (can be either module, program, interface, or generate scope)
* The return value shall be NULL for unrecognized scope names.
*/
svScope svGetScopeFromName(const char* scopeName);
/* Store an arbitrary user data pointer for later retrieval by svGetUserData()
* The userKey is generated by the user. It must be guaranteed by the user to
* be unique from all other userKey’s for all unique data storage requirements
* It is recommended that the address of static functions or variables in the
* user’s C code be used as the userKey.
* It is illegal to pass in NULL values for either the scope or userData
* arguments. It is also an error to call svPutUserData() with an invalid
* svScope. This function returns -1 for all error cases, 0 upon success. It is
* suggested that userData values of 0 (NULL) not be used as otherwise it can
* be impossible to discern error status returns when calling svGetUserData()
*/
int svPutUserData(const svScope scope, void *userKey, void* userData);
/* Retrieve an arbitrary user data pointer that was previously
* stored by a call to svPutUserData(). See the comment above
* svPutUserData() for an explanation of userKey, as well as
* restrictions on NULL and illegal svScope and userKey values.
* This function returns NULL for all error cases, 0 upon success.
* This function also returns NULL in the event that a prior call
* to svPutUserData() was never made.
*/
void* svGetUserData(const svScope scope, void* userKey);
/* Returns the file and line number in the SV code from which the extern call
* was made. If this information available, returns TRUE and updates fileName
* and lineNumber to the appropriate values. Behavior is unpredictable if
* fileName or lineNumber are not appropriate pointers. If this information is
* not available return FALSE and contents of fileName and lineNumber not
* modified. Whether this information is available or not is implementation
* specific. Note that the string provided (if any) is owned by the SV
* implementation and is valid only until the next call to any SV function.
* Applications must not modify this string or free it
*/
int svGetCallerInfo(char **fileName, int *lineNumber);
/*
* Returns 1 if the current execution thread is in the disabled state.
* Disable protocol must be adhered to if in the disabled state.
*/
int svIsDisabledState();
/*
* Imported functions call this API function during disable processing to
* acknowledge that they are correctly participating in the DPI disable protocol.
* This function must be called before returning from an imported function that is
* in the disabled state.
*/
void svAckDisabledState();
Group

附录F 包含文件

链接
附录F 包含文件


F.2 源级兼容性包含文件svdpi_src.h

链接
附录F 包含文件
SystemVerilog 3.1a语言参考手册
F.2 源级兼容性包含文件svdpi_src.h
附录F 包含文件
Copy Code
/* macros for declaring variables to represent the SystemVerilog */
/* packed arrays of type bit or logic */
/* WIDTH= number of bits,NAME = name of a declared field/variable */
#define SV_BIT_PACKED_ARRAY(WIDTH, NAME)   /* actual definition goes here */
#define SV_LOGIC_PACKED_ARRAY(WIDTH, NAME) /* actual definition goes here */
Group

附录F 包含文件

链接
附录F 包含文件


附录G 包含外部语言代码

链接
主题
SystemVerilog 3.1a语言参考手册
附录G 包含外部语言代码
主题

This annex describes common guidelines for the inclusion of Foreign Language Code into a SystemVerilog application. This intention of these guidelines is to enable the redistribution of C binaries in shared object form.

Foreign Language Code is functionality that is included into SystemVerilog using the DPI Interface. As a result, all statements of this annex apply only to code included using this interface; code included by using other interfaces (e.g., PLI or VPI) is outside the scope of this document. Due to the nature of the DPI Interface, most Foreign Language Code is usually be created from C or C++ source code, although nothing precludes the creation of appropriate object code from other languages. This annex adheres to this rule, it’s content is independent from the actual language used.

In general, Foreign Language Code is provided in the form of object code compiled for the actual platform. The capability to include Foreign Language Code in object-code form shall be supported by all simulators as specified here. Overview

This annex defines how to:

  • specify the location of the corresponding files within the file system
  • specify the files to be loaded (in case of object code) or
  • provide the object code (as a shared library or archive)
Although this annex defines guidelines for a common inclusion methodology, it requires multiple implementations (usually two) of the corresponding facilities. This takes into account that multiple users can have different viewpoints and different requirements on the inclusion of Foreign Language Code.
  • A vendor that wants to provide his IP in form of Foreign Language Code often requires a self-contained method for the integration, which still permits an integration by a third party. This use-case is often covered by a bootstrap file approach.
  • A project team that specifies a common, standard set of Foreign Language code, might change the code depending on technology, selected cells, back-annotation data, and other items. This-use case is often covered by a set of tool switches, although it might also use the bootstrap file approach.
  • An user might want to switch between selections or provide additional code. This-use case is covered by providing a set of tool switches to define the corresponding information, although it might also use the bootstrap file approach.
NOTE—This annex defines a set of switch names to be used for a particular functionality. This is of informative nature; the actual naming of switches is not part of this standard. It might further not be possible to use certain character configurations in all operating systems or shells. Therefore any switch name defined within this document is a recommendation how to name a switch, but not a requirement of the language.

主题
主题
描述
G.1 Location independence
All pathnames specified within this annex are intended to be location-independent, which is accomplished by using the switch -sv_root. It can receive a single directory pathname as the value, which is then prepended to any relative pathname that has been specified. In absence of this switch, or when processing relative filenames before any -sv_root specification, the current working directory of the user shall be used as the default value.
G.2 Object code inclusion
Compiled object code is required for cases where the compilation and linking of source code is fully handled by the user; thus, the created object code only need be loaded to integrate the Foreign Language Code into a SystemVerilog application. All SystemVerilog applications shall support the integration of Foreign Language Code in object code form. Figure 7-1depicts the inclusion of object code and its relations to the various steps involved in this integration process.

Figure 7-1 — Inclusion of object code into a SystemVerilog application

Compiled object code can be specified by one of the following two methods:

  1. by an... more
链接
主题


G.1 Location independence

链接
附录G 包含外部语言代码
SystemVerilog 3.1a语言参考手册
G.1 Location independence
附录G 包含外部语言代码

All pathnames specified within this annex are intended to be location-independent, which is accomplished by using the switch -sv_root. It can receive a single directory pathname as the value, which is then prepended to any relative pathname that has been specified. In absence of this switch, or when processing relative filenames before any -sv_root specification, the current working directory of the user shall be used as the default value.

Group

附录G 包含外部语言代码

链接
附录G 包含外部语言代码


G.2 Object code inclusion

链接
附录G 包含外部语言代码, 主题
SystemVerilog 3.1a语言参考手册
G.2 Object code inclusion
附录G 包含外部语言代码 | 主题

Compiled object code is required for cases where the compilation and linking of source code is fully handled by the user; thus, the created object code only need be loaded to integrate the Foreign Language Code into a SystemVerilog application. All SystemVerilog applications shall support the integration of Foreign Language Code in object code form. Figure 7-1depicts the inclusion of object code and its relations to the various steps involved in this integration process.

Figure 7-1 — Inclusion of object code into a SystemVerilog application

Compiled object code can be specified by one of the following two methods:

  1. by an entry in a bootstrap file; see Annex G.2.1 for more details on this file and its content. Its location shall be specified with one instance of the switch -sv_liblist pathname. This switch can be used multiple times to define the usage of multiple bootstrap files.
  2. by specifying the file with one instance of the switch -sv_lib pathname_without_extension (i.e., the filename shall be specified without the platform specific extension). The SystemVerilog application is responsible for appending the appropriate extension for the actual platform. This switch can be used multiple times to define multiple libraries holding object code.
Both methods shall be provided and made available concurrently, to permit any mixture of their usage. Every location can be an absolute pathname or a relative pathname, where the value of the switch -sv_root is used to identify an appropriate prefix for relative pathnames (see Annex G.1 for more details on forming pathnames).

The following conditions also apply.

  • The compiled object code itself shall be provided in form of a shared library having the appropriate extension for the actual platform. NOTE—Shared libraries use, for example, .so for Solaris and .sl for HP-UX; other operating systems might use different extensions. In any case, the SystemVerilog application needs to identify the appropriate extension.
  • The provider of the compiled code is responsible for any external references specified within these objects. Appropriate data needs to be provided to resolve all open dependencies with the correct information.
  • The provider of the compiled code shall avoid interferences with other software and ensure the appropriate software version is taken (e.g., in cases where two versions of the same library are referenced). Similar problems can arise when there are dependencies on the expected runtime environment in the compiled object code (e.g., in cases where C++ global objects or static initializers are used).
  • The SystemVerilog application need only load object code within a shared library that is referenced by the SystemVerilog code or by registration functions; loading of additional functions included within a shared library can interfere with other parts.
In case of multiple occurrences of the same file (files having the same pathname or which can easily be identified as being identical; e.g., by comparing the inodes of the files to detect cases where links are used to refer the same file), the above order also identifies the precedence of loading; a file located by method 1) shall override files specified by method 2).

All compiled object code need to be loaded in the specification order similarly to the above scheme; first the content of the bootstrap file is processed starting with the first line, then the set of -sv_lib switches is processed in order of their occurrence. Any library shall only be loaded once.

Group

附录G 包含外部语言代码

主题
主题
描述
G.2.1 Bootstrap file
The object code bootstrap file has the following syntax.
  1. The first line contains the string #!SV_LIBRARIES.
  2. An arbitrary amount of entries follow, one entry per line, where every entry holds exactly one library location. Each entry consists only of the pathname_without_extension of the object code file to be loaded and can be surrounded by an arbitrary number of blanks; at least one blank shall precede the entry in the line. The value pathname_without_extension is equivalent to the value of the switch -sv_lib.
  3. Any amount of comment lines can be interspersed between the entry lines; a comment line starts with the... more
G.2.2 Examples
1) If the pathname root has been set by the switch -sv_root to /home/user and the following object files need to be included:
/home/user/myclibs/lib1.so
/home/user/myclibs/lib3.so
/home/user/proj1/clibs/lib4.so
/home/user/proj3/clibs/lib2.so
then use either of the methods in Example 7-1. Both methods are equivalent.

Example 7-1 — Using a simple bootstrap file or a switch list

2) If the current working directory is /home/user, using the series of switches shown in Example 7-2 (left column) result in loading the following files (right column).

Example 7-2 — Using a combination of -sv_lib and -sv_root switches

3) Further, using the set of switches and contents of... more

链接
附录G 包含外部语言代码, 主题


G.2.1 Bootstrap file

链接
G.2 Object code inclusion
SystemVerilog 3.1a语言参考手册
G.2.1 Bootstrap file
G.2 Object code inclusion

The object code bootstrap file has the following syntax.

  1. The first line contains the string #!SV_LIBRARIES.
  2. An arbitrary amount of entries follow, one entry per line, where every entry holds exactly one library location. Each entry consists only of the pathname_without_extension of the object code file to be loaded and can be surrounded by an arbitrary number of blanks; at least one blank shall precede the entry in the line. The value pathname_without_extension is equivalent to the value of the switch -sv_lib.
  3. Any amount of comment lines can be interspersed between the entry lines; a comment line starts with the character # after an arbitrary (including zero) amount of blanks and is terminated with a newline.

Group

G.2 Object code inclusion

链接
G.2 Object code inclusion


G.2.2 Examples

链接
G.2 Object code inclusion
SystemVerilog 3.1a语言参考手册
G.2.2 Examples
G.2 Object code inclusion

1) If the pathname root has been set by the switch -sv_root to /home/user and the following object files need to be included:

/home/user/myclibs/lib1.so

/home/user/myclibs/lib3.so

/home/user/proj1/clibs/lib4.so

/home/user/proj3/clibs/lib2.so

then use either of the methods in Example 7-1. Both methods are equivalent.

Example 7-1 — Using a simple bootstrap file or a switch list

2) If the current working directory is /home/user, using the series of switches shown in Example 7-2 (left column) result in loading the following files (right column).

Example 7-2 — Using a combination of -sv_lib and -sv_root switches

3) Further, using the set of switches and contents of bootstrap files shown in Example 7-3:

Example 7-3 — Mixing -sv_root and bootstrap files

results in loading the following files:

/home/usr1/lib1.ext

/home/usr1/lib2.ext

/home/usr2/lib3.ext

/common/libx.ext

/home/usr2/lib5.ext

where ext stands for the actual extension of the corresponding file.

Group

G.2 Object code inclusion

链接
G.2 Object code inclusion


附录H 并发断言的形式语义

链接
主题
SystemVerilog 3.1a语言参考手册
附录H 并发断言的形式语义
主题
主题
主题 | 描述
H.1 简介 | This appendix presents a formal semantics for SystemVerilog concurrent assertions. Immediate assertions and coverage statements are not discussed here. Throughout this appendix, “assertion” is used to mean “concurrent assertion”. The semantics is defined by a relation that determines when a finite or infinite word (i.e., trace) satisfies an assertion. Intuitively, such a word represents a sequence of valuations of SystemVerilog variables sampled at the finest relevant granularity of time (e.g., at the granularity of simulator cycles). The process by which such words are produced is closely related to the SystemVerilog scheduling semantics and is not defined here. In this appendix,... more
H.2 抽象语法 |
H.3 语义 | Let P be the set of atomic propositions. The semantics of assertions and properties is defined via a relation of satisfaction by empty, finite, and infinite words over the alphabet Σ = 2P U {T, ⊥}. Such a word is an empty, finite, or infinite sequence of elements of Σ. The number of elements in the sequence is called the length of the word, and the length of word w is denoted |w|. Note that |w| is either a non-negative integer or infinity. The sequence elements of a word are called its letters and are assumed to be indexed consecutively... more
H.4 Extended Expressions | This section describes the semantics of several constructs that are used like expressions, but whose meaning at a point in a word can depend both on the letter at that point and on previous letters in the word. By abuse of notation, the meanings of these extended expressions are defined for letters denoted “w j” even” though they depend also on letters w i for i < j. The reason for this abuse is to make clear the way these definitions should be used in combination with those in preceding sections.
H.5 Recursive Properties | This section defines the neutral semantics of instances of recursive properties in terms of the neutral semantics of instances of non-recursive properties. The latter can be expanded to properties in the abstract syntax by appropriate substitutions, and so their semantics is assumed to be understood. According to Restriction 1 in Section 17.11.3, it is understood below that the negation operator not cannot be applied to any property expression that instantiates a recursive property. Restriction 2 in Section 17.11.3 is not represented here because disable iff is treated as a general property-building operator in this appendix. A precise version of Restriction... more
链接
主题


H.1 简介

链接
附录H 并发断言的形式语义
SystemVerilog 3.1a语言参考手册
H.1 简介
附录H 并发断言的形式语义

This appendix presents a formal semantics for SystemVerilog concurrent assertions. Immediate assertions and coverage statements are not discussed here. Throughout this appendix, “assertion” is used to mean “concurrent assertion”. The semantics is defined by a relation that determines when a finite or infinite word (i.e., trace) satisfies an assertion. Intuitively, such a word represents a sequence of valuations of SystemVerilog variables sampled at the finest relevant granularity of time (e.g., at the granularity of simulator cycles). The process by which such words are produced is closely related to the SystemVerilog scheduling semantics and is not defined here. In this appendix, words are assumed to be sequences of elements, each element being either a set of atomic propositions or one of two special symbols used as placeholders when extending finite words. The atomic propositions are not further defined. The meaning of satisfaction of a SystemVerilog boolean expression by a set of atomic propositions is assumed to be understood.

The semantics is based on an abstract syntax for SystemVerilog assertions. There are several advantages to using the abstract syntax rather than the full SystemVerilog Assertions BNF.

  1. The abstract syntax facilitates separation of derived operators from basic operators. The satisfaction relation is defined explicitly only for assertions built from basic operators.
  2. The abstract syntax avoids reliance on operator precedence, associativity, and auxiliary rules for resolving syntactic and semantic ambiguities.
  3. The abstract syntax simplifies the assertion language by eliminating some features that tend to encumber the definition of the formal semantics.
    • The abstract syntax eliminates local variable declarations. The semantics of local variables is written with implicit types.
    • The abstract syntax eliminates instantiation of sequences and properties. The semantics of an assertion with an instance of a sequence or non-recursive property is the same as the semantics of a related assertion obtained by replacing the sequence or non-recursive property instance with an explicitly written sequence or property. The explicit sequence or property is obtained from the body of the associated declaration by substituting actual arguments for formal arguments. A separate section defines the semantics of instances of recursive properties in terms of the semantics of instances of nonrecursive properties.
    • The abstract syntax does not allow implicit clocks. Clocking event controls must be applied explicitly in the abstract syntax.
    • The abstract syntax does not allow explicit procedural enabling conditions for assertions. Procedural enabling conditions are utilized in the semantics definition (see Subsection 3.3.1), but the method for extracting such conditions is not defined in this appendix.
  4. The abstract syntax eliminates the distinction between property_expr and property_spec from the full BNF. Without the distinction, disable iff is a general, nestable property-building operator, while in the full BNF disable iff can be attached only at the top level of a property. Semantically, there is no need for this restriction on the placement of disable iff. The abstract syntax thus eliminates an unnecessary semantic layer while maintaining the simple inductive form for the definition of the semantics of properties. As a result, semantics are given for some properties that do not correspond to forms from the full BNF, but this does not degrade the definitions for the properties that do correspond to forms from the full BNF.

In order to use this appendix to determine the semantics of a SystemVerilog assertion, the assertion must first be transformed into an enabling condition together with an assertion in the abstract syntax. For assertions that do not involve recursive properties, this transformation involves eliminating sequence and non-recursive property instances by substitution, eliminating local variable declarations, introducing parentheses, determining the enabling condition, determining implicit or inferred clocking event controls, and eliminating redundant clocking event controls. For example, the following SystemVerilog assertion

Copy Code
sequence s(x,y); x ##1 y; endsequence
sequence t(z); @(c) z[*1:2] ##1 B; endsequence
always @(c) if (b) assert property (s(A,B) |=> t(A));

is transformed into the enabling condition “b” together with the assertion

Copy Code
always @(c) assert property ((A ##1 B) |=> (A[*1:2] ##1 B))

in the abstract syntax.

If the SystemVerilog assertion involves instances of recursive properties, then the transformation replaces these instances with placeholder functions of the actual arguments. The semantics of an instance of a recursive property is defined in terms of associated non-recursive properties in Section H.5. Once the semantics of the recursive property instances are understood, the placeholder functions are treated as properties with these semantics. Then the ordinary definitions can be applied to the transformed assertion in the abstract syntax together with placeholder functions.

Group

附录H 并发断言的形式语义

链接
附录H 并发断言的形式语义


H.2 抽象语法

链接
附录H 并发断言的形式语义, 主题
SystemVerilog 3.1a语言参考手册
H.2 抽象语法
附录H 并发断言的形式语义 | 主题
Group

附录H 并发断言的形式语义

主题
主题 | 描述
H.2.1 Abstract grammars | In the following abstract grammars, b denotes a boolean expression, v denotes a local variable name, and e denotes an expression. The abstract grammar for unclocked sequences is R
H.2.2 Notations | Throughout the sequel, the following notational conventions will be used: b, c denote boolean expressions; v denotes a local variable name; e denotes an expression; R, R1, R2 denote unclocked sequences; S, S1, S2 denote clocked sequences; P, P1, P2 denote unclocked properties; Q denotes a clocked property; A denotes an assertion; i, j, k, m, n denote non-negative integer constants.
H.2.3 Derived forms | Internal parentheses are omitted in compositions of the (associative) operators ##1 and or.
链接
附录H 并发断言的形式语义, 主题


H.2.1 Abstract grammars

链接
H.2 抽象语法
SystemVerilog 3.1a语言参考手册
H.2.1 Abstract grammars
H.2 抽象语法

In the following abstract grammars, b denotes a boolean expression, v denotes a local variable name, and e denotes an expression.

The abstract grammar for unclocked sequences is R

Copy Code
R ::= b // "boolean expression" form
| ( 1, v = e ) // "local variable sampling" form
| ( R ) // "parenthesis" form
| ( R ##1 R ) // "concatenation" form
| ( R ##0 R ) // "fusion" form
| ( R or R ) // "or" form
| ( R intersect R ) // "intersect" form
| first_match ( R ) // "first match" form
| R [ *0 ] // "null repetition" form
| R [ *1:$ ] // "unbounded repetition" form

The abstract grammar for clocked sequences is

Copy Code
S ::= @(b) R // "clock" form
| ( S ) // "parenthesized" form
| ( S ## S ) // "concatenation" form

The abstract grammar for unclocked properties is

Copy Code
P ::= R // "sequence" form
| ( P ) // "parenthesis" form
| not P // "negation" form
| ( P or P ) // "or" form
| ( P and P ) // "and" form
| ( R |-> P ) // "implication" form
| disable iff ( b ) P // "reset" form

Each instance of R in this production must be a non-degenerate unclocked sequence. In the “sequence” form, R must not be tightly satisfied by the empty word. See H.3.2 and H.3.5 for the definitions of non-degeneracy and tight satisfaction.

The abstract grammar for clocked properties is

Copy Code
Q ::= @( b ) P // "clock" form
| S // "sequence" form
| ( Q ) // "parenthesis" form
| not Q // "negation" form
| ( Q or Q ) // "or" form
| ( Q and Q ) // "and" form
| ( S |-> Q ) // "implication" form
| disable iff ( b ) Q // "reset" form

Each instance of S in this production must be a non-degenerate clocked sequence. In the “sequence” form, S must not be tightly satisfied by the empty word. See H.3.2 and H.3.5 for the definitions of non-degeneracy and tight satisfaction.

The abstract grammar for assertions is

Copy Code
A ::= always assert property Q // "always" form
| always @( b ) assert property P // "always with clock" form
| initial assert property Q // "initial" form
| initial @( b ) assert property P // "initial with clock" form
Group

H.2 抽象语法

链接
H.2 抽象语法


H.2.2 Notations

链接
H.2 抽象语法
SystemVerilog 3.1a语言参考手册
H.2.2 Notations
H.2 抽象语法

Throughout the sequel, the following notational conventions will be used: b, c denote boolean expressions; v denotes a local variable name; e denotes an expression; R, R1, R2 denote unclocked sequences; S, S1, S2 denote clocked sequences; P, P1, P2 denote unclocked properties; Q denotes a clocked property; A denotes an assertion; i, j, k, m, n denote non-negative integer constants.

Group

H.2 抽象语法

链接
H.2 抽象语法


H.2.3 Derived forms

链接
H.2 抽象语法, 主题
SystemVerilog 3.1a语言参考手册
H.2.3 Derived forms
H.2 抽象语法 | 主题

Internal parentheses are omitted in compositions of the (associative) operators ##1 and or.

Group

H.2 抽象语法

主题
主题 | 描述
H.2.3.1 Derived non-overlapping implication operator | ? ( R1 |=> P ) (( R1 ##1 1 ) |-> P ) . ? ( S1 |=> Q ) ((S1 ##1 @(1) 1 ) |-> Q ) .
H.2.3.2 Derived consecutive repetition operators | ? Let m > 0. R [*m] ( R ##1 R ##1 ... ##1 R ) // m copies of R . ? R [*0:$] ( R [*0] or R [*1:$] ) . ? Let m < n. R [*m:n] ( R [*m] or R [*m +1] or ... or R [*n]) . ? Let m > 1. R [*m:$] ( R [*m – 1] ##1 R [*1:$]) .
H.2.3.3 Derived delay and concatenation operators | Let m < n. ? ( ##[m:n] R ) (1[*m:n] ##1 R ) . ? ( ##[m:$] R ) (1[*m:$] ##1 R ) . ? ( ##m R ) (1[*m] ##1 R ) . ? Let m > 0. ( R1 ##[m:n] R2 ) ( R1 ##1 1[*m – 1:n – 1] ##1 R2 ) . ? Let m > 0. ( R1 ##[m:$] R2 ) ( R1 ##1 1[*m – 1:$] ##1 R2 ) . ? Let m > 1. ( R1 ##m R2 ) ( R1 ##1 1[*m – 1] ##1 R2 ) . ? ( R1 ##[0:0]... more
H.2.3.4 Derived non-consecutive repetition operators | Let m < n. ? b [->m:n] ( !b [*0:$] ##1 b )[*m:n] . ? b [->m:$] ( !b [*0:$] ##1 b )[*m:$] . ? b [->m] ( !b [*0:$] ##1 b)[*m] . ? b [=m:n] ( b [->m:n] ##1 !b [*0:$] ) . ? b [=m:$] ( b [->m:$] ##1 !b [*0:$] ) . ? b [=m] ( b [->m] ##1 !b [*0:$] ) .
H.2.3.5 Other derived operators | ? ( R1 and R2 ) ((( R1 ##1 1[*0:$]) intersect R2 ) or ( R1 intersect ( R2 ##1 1[*0:$]))) . ? ( R1 within R2 ) ((1[*0:$] ##1 R1 ##1 1[*0:$]) intersect R2 ) . ? ( b throughout R ) (( b [*0:$]) intersect R ) . ? ( R, v = e ) ( R ##0 ( 1, v = e )) . ? ( R, v1 = e1,... ,vk = ek) (( R, v1 = e1) ##0 ( 1, v2 = e2 ,... , vk = ek )) for k > 1 ? ( if... more
链接
H.2 抽象语法, 主题


H.2.3.1 Derived non-overlapping implication operator

链接
H.2.3 Derived forms
SystemVerilog 3.1a语言参考手册
H.2.3.1 Derived non-overlapping implication operator
H.2.3 Derived forms

? ( R1 |=> P ) (( R1 ##1 1 ) |-> P ) .

? ( S1 |=> Q ) ((S1 ##1 @(1) 1 ) |-> Q ) .

Group

H.2.3 Derived forms

链接
H.2.3 Derived forms


H.2.3.2 Derived consecutive repetition operators

链接
H.2.3 Derived forms
SystemVerilog 3.1a语言参考手册
H.2.3.2 Derived consecutive repetition operators
H.2.3 Derived forms

? Let m > 0. R [*m] ( R ##1 R ##1 ... ##1 R ) // m copies of R .

? R [*0:$] ( R [*0] or R [*1:$] ) .

? Let m < n. R [*m:n] ( R [*m] or R [*m +1] or ... or R [*n]) .

? Let m > 1. R [*m:$] ( R [*m – 1] ##1 R [*1:$]) .

Group

H.2.3 Derived forms

链接
H.2.3 Derived forms


H.2.3.3 Derived delay and concatenation operators

链接
H.2.3 Derived forms
SystemVerilog 3.1a语言参考手册
H.2.3.3 Derived delay and concatenation operators
H.2.3 Derived forms

Let m < n.

? ( ##[m:n] R ) (1[*m:n] ##1 R ) .

? ( ##[m:$] R ) (1[*m:$] ##1 R ) .

? ( ##m R ) (1[*m] ##1 R ) .

? Let m > 0. ( R1 ##[m:n] R2 ) ( R1 ##1 1[*m – 1:n – 1] ##1 R2 ) .

? Let m > 0. ( R1 ##[m:$] R2 ) ( R1 ##1 1[*m – 1:$] ##1 R2 ) .

? Let m > 1. ( R1 ##m R2 ) ( R1 ##1 1[*m – 1] ##1 R2 ) .

? ( R1 ##[0:0] R2 ) ( R1 ##0 R2 ) .

? Let n > 0. ( R1 ##[0:n] R2 ) (( R1 ##0 R2 ) or ( R1 ##[1:n] R2 )) .

? ( R1 ##[0:$] R2 ) (( R1 ##0 R2 ) or ( R1 ##[1:$] R2 )) .

Group

H.2.3 Derived forms

链接
H.2.3 Derived forms


H.2.3.4 Derived non-consecutive repetition operators

链接
H.2.3 Derived forms
SystemVerilog 3.1a语言参考手册
H.2.3.4 Derived non-consecutive repetition operators
H.2.3 Derived forms

Let m < n.

? b [->m:n] ( !b [*0:$] ##1 b )[*m:n] .

? b [->m:$] ( !b [*0:$] ##1 b )[*m:$] .

? b [->m] ( !b [*0:$] ##1 b)[*m] .

? b [=m:n] ( b [->m:n] ##1 !b [*0:$] ) .

? b [=m:$] ( b [->m:$] ##1 !b [*0:$] ) .

? b [=m] ( b [->m] ##1 !b [*0:$] ) .

Group

H.2.3 Derived forms

链接
H.2.3 Derived forms


H.2.3.5 Other derived operators

链接
H.2.3 Derived forms
SystemVerilog 3.1a语言参考手册
H.2.3.5 Other derived operators
H.2.3 Derived forms

? ( R1 and R2 )

((( R1 ##1 1[*0:$]) intersect R2 ) or ( R1 intersect ( R2 ##1 1[*0:$]))) .

? ( R1 within R2 ) ((1[*0:$] ##1 R1 ##1 1[*0:$]) intersect R2 ) .

? ( b throughout R ) (( b [*0:$]) intersect R ) .

? ( R, v = e ) ( R ##0 ( 1, v = e )) .

? ( R, v1 = e1,... ,vk = ek) (( R, v1 = e1) ##0 ( 1, v2 = e2 ,... , vk = ek )) for k > 1

? ( if ( b ) P ) ( b |-> P )

? ( if ( b ) P1 else P2 ) ( ( b |-> P1 ) and ( !b |-> P2 ) )

Group

H.2.3 Derived forms

链接
H.2.3 Derived forms


H.3 语义

链接
附录H 并发断言的形式语义, 主题
SystemVerilog 3.1a语言参考手册
H.3 语义
附录H 并发断言的形式语义 | 主题

Let P be the set of atomic propositions.

The semantics of assertions and properties is defined via a relation of satisfaction by empty, finite, and infinite

words over the alphabet Σ = 2P U {T, ⊥}. Such a word is an empty, finite, or infinite sequence of elements of Σ.

The number of elements in the sequence is called the length of the word, and the length of word w is denoted

|w|. Note that |w| is either a non-negative integer or infinity.

The sequence elements of a word are called its letters and are assumed to be indexed consecutively beginning

at zero. If |w| > 0, then the first letter of w is denoted w0; if |w| > 1, then the second letter of w is denoted w1; and

so forth. w i.. denotes the word obtained from w by deleting its first i letters. If i < |w|, then w i.. = w iw i+1.... If

i > |w|, then w i.. is empty.

If i < j, then w i, j denotes the finite word obtained from w by deleting its first i letters and also deleting all letters

after its ( j + 1)st. If i < j < |w|, then w i, j = w iw i+1...w j.

If w is a word over Σ, define w to be the word obtained from w by interchanging T with ⊥. More precisely,

w i = T if w i = ⊥ ; w i = ⊥ if w i = T; and w i = w i if w i is an element in 2P.

The semantics of clocked sequences and properties is defined in terms of the semantics of unclocked

sequences and properties. See the subsection on rewrite rules for clocks below.

It is assumed that the satisfaction relation ζ b is defined for elements ζ in 2P and boolean expressions b. For

any boolean expression b, define

T b and ⊥ b .

Group

附录H 并发断言的形式语义

主题
主题 | 描述
H.3.1 Rewrite rules for clocks | The semantics of clocked sequences and properties is defined in terms of the semantics of unclocked sequences and properties. The following rewrite rules define the transformation of a clocked sequence or property into an unclocked version that is equivalent for the purposes of defining the satisfaction relation. In this transformation, it is required that the conditions in event controls not be dependent upon any local variables. ? @(c) b ( !c [*0:$] ##1 c & b ) . ? @(c)( 1, v = e ) ( @(c) 1 ##0 ( 1, v = e )) . ? @(c)( P )... more
H.3.2 Tight satisfaction without local variables | Tight satisfaction is denoted by . For unclocked sequences without local variables, tight satisfaction is defined as follows. w, x, y, z denote finite words over Σ. ? w b iff |w| = 1 and w0 b . ? w ( R ) iff w R . ? w ( R1 ##1 R2 ) iff there exist x, y such that w = xy and x R1 and y R2 . ? w ( R1 ##0 R2 ) iff there exist x, y, z such that w = xyz and |y| = 1, and xy R1 and yz R2 .... more
H.3.3 Satisfaction without local variables |
H.3.4 Local variable flow | This subsection defines inductively how local variable names flow through unclocked sequences. Below, “U” denotes set union, “ ” denotes set intersection, “–” denotes set difference, and “{}” denotes the empty set. The function “sample” takes a sequence as input and returns a set of local variable names as output. Intuitively, this function returns the set of local variable names that are sampled (i.e., assigned) in the sequence. The function “block” takes a sequence as input and returns a set of local variable names as output. Intuitively, this function returns the set of local variable names that are blocked from... more
H.3.5 Tight satisfaction with local variables | A local variable context is a function that assigns values to local variable names. If L is a local variable context, then dom(L) denotes the set of local variable names that are in the domain of L. If D dom(L), then L|D means the local variable context obtained from L by restricting its domain to D. In the presence of local variables, tight satisfaction is a four-way relation defining when a finite word w over the alphabet Σ together with an input local variable context L0 satisfies an unclocked sequence R and yields an output local variable context L1. This... more
H.3.6 Satisfaction with local variables |
链接
附录H 并发断言的形式语义, 主题


H.3.1 Rewrite rules for clocks

链接
H.3 语义
SystemVerilog 3.1a语言参考手册
H.3.1 Rewrite rules for clocks
H.3 语义

The semantics of clocked sequences and properties is defined in terms of the semantics of unclocked

sequences and properties. The following rewrite rules define the transformation of a clocked sequence or property

into an unclocked version that is equivalent for the purposes of defining the satisfaction relation. In this

transformation, it is required that the conditions in event controls not be dependent upon any local variables.

? @(c) b ( !c [*0:$] ##1 c & b ) .

? @(c)( 1, v = e ) ( @(c) 1 ##0 ( 1, v = e )) .

? @(c)( P ) ( @(c) P ).

? @(c)( R1 ##1 R2 ) ( @(c) R1 ##1 @(c) R2 ) .

? @(c)( R1 ##0 R2 ) ( @(c) R1 ##0 @(c) R2 ) .

? @(c)( R1 or R2 ) ( @(c) R1 or @(c) R2 ) .

? @(c)( R1 intersect R2 ) ( @(c) R1 intersect @(c) R2 ) .

? @(c) first_match ( R ) first_match ( @(c) R ) .

? @(c) R [*0] ( @(c) R )[*0] .

? @(c) R [*1:$] ( @(c) R )[*1:$] .

? @(c) disable iff ( b ) P disable iff ( b ) @(c) P .

? @(c) not P not @(c) P.

? @(c) ( R |-> P ) ( @(c) R |-> @(c) P ) .

? @(c) ( P1 or P2 ) ( @(c) P1 or @(c) P2 ).

? @(c) ( P1 and P2 ) ( @(c) P1 and @(c) P2 ).

Group

H.3 语义

链接
H.3 语义


H.3.2 Tight satisfaction without local variables

链接
H.3 语义
SystemVerilog 3.1a语言参考手册
H.3.2 Tight satisfaction without local variables
H.3 语义

Tight satisfaction is denoted by . For unclocked sequences without local variables, tight satisfaction is

defined as follows. w, x, y, z denote finite words over Σ.

? w b iff |w| = 1 and w0 b .

? w ( R ) iff w R .

? w ( R1 ##1 R2 ) iff there exist x, y such that w = xy and x R1 and y R2 .

? w ( R1 ##0 R2 ) iff there exist x, y, z such that w = xyz and |y| = 1, and xy R1 and yz R2 .

? w ( R1 or R2 ) iff either w R1 or w R2 .

? w ( R1 intersect R2 ) iff both w R1 and w R2 .

? w first_match ( R ) iff both

— w R and

— if there exist x, y such that w = xy and x R, then y is empty.

? w R [*0] iff |w| = 0.

? w R [*1:$] iff there exist words w1, w2,..., wj ( j > 1) such that w = w1w2...wj and for every i such that

1 < i < j, wi R .

If S is a clocked sequence, then w S iff w S’, where S’ is the unclocked sequence that results from S by

applying the rewrite rules.

An unclocked sequence R is non-degenerate iff there exists a non-empty finite word w over Σ such that

w R. A clocked sequence S is non-degenerate iff the unclocked sequence S’ that results from S by applying

the rewrite rules is non-degenerate.

Group

H.3 语义

链接
H.3 语义


H.3.3 Satisfaction without local variables

链接
H.3 语义, 主题
SystemVerilog 3.1a语言参考手册
H.3.3 Satisfaction without local variables
H.3 语义 | 主题
Group

H.3 语义

主题
主题 | 描述
H.3.3.1 Neutral satisfaction | w denotes a non-empty finite or infinite word over Σ. Assume that all properties, sequences, and unclocked property fragments do not involve local variables. Neutral satisfaction of assertions: For the definition of neutral satisfaction of assertions, b denotes the boolean expression representing the enabling condition for the assertion. Intuitively, b is derived from the conditions in the context of a procedural assertion, while b is “1” for a declarative assertion. ? w, b always @(c) assert property P iff for every 0 < i < |w| such that w i c and w i b, w i.. @(c) P. ?... more
H.3.3.2 Weak and strong satisfaction by finite words | This subsection defines weak and strong satisfaction, denoted – and + (respectively) of an assertion A by a finite (possibly empty) word w over Σ. These relations are defined in terms of the relation of neutral satisfaction by infinite words as follows: ? w – A iff w Tω A. ? w + A iff w⊥ω A. A tool checking for satisfaction of A by the finite word w should return: ? “holds strongly” if w + A. ? “fails” if w A. ? “holds (but does not hold strongly)” if w A and w + A. ? “pending” if... more
链接
H.3 语义, 主题


H.3.3.1 Neutral satisfaction

链接
H.3.3 Satisfaction without local variables
SystemVerilog 3.1a语言参考手册
H.3.3.1 Neutral satisfaction
H.3.3 Satisfaction without local variables

w denotes a non-empty finite or infinite word over Σ. Assume that all properties, sequences, and unclocked

property fragments do not involve local variables.

Neutral satisfaction of assertions:

For the definition of neutral satisfaction of assertions, b denotes the boolean expression representing the

enabling condition for the assertion. Intuitively, b is derived from the conditions in the context of a procedural

assertion, while b is “1” for a declarative assertion.

? w, b always @(c) assert property P iff for every 0 < i < |w| such that w i c and w i b,

w i.. @(c) P.

? w, b always assert property Q iff for every 0 < i < |w|, if w i b then w i.. Q .

? w, b initial @(c) assert property P iff for every 0 < i < |w| such that w 0, i !c [*0:$] ##1 c and

w i b, w i.. @(c) P .

? w, b initial assert property Q iff (if w 0 b then w Q ) .

Neutral satisfaction of properties:

? w ( P ) iff w P.

? w Q iff w Q’, where Q’ is the unclocked property that results from Q by applying the rewrite rules.

? w disable iff (b) P iff either w P or there exists 0 < k < |w| such that w k b and

w 0, k–1 Tω P. Here, w 0, –1 denotes the empty word.

? w not P iff w P.

? w R iff there exists 0 < j < |w| such that w 0, j R .

? w ( R |-> P ) iff for every 0 < j < |w| such that w 0, j R, w j.. P .

? w ( P1 or P2 ) iff w P1 or w P2.

? w ( P1 and P2 ) iff w P1 and w P2.

Remark: Since w is non-empty, it can be proved that w not b iff w !b.

Group

H.3.3 Satisfaction without local variables

链接
H.3.3 Satisfaction without local variables


H.3.3.2 Weak and strong satisfaction by finite words

链接
H.3.3 Satisfaction without local variables
SystemVerilog 3.1a语言参考手册
H.3.3.2 Weak and strong satisfaction by finite words
H.3.3 Satisfaction without local variables

This subsection defines weak and strong satisfaction, denoted – and + (respectively) of an assertion A by

a finite (possibly empty) word w over Σ. These relations are defined in terms of the relation of neutral satisfaction

by infinite words as follows:

? w – A iff w Tω A.

? w + A iff w⊥ω A.

A tool checking for satisfaction of A by the finite word w should return:

? “holds strongly” if w + A.

? “fails” if w A.

? “holds (but does not hold strongly)” if w A and w + A.

? “pending” if w - A and w A.

Group

H.3.3 Satisfaction without local variables

链接
H.3.3 Satisfaction without local variables


H.3.4 Local variable flow

链接
H.3 语义
SystemVerilog 3.1a语言参考手册
H.3.4 Local variable flow
H.3 语义

This subsection defines inductively how local variable names flow through unclocked sequences. Below, “U”

denotes set union, “ ” denotes set intersection, “–” denotes set difference, and “{}” denotes the empty set.

The function “sample” takes a sequence as input and returns a set of local variable names as output. Intuitively,

this function returns the set of local variable names that are sampled (i.e., assigned) in the sequence.

The function “block” takes a sequence as input and returns a set of local variable names as output. Intuitively,

this function returns the set of local variable names that are blocked from flowing out of the sequence.

The function “flow” takes a set X of local variable names and a sequence as input and returns a set of local variable

names as output. Intuitively, this function returns the set of local variable names that flow out of the

sequence given the set X of local variable names that flow into the sequence.

The function “sample” is defined by

? sample (b) = {} .

? sample (( 1, v = e )) = {v} .

? sample (( R )) = sample (R) .

? sample (( R1 ##1 R2 )) = sample (R1) U sample (R2) .

? sample (( R1 ##0 R2 )) = sample (R1) U sample (R2) .

? sample (( R1 or R2 )) = sample (R1) U sample (R2) .

? sample (( R1 intersect R2 )) = sample (R1) U sample (R2) .

? sample (first_match ( R )) = sample (R) .

? sample (R [*0]) = {} .

? sample (R [*1:$]) = sample (R) .

The function “block” is defined by

? block (b) = {} .

? block (( 1, v = e )) = {} .

? block (( R )) = block (R) .

? block (( R1 ##1 R2 )) = (block (R1) – flow ({}, R2)) U block (R2) .

? block (( R1 ##0 R2 )) = (block (R1) – flow ({}, R2)) U block (R2) .

? block (( R1 or R2 )) = block (R1) U block (R2) .

? block (( R1 intersect R2 )) = block (R1) U block (R2) U ( sample (R1) sample (R2)) .

? block (first_match ( R )) = block (R) .

? block (R [*0]) = {} .

? block (R [*1:$]) = block (R) .

The function “flow” is defined by

? flow (X, b) = X .

? flow (X, ( 1, v = e )) = X U {v} .

? flow (X, ( R )) = flow (X, R) .

? flow (X, ( R1 ##1 R2 )) = flow ( flow (X, R1), R2) .

? flow (X, ( R1 ##0 R2 )) = flow ( flow (X, R1), R2) .

? flow (X, ( R1 or R2 )) = flow (X, R1) flow (X, R2) .

? flow (X, ( R1 intersect R2 )) = ( flow (X, R1) U flow (X, R2)) – block (( R1 intersect R2 )) .

? flow (X, first_match(R)) = flow (X, R) .

? flow (X, R [*0]) = X .

? flow (X, R [*1:$]) = flow (X, R) .

Remark: It can be proved that flow (X, R) = (X U flow ({}, R)) – block (R) . It follows that flow ({}, R) and block

(R) are disjoint. It can also be proved that flow ({}, R) is a subset of sample (R).

Group

H.3 语义

链接
H.3 语义


H.3.5 Tight satisfaction with local variables

链接
H.3 语义
SystemVerilog 3.1a语言参考手册
H.3.5 Tight satisfaction with local variables
H.3 语义

A local variable context is a function that assigns values to local variable names. If L is a local variable context,

then dom(L) denotes the set of local variable names that are in the domain of L. If D dom(L), then L|D

means the local variable context obtained from L by restricting its domain to D.

In the presence of local variables, tight satisfaction is a four-way relation defining when a finite word w over

the alphabet Σ together with an input local variable context L0 satisfies an unclocked sequence R and yields an

output local variable context L1. This relation is denoted

w, L0, L1 R .

and is defined below. It can be proved that the definition guarantees that w, L0, L1 R implies

dom(L1) = flow (dom(L0), R) .

? w, L0, L1 ( 1, v = e ) iff |w| = 1 and w 0 1 and L1 = {(v, e[L0, w 0])} U L0|D , where e[L0, w 0] denotes the

value obtained from e by evaluating first according to L0 and second according to w 0 and D = dom(L0) –

{v}. In case w 0 {T, }, e[L0,T] and e[L0, ] can be any constant values of the type of e.

? w, L0, L1 b iff |w| = 1 and w 0 b[L0] and L1 = L0. Here b[L0] denotes the expression obtained from b by

substituting values from L0 .

? w, L0, L1 ( R ) iff w, L0, L1 R .

? w, L0, L1 ( R1 ##1 R2 ) iff there exist x, y, L’ such that w = xy and x, L0, L’ R1 and y, L’, L1 R2 .

? w, L0, L1 ( R1 ##0 R2 ) iff there exist x, y, z, L’ such that w = xyz and |y| = 1, and xy, L0, L’ R1 and

yz, L’, L1 R2 .

? w, L0, L1 ( R1 or R2 ) iff there exists L’ such that both of the following hold:

— either w, L0, L’ R1 or w, L0, L’ R2, and

— L1 = L’ |D, where D = flow (dom(L0), ( R1 or R2 )) .

? w, L0, L1 ( R1 intersect R2 ) iff there exist L’, L" such that

w, L0, L’ R1 and w, L0, L" R2 and L1 = L’ |D’ U L" |D’’ , where

D’ = flow (dom(L0), R1) – (block (( R1 intersect R2 )) U sample (R2))

D’’ = flow (dom(L0), R2) – (block (( R1 intersect R2 )) U sample (R1))

Remark: It can be proved that if w, L0, L’ R1 and w, L0, L" R2 , then L’ |D’ U L" |D’’ is a function.

? w, L0, L1 first_match ( R ) iff both

— w, L0, L1 R and

— if there exist x, y, L’ such that w = xy and x, L0, L’ R, then y is empty.

? w, L0, L1 R [*0] iff |w| = 0 and L1 = L0.

? w, L0, L1 R [*1:$] iff there exist L(0) = L0, w1, L(1), w2, L(2),..., wj, L( j) = L1 ( j > 1) such that w = w1w2...wj

and for every i such that 1 < i < j, wi, L(i –1), L(i) R .

If S is a clocked sequence, then w, L0, L1 S iff w, L0, L1 S’, where S’ is the unclocked sequence that results

from S by applying the rewrite rules.

An unclocked sequence R is non-degenerate iff there exist a non-empty finite word w over Σ and local variable

contexts L0, L1 such that w, L0, L1 R. A clocked sequence S is non-degenerate iff the unclocked sequence S’

that results from S by applying the rewrite rules is non-degenerate.

Group

H.3 语义

链接
H.3 语义


H.3.6 Satisfaction with local variables

链接
H.3 语义, 主题
SystemVerilog 3.1a语言参考手册
H.3.6 Satisfaction with local variables
H.3 语义 | 主题
Group

H.3 语义

主题
主题 | 描述
H.3.6.1 Neutral satisfaction | w denotes a non-empty finite or infinite word over Σ. L0, L1 denote local variable contexts. The rules defining neutral satisfaction of an assertion are identical to those without local variables, but with the understanding that the underlying properties can have local variables. Neutral satisfaction of properties: ? w Q iff w, {} Q. ? w, L0 Q iff w, L0 Q’, where Q’ is the unclocked property that results from Q by applying the rewrite rules. ? w, L0 disable iff (b) P iff either w, L0 P or there exists 0 < k < |w| such that w... more
H.3.6.2 Weak and strong satisfaction by finite words | The definition is identical to that without local variables, but with the understanding that the underlying properties can have local variables.
链接
H.3 语义, 主题


H.3.6.1 Neutral satisfaction

链接
H.3.6 Satisfaction with local variables
SystemVerilog 3.1a语言参考手册
H.3.6.1 Neutral satisfaction
H.3.6 Satisfaction with local variables

w denotes a non-empty finite or infinite word over Σ. L0, L1 denote local variable contexts.

The rules defining neutral satisfaction of an assertion are identical to those without local variables, but with the

understanding that the underlying properties can have local variables.

Neutral satisfaction of properties:

? w Q iff w, {} Q.

? w, L0 Q iff w, L0 Q’, where Q’ is the unclocked property that results from Q by applying the rewrite

rules.

? w, L0 disable iff (b) P iff either w, L0 P or there exists 0 < k < |w| such that

w k b[L0] and w 0, k–1Tω, L0 P. Here, w 0, –1 denotes the empty word.

? w, L0 not P iff w, L0 P .

? w, L0 R iff there exist 0 < j < |w| and L1 such that w 0, j, L0, L1 R .

? w, L0 ( R |-> P ) iff for every 0 < j < |w| and L1 such that w 0, j, L0, L1 R, w j.., L1 P .

? w, L0 ( P ) iff w, L0 P.

? w, L0 ( P1 or P2 ) iff w, L0 P1 or w, L0 P2.

? w, L0 ( P1 and P2 ) iff w, L0 P1 and w, L0 P2.

Group

H.3.6 Satisfaction with local variables

链接
H.3.6 Satisfaction with local variables


H.3.6.2 Weak and strong satisfaction by finite words

链接
H.3.6 Satisfaction with local variables
SystemVerilog 3.1a语言参考手册
H.3.6.2 Weak and strong satisfaction by finite words
H.3.6 Satisfaction with local variables

The definition is identical to that without local variables, but with the understanding that the underlying properties can have local variables.

Group

H.3.6 Satisfaction with local variables

链接
H.3.6 Satisfaction with local variables


H.4 Extended Expressions

链接
附录H 并发断言的形式语义, 主题
SystemVerilog 3.1a语言参考手册
H.4 Extended Expressions
附录H 并发断言的形式语义 | 主题

This section describes the semantics of several constructs that are used like expressions, but whose meaning at a point in a word can depend both on the letter at that point and on previous letters in the word. By abuse of notation, the meanings of these extended expressions are defined for letters denoted “w j” even” though they depend also on letters w i for i < j. The reason for this abuse is to make clear the way these definitions should be used in combination with those in preceding sections.

Group

附录H 并发断言的形式语义

主题
主题 | 描述
H.4.1 Extended booleans | w denotes a non-empty finite or infinite word over Σ, j denotes an integer such that 0 < j < |w|, and T(V) denotes an instance of a clocked or unclocked sequence that is passed the local variables V as actual arguments. ? w j,L0,L1 T(V).ended iff there exist 0 < i < j and L such that both w i, j, {}, L T(V) and L1 = L0 |D U LV , where D = dom(L0) – (dom(L) V). ? w j,L0,L1 @(c)(T(V).matched) iff there exists 0 < i < j such that w i,L0,L1 T(V).ended and w i+1,... more
H.4.2 Past | w denotes a non-empty finite or infinite word over Σ, and j denotes an integer such that 0 < j < |w|. ? Let n > 1. If there exist 0 < i < j such that w i, j , {}, {} (c ##1 c [->n – 1]), then @(c)$past(e, n)[w j] = e[w i]. Otherwise, @(c)$past(e, n)[w j] has the value x. ? $past(e) $past(e,1) .
链接
附录H 并发断言的形式语义, 主题


H.4.1 Extended booleans

链接
H.4 Extended Expressions
SystemVerilog 3.1a语言参考手册
H.4.1 Extended booleans
H.4 Extended Expressions

w denotes a non-empty finite or infinite word over Σ, j denotes an integer such that 0 < j < |w|, and T(V) denotes

an instance of a clocked or unclocked sequence that is passed the local variables V as actual arguments.

? w j,L0,L1 T(V).ended iff there exist 0 < i < j and L such that both w i, j, {}, L T(V) and

L1 = L0 |D U LV , where D = dom(L0) – (dom(L) V).

? w j,L0,L1 @(c)(T(V).matched) iff there exists 0 < i < j such that w i,L0,L1

T(V).ended and

w i+1, j , {}, {} (!c [*0:$] ##1 c) .

? w j @(c)$stable(e) iff there exists 0 < i < j such that w

i, j , {}, {} (c ##1 c [->1]) and

e[w i] = e[w j].

? w j @(c)$rose(e) iff b[w j] = 1 and (if there exists 0 < i < j such that w i, j ,{}, {} (c ##1 c [->1])

then b[w i] 1), where b is the least-significant bit of e.

? w j @(c)$fell(e) iff b[w j] = 0 and (if there exists 0 < i < j such that w i, j ,{}, {} (c ##1 c [->1])

then b[w i] 0), where b is the least-significant bit of e.

Group

H.4 Extended Expressions

链接
H.4 Extended Expressions


H.4.2 Past

链接
H.4 Extended Expressions
SystemVerilog 3.1a语言参考手册
H.4.2 Past
H.4 Extended Expressions

w denotes a non-empty finite or infinite word over Σ, and j denotes an integer such that 0 < j < |w|.

? Let n > 1. If there exist 0 < i < j such that w i, j , {}, {} (c ##1 c [->n – 1]), then

@(c)$past(e, n)[w j] = e[w i]. Otherwise, @(c)$past(e, n)[w j] has the value x.

? $past(e) $past(e,1) .

Group

H.4 Extended Expressions

链接
H.4 Extended Expressions


H.5 Recursive Properties

链接
附录H 并发断言的形式语义
SystemVerilog 3.1a语言参考手册
H.5 Recursive Properties
附录H 并发断言的形式语义

This section defines the neutral semantics of instances of recursive properties in terms of the neutral semantics of instances of non-recursive properties. The latter can be expanded to properties in the abstract syntax by appropriate substitutions, and so their semantics is assumed to be understood.

According to Restriction 1 in Section 17.11.3, it is understood below that the negation operator not cannot be applied to any property expression that instantiates a recursive property. Restriction 2 in Section 17.11.3 is not represented here because disable iff is treated as a general property-building operator in this appendix. A precise version of Restriction 3 is given below.

Named property p is said to depend on named property q if there exist n > 0 and named properties p0,...,pn such that p0 = p, pn = q, and for all 0 < i < n, the declaration of property pi instantiates property pi+1. In particular, by taking q = p and n = 0, it follows that property p depends on property p.

A named property p has an associated dependency digraph. The nodes of the digraph are all the named properties on which p depends. If q and r are nodes of the digraph, then there is an arc from q to r for each instance of r in the declaration of q. Such an arc is labelled by the minimum number of timesteps that are guaranteed from the beginning of the declaration of q until the particular instance r. For example, if q is declared by:

Copy Code
property q;
(a |-> r)
and
((b ##1 c[*0:3]) |=> r);
endproperty

where a, b, c are boolean expressions, then there is one arc from q to r labeled by “0” due to a |-> r and there is a second arc from q to r labeled by “2” due to (b ##1 c[*0:3]) |=> r.

A named property p is called recursive if its node appears on a cycle in the dependency digraph of p. The following is a precise version of Restriction 3:

RESTRICTION 3: The sum of the arc labels around any cycle of the dependency digraph of a recursive property must be positive.

Let p(X) be an instance of a recursive named property p, where X denotes the actual arguments of the instance.

For k > 0, the k-fold approximation to p(X), denoted p[k](X), is an instance of a non-recursive property p[k] defined inductively as follows.

— The declaration of p[0] is obtained from the declaration of p by replacing the body property_expr with the literal 1’b1.

— For k > 0, the declaration of p[k] is obtained from the declaration of p by replacing each instance of a recursive property by its (k – 1)-fold approximation.

The semantics of the instance p(X) is then defined as follows. For any word w over Σ and local variable context

L, w, L |= p(X) iff for all k > 0, w,L |= p[k](X).

Group

附录H 并发断言的形式语义

链接
附录H 并发断言的形式语义


附录I sv_vpi_user.h

附录I sv_vpi_user.h

sv_vpi_user.h

Copy Code
/***************************************************************************
* sv_vpi_user.h
*
* Accellera SystemVerilog VPI extensions.
*
* This file contains the constant definitions, structure definitions, and
* routine declarations used by the Verilog PLI procedural interface VPI
* access routines.
*
**************************************************************************/

/***************************************************************************
* NOTE: The constant values 600 through 999 are reserved for use in this
* sv_vpi_user.h file. The range 800 through 899 is reserved for the reader
* VPI
**************************************************************************/

#ifndef SV_VPI_USER_H
#define SV_VPI_USER_H

#include <vpi_user.h>

#ifdef __cplusplus
extern "C" {
#endif
}

/****************************** OBJECT TYPES ******************************/
#define vpiPackage                600
#define vpiInterface              601
#define vpiProgram                602
#define vpiInterfaceArray         603
#define vpiProgramArray           604
#define vpiTypespec               605
#define vpiModport                606
#define vpiInterfaceTfDecl        607
#define vpiRefObj                 608
#define vpiVarBitVar              vpiRegBit
#define vpiLongIntVar             609
#define vpiShortIntVar            610
#define vpiIntVar                 611
#define vpiShortRealVar           612
#define vpiByteVar                613
#define vpiClassVar               614
#define vpiStringVar              615
#define vpiEnumVar                616
#define vpiStructVar              617
#define vpiUnionVar               618
#define vpiBitVar                 619
#define vpiLogicVar               vpiRegVar
#define vpiArrayVar               vpiRegArray
#define vpiLongIntTypespec        620
#define vpiShortRealTypespec      621
#define vpiByteTypespec           622
#define vpiShortIntTypespec       623
#define vpiIntTypespec            624
#define vpiClassTypespec          625
#define vpiStringTypespec         626
#define vpiVarBitTypespec         627
#define vpiEnumTypespec           628
#define vpiEnumConst              629
#define vpiIntegerTypespec        630
#define vpiTimeTypespec           631
#define vpiRealTypespec           632
#define vpiStructTypespec         633
#define vpiUnionTypespec          634
#define vpiBitTypespec            635
#define vpiLogicTypespec          636
#define vpiArrayTypespec          637
#define vpiVoidTypespec           638
#define vpiMemberTypespec         639
#define vpiClockingBlock          640
#define vpiClockingIODecl         641
#define vpiClassDefn              642
#define vpiConstraint             643
#define vpiConstraintOrdering     644
#define vpiDistItem               645
#define vpiAliasStmt              646
#define vpiThread                 647
#define vpiMethodFuncCall         648
#define vpiMethodTaskCall         649
#define vpiAssertProperty         650
#define vpiAssumeProperty         651
#define vpiCoverProperty          652
#define vpiDisableCondition       653
#define vpiClockingEvent          654
#define vpiPropertyDecl           655
#define vpiPropertySpec           656
#define vpiPropertyExpr           657
#define vpiMulticlockSequenceExpr 658
#define vpiClockedSeq             659
#define vpiPropertyInst           660
#define vpiSequenceDecl           661
#define vpiSequenceSpec           662
#define vpiActualArgExpr          663
#define vpiSequenceInst           664
#define vpiImmediateAssert        665
#define vpiReturn                 666
#define vpiAnyPattern             667
#define vpiTaggedPattern          668
#define vpiStructPattern          669
#define vpiDoWhile                670
#define vpiOrderedWait            671
#define vpiWaitFork               672
#define vpiDisableFork            673
#define vpiExpectStmt             674
#define vpiForeachStmt            675
#define vpiFinal                  676
#define vpiExtend                 677
#define vpiDistribution           678
#define vpiIdentifier             679

/******************************** METHODS *********************************/
/************* methods used to traverse 1 to 1 relationships **************/
#define vpiActual                 680
#define vpiTypedefAlias           681
#define vpiIndexTypespec          682
#define vpiBaseTypespec           683
#define vpiElemTypespec           684
#define vpiDefInputSkew           685
#define vpiDefOutputSkew          686
#define vpiClockingSkew           687
#define vpiActualDefn             688
#define vpiLhs                    689
#define vpiRhs                    690
#define vpiOrigin                 691
#define vpiPrefix                 692
#define vpiWith                   693
#define vpiProperty               694
#define vpiValueRange             695
#define vpiPattern                696
#define vpiWeight                 697

/************ methods used to traverse 1 to many relationships ************/
#define vpiTypedef                698
#define vpiImport                 699
#define vpiDerivedClasses         700
#define vpiMethods                701
#define vpiSolveBefore            702
#define vpiSolveAfter             703
#define vpiWaitingProcesses       704
#define vpiMessages               705
#define vpiMembers                706
#define vpiLoopVars               707
#define vpiConcurrentAssertions   708
#define vpiMatchItem              709

/************ methods both 1-1 and 1-many relations ***********************/
#define vpiInstance               710

/************************ generic object properties ***********************/
#define vpiTop                    600
#define vpiUnit                   601
#define vpiAccessType             602
#define vpiForkJoinAcc            1
#define vpiExternAcc              2
#define vpiDPIExternAcc           3
#define vpiDPIImportAcc           4
#define vpiArrayType              603
#define vpiStaticArray            1
#define vpiDynamicArray           2
#define vpiAssocArray             3
#define vpiQueueArray             4
#define vpiIsRandomized           604
#define vpiRandType               605
#define vpiNotRand                1
#define vpiRand                   2
#define vpiRandC                  3
#define vpiConstantVariable       606
#define vpiMember                 607
#define vpiVisibility             608
#define vpiPublicVis              1
#define vpiProtectedVis           2
#define vpiLocalVis               3
#define vpiPacked                 609
#define vpiTagged                 610
#define vpiRef                    611
#define vpiDefaultSkew            612
#define vpiVirtual                613
#define vpiUserDefined            614
#define vpiIsConstraintEnabled    615
#define vpiClassType              616
#define vpiMailboxClass           1
#define vpiSemaphoreClass         2
#define vpiUserDefineClass        3
#define vpiMethod                 617
#define vpiValid                  618
#define vpiActive                 619
#define vpiIsClockInferred        620
#define vpiQualifier              621
#define vpiUniqueQualifier        1
#define vpiPriorityQualifier      2
#define vpiTaggedQualifier        3
#define vpiNullConst              622
#define vpiOneStepConst           623
#define vpiAlwaysType             624
#define vpiAlwaysComb             1
#define vpiAlwaysFF               2
#define vpiAlwaysLatch            3
#define vpiDistType               625
#define vpiEqualDist              1   /* constraint equal distribution */
#define vpiDivDist                2   /* constraint divided distribution */

/******************************** Operators *******************************/
#define vpiImplyOp                50  /* -> implication operator */
#define vpiNonOverlapImplyOp      51  /* |=> non-overlapped implication */
#define vpiOverlapImplyOp         52  /* |-> overlapped implication operator */
#define vpiUnaryCycleDelayOp      53  /* binary cycle delay (##) operator */
#define vpiCycleDelayOp           54  /* binary cycle delay (##) operator */
#define vpiIntersectOp            55  /* intersection operator */
#define vpiFirstMatchOp           56  /* first_match operator */
#define vpiThroughoutOp           57  /* throught operator */
#define vpiWithinOp               58  /* within operator */
#define vpiRepeatOp               59  /* [=] non-consecutive repetition */
#define vpiConsecutiveRepeatOp    60  /* [*] consecutive repetition */
#define vpiGotoRepeatOp           61  /* [->] goto repetition */
#define vpiPostIncOp              62  /* ++ post-increment */
#define vpiPreIncOp               63  /* ++ pre-increment */
#define vpiPostDecOp              64  /* -- post-decrement */
#define vpiPreDecOp               65  /* -- pre-decrement */
#define vpiMatchOp                66  /* match() operator */
#define vpiCastOp                 67  /* type‘() operator */
#define vpiIffOp                  68  /* iff operator */
#define vpiWildEqOp               69  /* =?= operator */
#define vpiWildNeqOp              70  /* !?= operator */
#define vpiStreamLROp             71  /* left-to-right streaming {>>} operator */
#define vpiStreamRLOp             72  /* right-to-left streaming {<<} operator */
#define vpiMatchedOp              73  /* the .matched sequence operation */
#define vpiEndedOp                74  /* the .ended sequence operation */

/************************** STRUCTURE DEFINITIONS *************************/
/***************************** structure *****************************/
/**************************** CALLBACK REASONS ****************************/
#define cbStartOfThread           600 /* callback on thread creation */
#define cbEndOfThread             601 /* callback on thread termination */
#define cbEnterThread             602 /* callback on re-entering thread */
#define cbStartOfFrame            603 /* callback on frame creation */
#define cbEndOfFrame              604 /* callback on frame exit */
#define cbTypeChange              605 /* callback on variable type/size change */

/************************* FUNCTION DECLARATIONS **************************/
/**************************************************************************/
/**************************************************************************/
/*************************** Coverage VPI *********************************/
/* coverage control */
#define vpiCoverageStart          711
#define vpiCoverageStop           712
#define vpiCoverageReset          713
#define vpiCoverageCheck          714
#define vpiCoverageMerge          715
#define vpiCoverageSave           716

/* coverage type properties */
#define vpiAssertCoverage         717
#define vpiFsmStateCoverage       718
#define vpiStatementCoverage      719
#define vpiToggleCoverage         720

/* Coverage status properties */
#define vpiCovered                721
#define vpiCoverMax               722
#define vpiCoveredCount           723

/* Assertion-specific coverage status properties */
#define vpiAssertAttemptCovered   724
#define vpiAssertSuccessCovered   725
#define vpiAssertFailureCovered   726

/* FSM-specific coverage status properties */
#define vpiFsmStates              727
#define vpiFsmStateExpression     728

/* FSM handle types */
#define vpiFsm                    729
#define vpiFsmHandle              730

/***************************************************************************/
/***************************************************************************/
/***************************** Assertion VPI *******************************/
/* assertion types */
#define vpiSequenceType           731
#define vpiAssertType             732
#define vpiCoverType              733
#define vpiPropertyType           734
#define vpiImmediateAssertType    735

/* assertion callback types */
#define cbAssertionStart          606
#define cbAssertionSuccess        607
#define cbAssertionFailure        608
#define cbAssertionStepSuccess    609
#define cbAssertionStepFailure    610
#define cbAssertionDisable        611
#define cbAssertionEnable         612
#define cbAssertionReset          613
#define cbAssertionKill           614
#define cbAssertionSysInitialized 615
#define cbAssertionSysStart       616
#define cbAssertionSysStop        617
#define cbAssertionSysEnd         618
#define cbAssertionSysReset       619

/* Assertion control constants */
#define vpiAssertionDisable       620
#define vpiAssertionEnable        621
#define vpiAssertionReset         622
#define vpiAssertionKill          623
#define vpiAssertionEnableStep    624
#define vpiAssertionDisableStep   625
#define vpiAssertionClockSteps    626
#define vpiAssertionSysStart      627
#define vpiAssertionSysStop       628
#define vpiAssertionSysEnd        629
#define vpiAssertionSysReset      630

/* Assertion related structs and types */
typedef struct t_vpi_source_info {
    PLI_BYTE8 *fileName;
    PLI_INT32 startLine;
    PLI_INT32 startColumn;
    PLI_INT32 endLine;
    PLI_INT32 endColumn;
} s_vpi_source_info, *p_vpi_source_info;

typedef struct t_vpi_assertion_info {
    PLI_BYTE8 *assertName;   /* name of assertion */
    vpiHandle instance;      /* instance containing assertion */
    PLI_BYTE8 defname;       /* name of module/interface containing the assertion */
    vpiHandle clock;         /* clocking expression */
    PLI_INT32 assertionType; /* vpiSequenceType, vpiAssertType,
                                vpiCoverType, vpiPropertyType,
                                vpiImmediateAssertType */
    s_vpi_source_info sourceInfo;
} s_vpi_assertion_info, *p_vpi_assertion_info;

typedef struct t_vpi_assertion_step_info {
    PLI_INT32 matched_expression_count;
    vpiHandle *matched_exprs;             /* array of expressions */
    p_vpi_source_info *exprs_source_info; /* array of source info */
    PLI_INT32 stateFrom, stateTo;         /* identify transition */
} s_vpi_assertion_step_info, *p_vpi_assertion_step_info;

typedef struct t_vpi_attempt_info {
    union {
        vpiHandle failExpr;
        p_vpi_assertion_step_info step;
    } detail;
    s_vpi_time attemptStartTime; /* Time attempt triggered */
} s_vpi_attempt_info, *p_vpi_attempt_info;

/* typedef for vpi_register_assertion_cb callback function */
typedef PLI_INT32 (vpi_assertion_callback_func)(
    PLI_INT32 reason,        /* callback reason */
    p_vpi_time cb_time,      /* callback time */
    vpiHandle assertion,     /* handle to assertion */
    p_vpi_attempt_info info, /* attempt related information */
    PLI_BYTE8 *user_data     /* user data entered upon registration */
);

/* assertion specific VPI functions */
PLI_INT32 vpi_get_assertion_info (assert_handle, p_vpi_assertion_info);

vpiHandle vpi_register_assertion_cb(
    vpiHandle assertion, /* handle to assertion */
    PLI_INT32 reason,    /* reason for which callbacks needed */
    vpi_assertion_callback_func *cb_rtn,
    PLI_BYTE8 *user_data /* user data to be supplied to cb */
);

/***************************************************************************/
/***************************************************************************/
/*************** Reader VPI ***********************/
/* reader VPI has been assigned the numeric range 800-899 */
/********** Reader types ***********/
#define vpiTrvsObj                800 /* Data traverse object */
#define vpiCollection             810 /* Collection of VPI handle */
#define vpiObjCollection          811 /* Collection of traversable design objs */
#define vpiTrvsCollection         812 /* Collection of vpiTrvsObjs */

/********* Reader methods *********/
/* Check */
#define vpiIsLoaded               820 /* Object data is loaded check */
#define vpiHasDataVC              821 /* Traverse object has at least one VC
                                       * at some point in time in the
                                       * database check */
#define vpiHasVC                  822 /* Has VC at specific time check */
#define vpiHasNoValue             823 /* Has no value at specific time check */
#define vpiBelong                 824 /* Belongs to extension check */

/* Access */
#define vpiAccessLimitedInteractive 830 /* Interactive access */
#define vpiAccessInteractive        831 /* interactive with history access */
#define vpiAccessPostProcess        832 /* Database access */

/* Member of a collection */
#define vpiMember                   840 /* Member of a collection */

/* Iteration on instances for loaded */
#define vpiDataLoaded               850 /* Use in vpi_iterate() */

/* Control Traverse/Check Time */
#define vpiMinTime                  860 /* Min time */
#define vpiMaxTime                  864 /* Max time */
#define vpiPrevVC                   868 /* Previous Value Change (VC) */
#define vpiNextVC                   870 /* Next Value Change (VC) */
#define vpiTime                     874 /* Time jump */

/********** routines **********/

/* general form of the vpi extension loading function is:
* PLI_INT32 vpi_load_extension PROTO_PARAMS((PLI_BYTE8 *extension_name, ...))
*/

/********** Reader routines **********/
/* load extension form for the reader extension */
PLI_INT32 vpi_load_extension PROTO_PARAMS((PLI_BYTE8 *extension_name,
                                           PLI_BYTE8 *name,
                                           vpiType mode, ...))

PLI_INT32 vpi_close PROTO_PARAMS((PLI_INT32 tool,
                                  vpiType prop,
                                  PLI_BYTE8* name));

PLI_INT32 vpi_load_init PROTO_PARAMS((vpiHandle objCollection,
                                      vpiHandle scope,
                                      PLI_INT32 level));

PLI_INT32 vpi_load PROTO_PARAMS((vpiHandle h));

PLI_INT32 vpi_unload PROTO_PARAMS((vpiHandle h));

vpiHandle vpi_create PROTO_PARAMS((vpiType prop,
                                   vpiHandle h,
                                   vpiHandle obj));

vpiHandle vpi_goto PROTO_PARAMS((vpiType prop,
                                 vpiHandle obj,
                                 p_vpi_time time_p,
                                 PLI_INT32 *ret_code));

vpiHandle vpi_filter PROTO_PARAMS((vpiHandle h,
                                   PLI_INT32 ft,
                                   PLI_INT32 flag));

#ifdef __cplusplus
}
#endif

#endif


附录J 术语表

链接
主题
SystemVerilog 3.1a语言参考手册
附录J 术语表
主题
主题
主题 | 描述
集合 | 一个集合表达式、变量或类型代表了一组单一值。集合类型是任意非压缩结构体、非压缩联合体、或非压缩数组数据类型。集合可以作为一个整体拷贝或比较，但典型情况下不能作为一个整体使用在表达式中。
断言 | 断言是一条某个特性必须为“真”的语句。例如，一个read_request信号必须总是在两个时钟内跟着一个read_grant信号。断言能够自动检查一个指定的特性是否为“真”，并且，如果特性不为“真”，它能够自动产生一条错误信息。SystemVerilog提供了特殊的断言结构。断言结构在第17章中讨论。
Bit-stream | A bit-stream type or variables is any type that can be represented as a serial stream of bits. To qualify as a bit-stream type, each and every bit of the type must be individually addressable. This means that a bit-stream type can be any type that does not include a handle, chandle, real, shortreal, or event.
Canonical representation | A data representation format established by convention into which and from which translations can be made with specialized representations.
Constant | There are two types of constants in SystemVerilog. Parameters and local parameters are elaboration constants. Their values are calculated before elaboration is complete. Elaboration constants can be used to set the range of array types. The other form of constant is a run-time constant. These are variables that can only be set in an initialization expression using the const qualifier.
Context imported task | A DPI imported task declared with the 'context' property that is capable of calling exported tasks or functions and capable of accessing System Verilog objects via VPI or PLI calls.
Disable protocol | A set of conventions for setting, checking and handling disable status.
DPI | Direct Programming Interface. This is an interface between SystemVerilog and foreign programming languages permitting direct function calls from SystemVerilog to foreign code and from foreign code to SystemVerilog. It has been designed to have low inherent overhead and permit direct exchange of data between SystemVerilog and foreign code.
Dynamic | A dynamic type or variable is one that can be resized or re-allocated at runtime. Dynamic types include those that contain dynamic arrays, associative arrays, queues, or class handles.
Elaboration | Elaboration is the process of binding together the components that make up a design. These components can include module instances, primitive instances, interfaces, and the top-level of the design hierarchy.
枚举类型 | 枚举数据类型提供了一种能力来声明可以由一组命名值表示的变量。我们可以指定这些值等价的数值。枚举类型可以使用枚举名字而不是枚举值方便地引用或显示。3.10节讨论了枚举类型。
Exported task | A System Verilog task that is declared in an export declaration and can be enabled from an imported task.
Imported task | A DPI foreign code subprogram that can call exported tasks and can directly or indirectly consume simulation time.
Interface | An interface encapsulates the communication between blocks of a design, allowing a smooth migration from abstract system-level design through successive refinement down to lower-level register-transfer and structural views of the design. By encapsulating the communication between blocks, the interface construct also facilitates design re-use. The inclusion of interface capabilities is one of the major advantages of SystemVerilog. Interfaces are covered in Section 19.
Integral | An integral expression, variable or type is used to represent integral, or integer value They may also be called vectored values. .Integrals may be signed or unsigned, sliced into smaller integral values, or concatenated into larger values.
LRM | LRM是Language Reference Manual的缩写。“SystemVerilog LRM”指的是本文档。“Verilog LRM”指的是IEEE手册“1364-2001 IEEE Standard for Verilog Hardware Description Language 2001”。参见附录K中有关这个手册的信息。
Open array | A DPI array formal argument for which the packed or unpacked dimension size (or both) is not specified and for which interface routines describe the size of corresponding actual arguments at runtime.
Packed array | Packed array refers to an array where the dimensions are declared before an object name. Packed arrays can have any number of dimensions. A one-dimensional packed array is the same as a vector width declaration in Verilog. Packed arrays provide a mechanism for subdividing a vector into subfields, which can be conveniently accessed as array elements. A packed array differs from an unpacked array, in that the whole array is treated as a single vector for arithmetic operations. Packed arrays are discussed in detail in Section 4.
进程 | 进程是一个或多个编程语句的线程，这些编程语句可以独立于其它编程语句执行。Verilog中的每一个initial过程、always过程以及连续赋值语句都是一个独立的进程。这些都是静态的进程。也就是说，每次进程启动运行后，都会有一个进程的结束。SystemVerilog加入了特殊的always过程，它们既可以是静态进程也可以是动态进程。当启动动态进程的时候，它们可以无中止地运行。有关进程的内容在第九章提供。
信号 | 信号是一个非正式的术语，通常指的是一个变量或线网。它所处的上下文可能会在允许的类型上作进一步的限制。
单一类型（Singular） | 一个单一（singular）表达式、变量或类型代表一个单一的值、符号或句柄。一个单一类型可以是除非压缩结构体、非压缩联合体、或非压缩数组数据类型外的任何类型。
SystemVerilog | SystemVerilog指的是Accellera为在抽象建模和验证方面扩展IEEE 1364-2001 Verilog标准的能力所建立的标准。SystemVerilog标准的许多特性均在本文档中提供。
非压缩数组（Unpacked array） | 非压缩数组是一种类型的数组，它的数组维数在对象名之后声明。非压缩数组与Verilog中的数组相同，并且可以拥有任意数目的维数。非压缩数组与压缩数组的不同之处在于：非压缩数组作为一个整体不能使用在算术运算中。它的每一个元素必须单独处理。非压缩数组在第四章中讨论。
Verilog | Verilog指的是IEEE 1364-2001 Verilog硬件描述语言（HDL），一般称为Verilog-2001。这个语言在IEEE手册“1364-2001 IEEE Standard for Verilog Hardware Description Language 2001”中描述。参见附录K中有关这个手册的相关信息。
VPI | Verilog Procedural Interface的缩写，意为“Verilog程序接口”。它是第三代Verilog编程语言接口（PLI），提供了以面向对象的方式访问Verilog行为对象、结构对象、断言和覆盖对象的能力。
链接
主题


集合

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
集合
附录J 术语表

一个集合表达式、变量或类型代表了一组单一值。集合类型是任意非压缩结构体、非压缩联合体、或非压缩数组数据类型。集合可以作为一个整体拷贝或比较，但典型情况下不能作为一个整体使用在表达式中。

Group

附录J 术语表

链接
附录J 术语表


断言

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
断言
附录J 术语表

断言是一条某个特性必须为“真”的语句。例如，一个read_request信号必须总是在两个时钟内跟着一个read_grant信号。断言能够自动检查一个指定的特性是否为“真”，并且，如果特性不为“真”，它能够自动产生一条错误信息。SystemVerilog提供了特殊的断言结构。断言结构在第17章中讨论。

Group

附录J 术语表

链接
附录J 术语表


Bit-stream

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Bit-stream
附录J 术语表

A bit-stream type or variables is any type that can be represented as a serial stream of bits. To qualify as a bit-stream type, each and every bit of the type must be individually addressable. This means that a bit-stream type can be any type that does not include a handle, chandle, real, shortreal, or event.

Group

附录J 术语表

链接
附录J 术语表


Canonical representation

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Canonical representation
附录J 术语表

A data representation format established by convention into which and from which translations can be made with specialized representations.

Group

附录J 术语表

链接
附录J 术语表


Constant

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Constant
附录J 术语表

There are two types of constants in SystemVerilog. Parameters and local parameters are elaboration constants. Their values are calculated before elaboration is complete. Elaboration constants can be used to set the range of array types. The other form of constant is a run-time constant. These are variables that can only be set in an initialization expression using the const qualifier.

Group

附录J 术语表

链接
附录J 术语表


Context imported task

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Context imported task
附录J 术语表

A DPI imported task declared with the 'context' property that is capable of calling exported tasks or functions and capable of accessing System Verilog objects via VPI or PLI calls.

Group

附录J 术语表

链接
附录J 术语表


Disable protocol

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Disable protocol
附录J 术语表

A set of conventions for setting, checking and handling disable status.

Group

附录J 术语表

链接
附录J 术语表


DPI

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
DPI
附录J 术语表

Direct Programming Interface. This is an interface between SystemVerilog and foreign programming languages permitting direct function calls from SystemVerilog to foreign code and from foreign code to SystemVerilog. It has been designed to have low inherent overhead and permit direct exchange of data between SystemVerilog and foreign code.

Group

附录J 术语表

链接
附录J 术语表


Dynamic

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Dynamic
附录J 术语表

A dynamic type or variable is one that can be resized or re-allocated at runtime. Dynamic types include those that contain dynamic arrays, associative arrays, queues, or class handles.

Group

附录J 术语表

链接
附录J 术语表


Elaboration

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Elaboration
附录J 术语表

Elaboration is the process of binding together the components that make up a design. These components can include module instances, primitive instances, interfaces, and the top-level of the design hierarchy.

Group

附录J 术语表

链接
附录J 术语表


枚举类型

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
枚举类型
附录J 术语表

枚举数据类型提供了一种能力来声明可以由一组命名值表示的变量。我们可以指定这些值等价的数值。枚举类型可以使用枚举名字而不是枚举值方便地引用或显示。3.10节讨论了枚举类型。

Group

附录J 术语表

链接
附录J 术语表


Exported task

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Exported task
附录J 术语表

A System Verilog task that is declared in an export declaration and can be enabled from an imported task.

Group

附录J 术语表

链接
附录J 术语表


Imported task

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Imported task
附录J 术语表

A DPI foreign code subprogram that can call exported tasks and can directly or indirectly consume simulation time.

Group

附录J 术语表

链接
附录J 术语表


Interface

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Interface
附录J 术语表

An interface encapsulates the communication between blocks of a design, allowing a smooth migration from abstract system-level design through successive refinement down to lower-level register-transfer and structural views of the design. By encapsulating the communication between blocks, the interface construct also facilitates design re-use. The inclusion of interface capabilities is one of the major advantages of SystemVerilog. Interfaces are covered in Section 19.

Group

附录J 术语表

链接
附录J 术语表


Integral

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Integral
附录J 术语表

An integral expression, variable or type is used to represent integral, or integer value They may also be called vectored values. .Integrals may be signed or unsigned, sliced into smaller integral values, or concatenated into larger values.

Group

附录J 术语表

链接
附录J 术语表


LRM

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
LRM
附录J 术语表

LRM是Language Reference Manual的缩写。“SystemVerilog LRM”指的是本文档。“Verilog LRM”指的是IEEE手册“1364-2001 IEEE Standard for Verilog Hardware Description Language 2001”。参见附录K中有关这个手册的信息。

Group

附录J 术语表

链接
附录J 术语表


Open array

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Open array
附录J 术语表

A DPI array formal argument for which the packed or unpacked dimension size (or both) is not specified and for which interface routines describe the size of corresponding actual arguments at runtime.

Group

附录J 术语表

链接
附录J 术语表


Packed array

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Packed array
附录J 术语表

Packed array refers to an array where the dimensions are declared before an object name. Packed arrays can have any number of dimensions. A one-dimensional packed array is the same as a vector width declaration in Verilog. Packed arrays provide a mechanism for subdividing a vector into subfields, which can be conveniently accessed as array elements. A packed array differs from an unpacked array, in that the whole array is treated as a single vector for arithmetic operations. Packed arrays are discussed in detail in Section 4.

Group

附录J 术语表

链接
附录J 术语表


进程

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
进程
附录J 术语表

进程是一个或多个编程语句的线程，这些编程语句可以独立于其它编程语句执行。Verilog中的每一个initial过程、always过程以及连续赋值语句都是一个独立的进程。这些都是静态的进程。也就是说，每次进程启动运行后，都会有一个进程的结束。SystemVerilog加入了特殊的always过程，它们既可以是静态进程也可以是动态进程。当启动动态进程的时候，它们可以无中止地运行。有关进程的内容在第九章提供。

Group

附录J 术语表

链接
附录J 术语表


信号

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
信号
附录J 术语表

信号是一个非正式的术语，通常指的是一个变量或线网。它所处的上下文可能会在允许的类型上作进一步的限制。

Group

附录J 术语表

链接
附录J 术语表


单一类型（Singular）

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
单一类型（Singular）
附录J 术语表

一个单一（singular）表达式、变量或类型代表一个单一的值、符号或句柄。一个单一类型可以是除非压缩结构体、非压缩联合体、或非压缩数组数据类型外的任何类型。

Group

附录J 术语表

链接
附录J 术语表


SystemVerilog

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
SystemVerilog
附录J 术语表

SystemVerilog指的是Accellera为在抽象建模和验证方面扩展IEEE 1364-2001 Verilog标准的能力所建立的标准。SystemVerilog标准的许多特性均在本文档中提供。

Group

附录J 术语表

链接
附录J 术语表


非压缩数组（Unpacked array）

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
非压缩数组（Unpacked array）
附录J 术语表

非压缩数组是一种类型的数组，它的数组维数在对象名之后声明。非压缩数组与Verilog中的数组相同，并且可以拥有任意数目的维数。非压缩数组与压缩数组的不同之处在于：非压缩数组作为一个整体不能使用在算术运算中。它的每一个元素必须单独处理。非压缩数组在第四章中讨论。

Group

附录J 术语表

链接
附录J 术语表


Verilog

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
Verilog
附录J 术语表

Verilog指的是IEEE 1364-2001 Verilog硬件描述语言（HDL），一般称为Verilog-2001。这个语言在IEEE手册“1364-2001 IEEE Standard for Verilog Hardware Description Language 2001”中描述。参见附录K中有关这个手册的相关信息。

Group

附录J 术语表

链接
附录J 术语表


VPI

链接
附录J 术语表
SystemVerilog 3.1a语言参考手册
VPI
附录J 术语表

Verilog Procedural Interface的缩写，意为“Verilog程序接口”。它是第三代Verilog编程语言接口（PLI），提供了以面向对象的方式访问Verilog行为对象、结构对象、断言和覆盖对象的能力。

Group

附录J 术语表

链接
附录J 术语表


附录K 参考书目

附录K 参考书目

[K1] IEEE Std. 754-1985, IEEE Standard for Binary Floating-Point Arithmetic 1985. ISBN 1-5593-7653-8. IEEE Product No. SH10116-TBR.

[K2] IEEE Std. 1364-1995, IEEE Standard Hardware Description Language Based on the Verilog Hardware Description Language 1995. ISBN 0-7381-3065-6. IEEE Product No. WE94418-TBR.

[K3] IEEE Std. 1364-2001, IEEE Standard for Verilog Hardware Description Language 2001. ISBN 0-7381- 2827-9. IEEE Product No. SH94921-TBR.


主题

主题
3.3 整数数据类型
主题
主题 | 描述
3.3.1 integral类型 | 在本参考手册中，术语integral指的基本的整数数据类型、压缩数组、压缩结构体、压缩联合体、枚举类型和时间类型。
3.3.2 两态（两值）与四态（四值）数据类型 | 具有未知值（X）和高阻值（Z）的类型称为四态类型，包括logic、reg、integer和time。其它不具有未知值及高阻值的类型称为两态类型，例如bit和int。 int和integer的区别是：int是两态逻辑而integer是四态逻辑。四态值需要一个额外的位来编码X和Z状态。两态数据类型的仿真速度更快一些，而且占用更少的内存，因而在某些设计风格中成为首选数据类型。
3.3.3 有符号与无符号数据类型 | 整数类型使用整数算术，并且可以是有符号的也可以是无符号的。这些会影响某些操作码的含义，例如“<”等。


主题

主题
3.7 string数据类型
主题
主题 | 描述
3.7.1 len() |
3.7.2 putc() |
3.7.3 getc() |
3.7.4 toupper() |
3.7.5 tolower() |
3.7.6 compare() |
3.7.7 icompare() |
3.7.8 substr(int i, int j) |
3.7.9 atoi(), atohex(), atooct(), atobin() |
3.7.10 atoreal() |
3.7.11 itoa() |
3.7.12 hextoa() |
3.7.13 octtoa() |
3.7.14 bintoa() |
3.7.15 realtoa() |


主题

主题
3.10.4 数值表达式中的枚举类型
主题
主题 | 描述
3.10.4.1 first() | first()方法的原型为：
3.10.4.2 last() | last()方法的原型为：
3.10.4.3 next() | next()方法的原型为：
3.10.4.4 prev() | prev()方法的原型为：
3.10.4.5 num() | num()方法的原型为：
3.10.4.6 name() | name()方法的原型为：
3.10.4.7 使用枚举类型的方法 | 下面的代码片断展示了如何显示一个枚举变量所有成员的名字和值。


主题

主题
3.10 枚举
主题
主题 | 描述
3.10.1 将新的数据类型定义成枚举类型 | 我们可以为枚举类型指定一个类型名，这样相同的类型可以在许多地方使用。
3.10.2 枚举类型的排列 | 枚举元素的排列可以使用下列的语法自动指定。 表格 3-3：枚举元素的排列
3.10.3 类型检查 | SystemVerilog枚举类型是一种强类型，因此，一个enum类型的变量不能被直接赋值为一个位于枚举集范围之外的值，除非使用强制类型转换或者除非这个枚举变量是一个联合体的成员。这种强大的类型检查能够防止用户偶然地将枚举类型变量赋值为不存在的值。这个限制仅仅适用于被显式地声明成一个类型的枚举。枚举值仍然可以在表达式中作为常量使用，并且运算结果也可以赋值到任何一个具有兼容的integral类型的变量。 无论是枚举名还是它们的整数值都必须是唯一的。它们的值可以被设置为任意integral常量值，或者从初始值0开始递增。如果将两个值设置到相同的枚举名，或者设置的值与递增值冲突都是错误的。 枚举变量在赋值、传递和关系操作符中进行类型检查。枚举变量可以自动转换成integral值，然而，将任何表达式赋值到枚举变量均要求一个显式的强制类型转换。例如：
3.10.4 数值表达式中的枚举类型 | 枚举变量的元素可以使用在数值表达式中。表达式中使用的值是与枚举值相关的数值。例如：


主题

主题
4.6 动态数组
主题
主题 | 描述
4.6.1 new[] | 内建函数new为动态数组分配存储空间，并使用缺省值或可选参数提供的值对最新分配的数组元素进行初始化。 new函数的原型如下：
4.6.2 size() | size()方法的原型如下：
4.6.3 delete() | delete()方法的原型如下：


主题

主题
4.9 联合数组
主题
主题 | 描述
4.9.1 通配符索引类型 | 例子：
4.9.2 字符串索引 | 例子：
4.9.3 类索引 | 例子：
4.9.4 integer（或int）索引 | 例子：
4.9.5 有符号的压缩数组 | 例子：
4.9.6 无符号压缩数组或压缩结构体 | 例子：
4.9.7 其它用户定义类型 | 例子：


主题

主题
4.10 联合数组方法
主题
主题 | 描述
4.10.1 num() | num()方法的语法如下：
4.10.2 delete() | delete()方法的语法如下：
4.10.3 exists() | exists()方法的语法如下：
4.10.4 first() | first()方法的语法如下：
4.10.5 last() | last()方法的语法如下：
4.10.6 next() | next()方法的语法如下：
4.10.7 prev() | prev()方法的语法如下：


主题

主题
4.14.2 队列方法
主题
主题 | 描述
4.14.2.1 size() | size()方法的原型如下：
4.14.2.2 insert() | insert()方法的原型如下：
4.14.2.3 delete() | delete()方法的原型如下：
4.14.2.4 pop_front() | pop_front()方法的原型如下：
4.14.2.5 pop_back() | pop_back()方法的原型为：
4.14.2.6 push_front() | push_front()方法的原型如下：
4.14.2.7 push_back() | push_back()方法的原型如下：


主题

主题
4.14 队列
主题
主题 | 描述
4.14.1 队列操作符 | 队列可以与非压缩数组执行相同的操作，除下述的操作符和操作规则外，它们使用相同的操作符和操作规则。
4.14.2 队列方法 | 除了数组操作符外，队列还提供了几个内建方法。


主题

主题
4.15 数组处理方法
主题
主题 | 描述
4.15.1 数组定位符方法 | 数组定位符方法可以对任意非压缩数组（包括队列）进行操作，但它们的返回值是一个队列。这些定位符方法能够在数组中搜索满足一个指定表示式的元素（或它们的索引）。数组定位符方法以未指定的顺序遍历数组。表达式选项不应具有任何边带效应，否则，会出现不可预料的结果。 这些方法的原型如下：
4.15.2 数组排序方法 | 数组排序方法可以对一维数组或队列的元素重新排序。 数组排序方法的基本原型如下：
4.15.3 数组缩减方法 | 数组缩减方法适用于任何非压缩数组以便将数组缩减成一个单独的值。可选的with子句中的表达式被用来指定缩减操作中使用的元素。 这些方法的原型如下：
4.15.4 迭代器索引查询 | 在数组处理方法中使用的表达式有时在每一次迭代过程中都需要真实的数组索引，而不仅仅是数组元素。一个迭代器的索引方法返回指定维数的索引值。 索引方法的原型如下：


主题

主题
5.8 类型兼容性
主题
主题
描述
5.8.1 等价类型
如果两个数据类型符合下列的归纳定义，那么它们是等价的。如果两个数据类型不符合下列的归纳定义，那么它们就是不等价的。
  1. 在每一个范围内，任何内建类型都等价于它本身的每一个其它的具体值。
  2. 一个简单的typedef或者重命名了一个内建的或用户定义类型的类型参数覆盖在类型标识符作用范围内等价于那个内建的或用户定义的数据类型。
5.8.2 赋值兼容
所有的等价类型以及所有定义了隐式强制类型转换的非等价类型都是赋值兼容的类型。例如，所有integral类型都是赋值兼容的。赋值兼容类型间的转换会由于缩减或四舍五入导致数据丢失。

兼容性可能仅存在于一个方向上。例如，一个枚举类型不需要一个强制类型转换就可以转换成integral类型，但反方向则不行。显式强制类型转换在“第三章 数据类型”以及“第七章 操作符与表达式”中定义。
5.8.3 强制转换兼容
所有的赋值兼容类型，加上定义了显式强制类型转换规则的非等价类型都是强制转换兼容的。例如，一个integral类型要求一个强制类型转换来赋值到一个枚举类型。显式强制类型转换在“第三章 数据类型”中定义。
5.8.4 类型非兼容性
所有余下的没有定义隐式或显式强制类型转换规则的非等价类型都是类型不兼容的。类句柄和chandle与所有其它类型都是类型不兼容的。


主题

主题
7.10 内建方法
主题
主题 | 描述
7.10.1 内建包 | SystemVerilog提供了一个内建的包，它包含了系统类型（例如类）、变量、任务和函数。用户不能在内建包中插入其它的声明。 内建包被隐含地导入到每一个编译单元的作用范围内（参见18.3节）。因此，内建包中的声明在所有范围内直接有效（就像系统任务和函数一样），除非他们被用户代码重新定义。


主题

主题
7.18 流操作符（压缩/非压缩）
主题
主题 | 描述
7.18.1 将动态尺寸的数据位流化 | 如果解压缩操作包含了庞大的动态尺寸类型，那么解压缩过程是很复杂的（就像强制类型转换中一样）：第一个动态尺寸条目被重新调整尺寸以便容纳流中所有的有效数据（排除了后续的固定尺寸条目）。对于仅仅包含了一个动态尺寸数据条目的流来说，采用这种机制来实现解压缩操作是足够的。然而，当流中包含了多个可变尺寸的数据包，或者每一个数据包包含了多个可变尺寸的数据条目、或者解压缩的数据的尺寸存储与一个流的中间部分，那么这种机制是很麻烦的并且容易引入错误。为了解决这些问题，解压缩操作允许使用一个with表达式来显式地指明解压缩操作中可变尺寸域的范围。 with表达式的语法如下：


主题

主题
8.4.1 模式匹配
主题
主题 | 描述
8.4.1.1 case语句中的模式匹配 | 在一个模式匹配case语句中，圆括号内的表达式紧跟着关键字matches，并且语句包含了一系列“case_pattern_items”。在一个case条目的左侧，“:”之前的部分，包含了一个模式以及一个可选的&&操作符，在&&操作符之后紧跟一个“filter”布尔表达式。case条目的右侧是一条语句。每一个模式都引入了一个新的作用范围，在这个范围中会隐式地声明它的模式标识符；这个作用范围扩展到可选的过滤器表达式以及同一个case条目右侧的语句。因此，不同的case条目可以复用模式标识符。 所有的模式均执行完全静态的类型检查。在模式匹配case语句中进行测试的表达式必须具有已知的类型，它与每个case条目中模式的类型相同。 模式匹配case语句中圆括号内的表达式应该仅计算一次。它的值V应该以指定的顺序一次一个条目地与case条目的左侧进行匹配，如果有default case条目的话，会将其忽略。在这个线性搜索过程中，如果一个case条目被选择，那么它对应的语句会被执行，然后中止这个线性搜索。如果没有case条目被选择，那么会执行default case条目中的语句。如果既没有case条目被选择也没有指定default case条目的话，那么不执行任何语句。 对于一个被选择的case条目，值V必须与模式匹配（模式标识符被赋值为V中对应的成员），并且，布尔过滤器表达式的计算结果必须为“真”（非零的确定值）。 例子：
8.4.1.2 if语句中的模式匹配 | if语句中的判定条件可以是一系列使用&&操作符分割的子句。每一个字句或者是一个表达式（用作布尔过滤器），或者具有形状表达式匹配模式。这些子句代表了一个从左到右的顺序的联合，也就是说，如果任何子句失败，剩余的子句都不会被计算，为了使判定条件为真，所有的子句都必须成功。布尔表达式以正常的方式计算。每一个模式都产生一个新的作用范围，其中模式标识符被隐式声明；这个作用范围扩展到判定条件中剩余的子句并扩展到if语句中对应为“真”的分支。 在每一个e匹配于p的子句中，e和p必须相同的静态已知的类型。e的值以上面描述的方式与p进行匹配。 即使模式匹配子句总是返回1位的结果，整个判定条件的结果也可能会因为其中的布尔过滤器表达式变得不明确。if语句保持标准语义，也就是说，第一条语句只有当结果是确定的非零值时才执行。 例子：
8.4.1.3 条件表达式中的模式匹配 | 条件表达式（e1 ? e2 : e3）也可以使用模式匹配，也就是说，判定条件e1可以是一个表达式序列，并且表达式匹配模式子句使用&&操作符分割，就像if语句中的判定条件一样。这些子句代表了一个从左到右的顺序的联合，也就是说，如果任何子句失败，剩余的子句都不会被计算，为了使判定条件为真，所有的子句都必须成功。布尔表达式以正常的方式计算。每一个模式都产生一个新的作用范围，其中模式标识符被隐式声明；这个作用范围扩展到判定条件中剩余的子句并扩展到作为结果的表达式e2。 正像前面章节所描述的那样，e1可以被计算成“真”、“假”或者一个不明确的值。对于e1，整个条件表达式的语义基于这三个可能的结果在7.18节中描述。


主题

主题
8.4 选择语句
主题
主题 | 描述
8.4.1 模式匹配 | 对于将一个值与结构体、标签联合体和常量进行比较以及对它们的成员的访问来讲，模式匹配提供了一个形象而又简洁的符号。SystemVerilog为case语句、if语句以及条件表达式加入了模式匹配的能力。在描述那些关联文中的模式匹配之前，我们首先描述一下基本概念。 模式是在叶子上带有标识符、常量表达式、以及通配符模式“.*”的标签联合体和结构体表达式的嵌套。对于标签联合体模式，紧跟tagged关键字之后的标识符是一个联合体成员名。对于void成员， 嵌套的成员模式被忽略。


主题

主题
8.5 循环语句
主题
主题 | 描述
8.5.1 do...while循环 |
8.5.2 循环的增强 | 在Verilog中，用来控制for循环的变量必须在循环之前声明。如果两个或多个并行程序中的循环使用相同的循环控制变量，那么就有可能出现一个循环修改其它循环还在使用的循环控制变量的情况。 SystemVerilog加入了在for循环中声明for循环控制变量的能力。这种方式会在循环内产生一个本地变量。其它并行循环不可能偶然地影响这个循环控制变量。例如：
8.5.3 foreach循环 | foreach结构指定在数组元素上的迭代。它的自变量是一个指明任意类型数组（固定尺寸的、动态的、及联合数组）的标识符，然后紧跟着一个包围在方括号内的循环变量的列表。每一个循环变量对应于数组的某一维。foreach结构类似于一个使用数组范围替代一个表达式来指定重复次数的repeat循环。 例子：


主题

主题
8.10 事件控制
主题
主题 | 描述
8.10.1 序列事件 | 事件表达式中可以使用一个序列实例，它基于序列的成功匹配来控制过程语句的执行。这就允许命名序列的终点能够触发其它进程中的多个动作。语法17-2和语法17-4描述了声明命名序列和序列实例的语法。正像语法8-9所显示的那样，一个序列实例可以直接使用在事件表达式中。 当一个事件表达式中指定了一个序列实例的时候，执行事件控制的进程应该阻塞直到指定的序列到达终点。只要整个序列形成匹配，一个序列就到达终点。进程继续执行之后的检测到终点的Observe区域。 使用一个序列作为事件控制的例子如下：


主题

主题
9.2 组合逻辑
主题
主题
描述
9.2.1 隐含的always_comb敏感性
最长静态前缀“P”的扩展具有如下的定义：
  1. 如果P不是一个存储器或索引选择，或者P是一个合法的字或位选择，那么扩展就是P本身。
  2. 如果P是一个存储器或索引选择，那么扩展是每一个可能的有效的存储器字，只要它带有与P匹配的静态前缀。
一个always_comb块的隐式敏感列表包括每一个变量或选择表达式的最长静态前缀扩展，只要它们块内读取或在块内的任何函数调用中读取，但具有下列例外：
  1. 在块内或块内调用的任何函数内声明的变量的扩展。
  2. 也在块内或块内调用的任何函数内写入的任何表达式。


主题

主题
9.8 进程控制
主题
主题 | 描述
9.8.1 wait fork | wait fork语句被用来确保所有子进程（调用进程产生的进程）的执行都已经结束。 wait fork的语法如下：
9.8.2 disable fork | disable fork语句用来中止调用进程的所有活跃的子进程。 disable fork的语法如下：


主题

主题
10.3 函数
主题
主题 | 描述
10.3.1 返回值与void函数 | 在Verilog中，函数必须具有返回值。返回值是通过为函数的名字赋值来完成的。
10.3.2 丢弃函数返回值 | 在Verilog-2001中，函数返回的值必须使用在赋值语句或使用在一个表达式中。调用一个好象没有返回值的函数会导致一个警告信息。通过将函数返回值强制转换成void类型，SystemVerilog允许使用void数据类型来忽略一个函数的返回值。


主题

主题
10.4 任务与函数的参数传递
主题
主题 | 描述
10.4.1 通过值传递 | 通过值传递是向子例程传递参数的缺省机制，它也是Verilog-2001提供的唯一的参数传递机制。这种参数传递机制是通过将每一个参数拷贝到子例程区域的方式实现的。如果子例程是自动的，那么子例程在它的堆栈中保留一个参数的本地拷贝。如果参数在子例程中被改变，那么这种改变在子例程外是不可见得。当参数很大的时候，我们可能不希望拷贝这个参数。而且，有时程序需要与一个没有声明成全局的数据共享一个数据片。 例如，对下面函数的调用会在每次调用函数时拷贝1000个字节。
10.4.2 通过引用传递 | 通过引用传递的参数不会拷贝到子例程区域，相反，一个对原始参数的引用会被传递到子例程。然后子例程可以通过这个引用访问参数数据。通过引用传递的参数必须匹配于等价数据类型。参见5.8.1节，等价类型。而且不允许使用强制类型转换。为了指示通过引用传递的参数，参数声明需要以ref关键字开始。基本语法如下：
10.4.3 缺省参数值 | 为了处理一些共用的情况或者考虑一些不用的参数，SystemVerilog允许子例程声明为每一个单一参数指定一个缺省值。 在一个子例程中声明一个缺省参数的语法如下：
10.4.4 通过名字传递参数 | SystemVerilog允许任务和函数的参数通过名字或位置进行传递。这就允许指定非连续的缺省参数，并能够方便地指定调用中传递的参数。例如：
10.4.5 可选的参数列表 | 如果一个任务或函数没有指定参数，那么紧跟在任务/函数名后面的圆括号()是可选的。这条规则对于要求参数，但所有的参数都指定了缺省值的情况也是适用的。


主题

主题
12.3 随机变量
主题
主题 | 描述
12.3.1 rand修饰符 | 使用rand关键字声明的变量是标准的随机变量。它们的值在其取值范围内均匀分布。例如：
12.3.2 randc修饰符 | 使用randc声明的变量是周期随机变量，它在一个它们声明范围内的一个随机排列中循环地选择所有的值。周期随机变量只能是bit类型或枚举类型，并且可以被限制到一个最大的尺寸。 为了理解randc，考虑一个两位的随机变量y：


主题

主题
12.4 约束块
主题
主题
描述
12.4.1 外部约束块
约束体可以像外部任务和函数体一样在一个类声明之外声明：
12.4.2 继承
对于继承而言，约束与类变量、任务和函数遵从相同的规则：
  • 如果一个继承类中的约束与它父类中的约束具有相同的名字，那么它会过载基类约束。例如：
12.4.3 集合成员资格
约束支持整数值集合以及集合成员资格操作符（在7.20节定义）。

如果没有其它的约束，inside操作符在选择值的时候，所有的值（包括单一值或范围值）都具有相等的概率。

inside操作符的否定形式指示表达式位于集合范围之外：!(expression inside {set})。

例如：
12.4.4 分布
除了集合成员资格外，约束支持被称为分布的加权值的集合。分布具有两个特性：它们是集合成员资格的关系测试，并且它们为结果指定了一个统计分布函数。

定义一个分布表达式的语法如下：
12.4.5 蕴含
约束提供了两种结构来声明有条件（判定的）的关系：蕴含和if...else。

蕴含操作符（->）可以用来声明隐含了一个约束的表达式。

定义一个蕴含约束的语法如下：
12.4.6 if...else约束
SystemVerilog还支持if...else类型的约束。

定义if...else约束的语法如下：
12.4.7 迭代约束
迭代约束让我们能够使用循环变量和索引表达式以一种参数化的方式约束数组变量。

定义一个迭代约束的语法如下：
12.4.8 全局约束
当类中的一个对象成员使用rand声明的时候，类中的所有约束和随机变量都会与其它的类变量和约束同时随机化。包含来自其它对象的约束变量的约束表达式被称为全局约束。
12.4.9 变量排序
求解器必须确保选择的值在有效的值组合中具有均匀的值分布（也就是说，所有的有效值组合在求解过程中具有相等的概率）。这个重要的特性能够保证所有的值组合的可能性是相等的，这也就允许随机化能够更好地探索整个设计空间。

然而，有时我们希望强制某种组合出现的频率更高一些。考虑一个案例，其中1位的控制变量s约束了一个32位的数据值d：
12.4.10 静态约束块
一个约束块可以通过在其定义中包含static关键字来被定义成静态的。

声明一个静态约束块的语法如下：
12.4.11 约束中的函数
某些特性很难或不可能在单一的表达式中表达。例如，在计算一个压缩数组中1的数目的时候，最普通的方法是使用一个循环语句：
12.4.12 约束守卫者
约束守卫者是一些判决表达式，它的作用并不是为了求解约束需要满足的逻辑关系，而是作为产生约束的守卫者。这些判决表达式在约束被求解之前计算，并且只能调用下列条目：
  • 常量
  • 状态变量
  • 对象句柄比较（两个句柄之间比较或者在句柄与常量null之间比较）
除了上面描述的条目外，迭代约束（参见12.4.7节）还会将循环变量以及正在被迭代的数组的尺寸当作状态变量。

将这些判决表达式作为约束守卫者能够在某些表面上看起来正确的约束上失败，因此也就可以防止求解器产生计算错误。这就使得用户能够编写约束来防止由于无效句柄或越界的数组索引导致的错误。例如，下面的例子实现了一个singlylinked链表（名字为SList），使用它的sort约束能够赋值一个按降序排列的数字随机序列。然而，对于最后一个元素，next.n会由于无效句柄产生一个计算错误，因此约束表达式会在最后一个元素失败。


主题

主题
12.5 随机化方法
主题
主题
描述
12.5.1 randomize()
一个对象中的变量使用randomize()类方法进行随机化。每一个类都有一个内建的randomize()虚拟方法，它的声明原型如下：
12.5.2 pre_randomize()与post_randomize()
每一个类都包含了内建的pre_randomize()和post_randomize()函数，它们在计算新的随机值之前和之后被 randomize()自动调用。

pre_randomize()的内建定义如下：
12.5.3 随机化方法注意事项
  • 被声明成static的随机变量被随机变量在其中声明的类的所有实例所共享。每次调用randomize()方法的时候，在每一个类实例中的变量都会被改变。
  • 如果randomize()失败，那么约束是不可实行的并且变量保持为原来的值。
  • 如果randomize()失败，post_randomize()方法不会被调用。
  • randomize()方法是内建的并且不能被过载。
  • randomize()方法实现了对象的随机稳定性。一个对象可以通过调用它的srandom()方法来设置种子（参见12.12.3节）。
  • pre_randomize()和post_randomize()内建方法是函数并且不能被阻塞。


主题

主题
12.10 内联随机变量控制
主题
主题 | 描述
12.10.1 内联约束检查器 | 通常，调用一个没有随机变量的类的randomize方法会导致这个方法作为一个检查器使用，也就是说它不会赋随机值，而是仅仅返回一个状态：如果所有的约束都被满足返回1，否则返回0。内联随机变量控制机制还可以用来强制randomize()方法作为一个检查器使用。 randomize方法可以接受特殊的参数null，它用来指示在调用期内没有随机变量。也就是说，所有的类成员均作为状态变量使用。这会导致randomize方法作为一个检查器使用而不是作为一个产生器使用。一个检查器会计算所有的约束并简单地在所有的约束都被满足时返回1，否则返回0。例如，如果上面定义的类CA执行了下列的调用：


主题

主题
12.11 范围变量的随机化 — std::randomize()
主题
主题 | 描述
12.11.1 为范围变量添加约束 — std::randomize() with | 范围随机化函数的std::randomize() with形式允许用户为本地范围变量指定随机约束。当说明约束的时候，范围随机化函数的参数指定的变量变成了随机变量，所有其它变量被认为是状态变量。


主题

主题
12.12 随机数系统函数与方法
主题
主题
描述
12.12.1 $urandom
$urandom系统函数提供了一种机制来产生伪随机数。每次调用这个函数的时候都会返回一个新的32位的随机数。这个随机数应该是无符号的。

$urandom的语法如下：
12.12.2 $urandom_range()
$urandom_range()函数返回一个指定范围内的无符号整数。

$urandom_range()的语法如下：
12.12.3 srandom()
srandom()方法允许我们手工地为对象或线程的随机数发生器（RNG）设置种子。一个进程的RNG可以使用进程的srandom()方法来设置种子（参见9.9节）。

srandom()方法的原型如下：
12.12.4 get_randstate()
get_randstate()方法重新获得一个对象的随机数发生器（RNG）的当前状态。与一个进程相关联的RNG的状态可以使用进程的get_randstate()方法重新获得（参见9.9节）。

get_randstate()方法的原型如下：
12.12.5 set_randstate()
set_randstate()方法设置一个对象的随机数发生器（RNG）的状态。与一个进程相关联的RNG的状态使用进程的set_randstate()方法来设置（参见9.9节）。

set_randstate()方法的原型如下：


主题

主题
12.13 随机稳定性
主题
主题
描述
12.13.1 随机稳定性的特性
随机稳定性包含下列特性：
  • 线程稳定性
每一个线程对于在该进程中发生的所有随机化系统调用都具有一个独立的RNG。当产生一个新的线程的时候，它的RNG的种子在父进程中被设置成下一个随机值。这个特性被称为层次化播种。

只要进程的产生和随机数产生是以前面相同的顺序完成，那么程序和线程稳定性就能得到保证。当为一个现存的测试加入新的进程的时候，为了维持先前产生的工作的随机数稳定性，它们可以在一个代码块的尾部加入。
  • 对象稳定性
每一个类实例（对象）对于类中的所有随机化方法都具有一个独立的RNG。当使用new产生一个对象的时候，它的RNG的种子会在产生对象的进程中设置为下一个随机值。

只要对象和线程的产生以及随机数的产生是与以前相同的顺序完成，对象稳定性就能得到保证。为了维持随机数稳定性，新的对象、线程和随机数可以在现存对象被产生以后产生。
  • 手工设置种子
所有RNG的种子都可以手工设置。与层次化的播种结合起来，这个便利性使得用户能够完全定义在系统根线程上具有单个种子的子系统（层次子树）的操作。
12.13.2 线程稳定性
从$urandom系统调用返回的随机值独立于线程的执行顺序。例如：
12.13.3 对象稳定性
构建在每一个类中的randomize()方法展示了对象稳定性。这种特性使得一个实例中对randomize()的调用独立于其它实例对randomize()的调用，并且独立于其它随机化函数的调用。

例如：


主题

主题
12.16 随机序列产生 — randsequence
主题
主题 | 描述
12.16.1 随机生成式权重 | 一个生成式列表被产生的概率可以通过为生成式列表赋值一个权重来改变。一个特定的生成式列表被产生的概率与它的权重成比例。
12.16.2 If...else生成式语句 | 通过if...else生成式语句可以使得一个生成式成为有条件的。if...else生成式语句的语法如下：
12.16.3 case生成式语句 | 一个生成式可以使用case生成式语句从一组可选项中选择。case生成式语句的语法如下：
12.16.4 repeat生成式语句 | repeat生成式语句被用来在一个生成式上迭代指定的次数。repeat生成式语句的语法如下：
12.16.5 交叉生成式 — rand join | rand join生成式控制被用来随机地交叉两个或多个生成式序列而又能维持每一个序列的相对顺序。rand join生成式控制的语法如下：
12.16.6 中止生成式 — break和return | 两个过程化语句可以用来提前中止一个生成式：break和return。这两个语句可以出现在任意代码块中；它们的不同之处在于它们退出的范围不同。 break语句中止序列的产生。当在一个生成式代码块中执行break语句的时候，它会强制跳出randsequence块。例如：
12.16.7 生成式间的值传递 | 数据可以传递到将要产生的生成式，并且产生的生成式可以将数据返回到触发的非端接生成式。向生成式传递数据类似于一个任务调用，并且使用相同的语法。从一个生成式返回数据要求为生成式声明一个类型，这与函数声明使用相似的语法。 接收数据的生成式包含一个形式参数列表。为生成式声明参数的语法类似于一个任务原型；向生成式传递数据的语法与一个任务调用相同。


主题

主题
13.2 semaphore
主题
主题
描述
13.2.1 new()
semaphore使用new()方法产生。

semaphore new()方法的原型如下：
13.2.2 put()
semaphore put()方法被用来将键值返回到一个semaphore中。

put()方法的原型如下：
13.2.3 get()
semaphore get()方法被用来从一个semaphore中获得指定数目的键值。

get()方法的原型如下：
13.2.4 try_get()
semaphore try_get()方法被用来无阻塞地从一个semaphore中获得指定数目的键值。

try_get()方法的原型如下：


主题

主题
13.3 mailbox
主题
主题
描述
13.3.1 new()
new()方法用来产生mailbox。

mailbox new()方法的原型如下：
13.3.2 num()
一个mailbox中消息的数目可以通过num()方法获得。

num()方法的原型如下：
13.3.3 put()
put()方法将一个消息放入到一个mailbox中。

put()方法的原型如下：
13.3.4 try_put()
try_put()方法尝试将一个消息放置在一个mailbox中。

try_put()方法的原型如下：
13.3.5 get()
get()方法从一个mailbox中重新获得一个消息。

get()方法的原型如下：
13.3.6 try_get()
try_get()方法尝试无阻塞地从一个mailbox中重新获得一个消息。

try_get()方法的原型如下：
13.3.7 peek()
peek()方法从一个mailbox中拷贝一个消息但不会将其从队列中删除。

peek()方法的原型如下：
13.3.8 try_peek()
try_peek()方法尝试从一个mailbox中无阻塞地拷贝一个消息。

try_peek()方法的原型如下：


主题

主题
13.5 事件
主题
主题 | 描述
13.5.1 触发一个事件 | 命名事件可以通过->操作符触发。 触发一个事件可以为当前等待这个事件的所有进程解除阻塞。当被触发以后，命名事件的行为就好像一个热点，也就是说，触发状态本身是不可观测的，我们仅仅能够观测到它的效果。这种方式类似于一个沿能够触发一个触发器，但沿的状态却不能被确定一样，也就是说，if (posedge clock)是非法的。
13.5.2 无阻塞的事件触发 | 无阻塞事件使用->>操作符触发。 ->>操作符的效果是语句会无阻塞地执行，并且在延时控制过期或事件控制发生的时候会产生一个无阻塞的赋值更新事件。这个更新事件的效果应该是在仿真周期的无阻塞赋值区域触发被引用的事件。
13.5.3 等待一个事件 | 等待一个事件被触发的基本机制是通过事件控制操作符，@。
13.5.4 稳固的触发：触发特性 | SystemVerilog能够从在整个时间步值期间持续（也就是直到仿真时间继续）的事件触发状态中辨别事件触发器本身（瞬时的）。触发的事件特性允许用户检查这个状态。 触发的特性使用一个类似于方法的语法来调用：


主题

主题
13.7 事件变量
主题
主题
描述
13.7.1 合并事件
当一个事件被赋值到另外一个事件的时候，这两个事件被合并。因此，在其中一个变量上执行->会影响等待任意一个事件变量的进程。

例如：
13.7.2 回收事件
当一个事件变量被赋值为特殊的null值的时候，事件变量和底层同步队列之间的关联被打断。当没有事件变量与一个底层同步队列相关联的时候，队列本身的资源变成能够被重新使用的（资源被释放？<FPGA技术网疑问？>）。

触发一个空事件不会有任何效果。等待一个空事件的结果是未定义的，并且在实现时可以发布一个运行时警告。

例如：
13.7.3 事件比较
事件变量可以与其它事件变量或特殊值null比较。对于事件变量的比较，仅仅允许下列的操作符：
  • 与另外一个事件或与null进行相同操作（==）；
  • 与另外一个事件或与null进行不等操作（!=）；
  • 与另外一个事件或与null进行条件相等操作（===，与==具有相同的语义）；
  • 与另外一个事件或与null进行条件不等操作（!==，与!=具有相同的语义）；
  • 检测一个布尔值，在事件为null的时候它为0，否则为1。

例子：


主题

主题
14.3 分层的事件调度器
主题
主题 | 描述
14.3.1 SystemVerilog仿真参考算法 |


主题

主题
15.14 同步的驱动
主题
主题 | 描述
15.14.1 驱动和无阻塞赋值 | 同步信号驱动按照无阻塞赋值处理。 inout时钟控制块变量和同步驱动的一个关键特性是一个驱动不会改变时钟控制块输入。这是因为读取输入总是产生最后一个被采样的值，而不是被驱动的值。
15.14.2 驱动值解析 | 当多于一个同步驱动在相同的仿真时间被应用到相同的时钟控制块输出（或inout）的时候，SystemVerilog会检查被驱动值的冲突。当检测到冲突驱动的时候会发布一个运行时错误，并且每一个发生冲突的位都被驱动成X（对一个两态端口会被驱动成0）。 例如：


主题

主题
16.4 消除测试平台的竞争
主题
主题 | 描述
16.4.1 零时滞时钟控制块竞争 | 当一个时钟控制块将输入和输出时滞都设置成#0（参见15.3节）的时候，它的输入在其输出被驱动（在NBA区域）的同一时刻被采样（在observed区域）。这种类型的显式的#0延时处理是一个能够导致竞争的基本的非确定性源。然而，即使是在这种情况下，程序通过两种机制最小化了出现竞争的可能性。首先，在所有的#0延时转换已经通过设计传播并且系统已经达到了准稳态之后约束程序语句在Reactive区域被调度。其次，通过要求设计变量或线网址能够通过非阻塞修改。这两种机制降低了竞争的可能性；尽管如此，当时滞被显式地设置成#0的时候，一个竞争仍然有可能发生。


主题

主题
16.6 程序控制任务
主题
主题 | 描述
16.6.1 $exit() | 每一个程序都可以通过调用$exit系统任务显式地退出。当所有的程序退出（隐式或显式）的时候，仿真会结束并且会隐式地调用$finish。 $exit系统任务的语法如下：


主题

主题
17.4 布尔表达式
主题
主题
描述
17.4.1 操作数类型
下列类型是不被允许的：
  • 非整数类型（shortreal、real、realtime）
  • 字符串
  • 事件
  • chandle
  • 类
  • 联合数组
  • 动态数组
固定尺寸数组（压缩的以及非压缩的）都可以当作一个整体、部分选择和被索引的位使用。片断可以是常量、参数或变量。

下面的例子显示了一些可能的结构体和联合体成员比较的格式：
17.4.2 变量
可以出现在表达式中的变量必须是静态设计变量或者是返回17.4.1节中描述的类型值的函数调用。在程序、接口或时钟控制块中声明的静态变量也可以被访问。如果引用一个任务中声明的静态变量，那么变量独立于任务调用被采样成任意其它变量。
17.4.3 操作符
针对17.4.1节中描述的类型有效的所有操作符都是允许的，除了赋值操作符以及递增和递减操作符。SystemVerilog包含C语言赋值操作符，例如+=，以及C语言递增和递减操作符（++和--）。这些表达式不能在出现在断言中的表达式中使用。这个限制阻止了边带效应。


主题

主题
17.7 序列操作
主题
主题 | 描述
17.7.1 操作符优先级 | 操作符优先级和关联性在下面的表17-1中列出。最高的优先级被最先列出。 表17-1: 操作符优先级和关联性
17.7.2 序列中的复制 | 下面是序列复制的语法：
17.7.3 采样值函数 | 本节描述了用来访问一个表达式采样值的有效的系统函数。这些函数能够访问当前的采样值、访问过去的采样值、或者检测一个表达式采样值的变化。一个表达式的采样在17.3节中解释。SystemVerilog提供了下列的函数。
17.7.4 与操作 | 当我们希望两个操作数都能够匹配，但操作数序列的结束时间可以不同的时候，我们可以使用二元操作符and。
17.7.5 交集（具有长度限制的与操作） | 当我们希望两个操作数能够匹配，并且操作数序列的结束时间必须相同的时候，我们可以使用intersect二元操作符。
17.7.6 或操作 | 当希望两个操作数序列中至少有一个匹配的时候，我们可以使用or操作符。
17.7.7 first_match操作 | 对于操作数序列的一次计算尝试的多个可能的匹配，first_match操作符仅仅匹配其中的第一个。这就使得所有后续的匹配都不会被考虑。特别地，当一个序列是一个更大的序列的子序列的时候，first_match操作符对于封闭序列的计算具有明显的效果。
17.7.8 序列上的条件 | 序列经常发生在某种假设的条件下以获得正确的行为。一个逻辑条件必须保持为“真”，例如在处理一个事物的时候。而且，在处理一个事务的时候，是禁止出现某些值的 。这样的情形可以直接使用下面的结构来表达：
17.7.9 包含在另外一个序列中的序列 | 在一个序列中容纳另外一个序列可以按如下方式表示：
17.7.10 一个序列结束点的检测和使用 | SystemVerilog中提供了两种方法将一个复杂序列分解成较为简单的子序列。 一种方法是通过引用名字来实例化一个命名序列。这样一个引用的计算要求命名序列从包围序列的计算期间引用被到达的时钟标记上开始匹配。例如：


主题

主题
17.11 声明特性
主题
主题
描述
17.11.1 蕴含
蕴含结构指出一个特性检查是在一个有序前项匹配的基础上有条件地执行的。
17.11.2 特性的例子
下面的例子演示了特性的格式。
17.11.3 递归特性
SystemVerilog允许使用递归的特性。如果一个命名特性的声明调用了其本身的一个实例，那么这个命名特性是递归的。递归提供了一种灵活的框架来对特性进行编码以便作为正在进行的假设、检查器或覆盖率监视器使用。

例如：
17.11.4 有限长度与无限长度行为
The formal semantics in Annex H defines whether a given property holds on a given behavior. How the outcome of this evaluation relates to the design depends on the behavior that was analyzed. In dynamic verification, only behaviors that are finite in length are considered. In such a case, SystemVerilog defines four levels of satisfaction of a property:

Holds strongly:
  • no bad states have been seen
  • all future obligations have been met
  • the property will hold on any extension of the path
Holds (but does not hold strongly):
  • no bad states have been seen
  • all future obligations have been met... more
17.11.5 Non-degeneracy
It is possible to define sequences that can never be matched. For example:


主题

主题
17.12 多时钟的支持
主题
主题 | 描述
17.12.1 多时钟控制序列 | Multiply-clocked sequences are built by concatenating singly-clocked subsequences using the single-delay concatenation operator ##1. This operator is non-overlapping and synchronizes between the clocks of the two sequences. The single delay indicated by ##1 is understood to be from the endpoint of the first sequence, which occurs at a tick of the first clock, to the nearest strictly subsequent tick of the second clock, where the second sequence begins. For example, consider
17.12.2 多时钟控制特性 | As in the case of singly-clocked properties, the result of evaluating a multiply-clocked property is either true or false. Multiply-clocked properties can be formed in a number of ways. Multiply-clocked sequences are themselves multiply-clocked properties. For example,
17.12.3 时钟流 | Throughout this subsection, c, d denote clocking event expressions and v, w, x, y, z denote sequences with no clocking events. Clock flow allows the scope of a clocking event to extend in a natural way through various parts of multiplyclocked sequences and properties and reduces the number of places at which the same clocking event must be specified. Intuitively, clock flow provides that in a multiply-clocked sequence or property the scope of a clocking event flows left-to-right across linear operators (e.g., repetition, concatenation, negation, implication) and distributes to the operands of branching operators (e.g., conjunction, disjunction, intersection, if...else) until... more
17.12.4 例子 | The following are examples of multiple-clock specifications:
17.12.5 在多时钟语境中检测和使用一个序列的结束点 | To detect the end point of a sequence when the clock of the source sequence is different than the destination sequence, method matched on the source sequence is used. The end point of a sequence is reached whenever there is a match on its expression. The occurrence of the end point can be tested in any sequence expression by using the method ended when the clocks of the source and destination sequences are the same, while method matched is used when the clocks are different. The syntax of the matched method is:


主题

主题
17.13 并发断言
主题
主题 | 描述
17.13.1 断言语句 | The assert statement is used to enforce a property as a checker. When the property for the assert statement is evaluated to be true, the pass statements of the action block are executed. Otherwise, the fail statements of the action_block are executed. For example,
17.13.2 假设语句 | The purpose of the assume statement is to allow properties to be considered as assumptions for formal analysis as well as for dynamic simulation tools. When a property is assumed, the tools constrain the environment so that the property holds. For formal analysis, there is no obligation to verify that the assumed properties hold. An assumed property can be considered as a hypothesis to prove the asserted properties. For simulation, the environment must be constrained such that the properties that are assumed shall hold. Like an assert property, an assumed property must be checked and reported if it fails to... more
17.13.3 覆盖语句 | To monitor sequences and other behavioral aspects of the design for coverage, the same syntax is used with the cover statement. The tools can gather information about the evaluation and report the results at the end of simulation. When the property for the cover statement is successful, the pass statements can specify a coverage function, such as monitoring all paths for a sequence. The pass statement shall not include any concurrent assert, assume or cover statement. Coverage results are divided into two: coverage for properties, coverage for sequences. For sequence coverage, the statement appears as:
17.13.4 在过程化代码外部使用并发断言语句 | A concurrent assertion statement can be used outside of a procedural context. It can be used within a module, an interface, or a program. A concurrent assertion statement is an assert, an assume, or a cover statement.Such a concurrent assertion statement uses the always semantics. The following two forms are equivalent:
17.13.5 在过程化代码中嵌入并发断言 | A concurrent assertion statement can also be embedded in a procedural block. For example:


主题

主题
17.14 时钟解析
主题
主题 | 描述
17.14.1 在多时钟控制特性中的时钟解析 | Throughout this subsection, s, s1, s2 denote sequences without clocking events; p, p1, p2 denote properties without clocking events; m, m1, m2 denote multiply-clocked sequences, q, q1, q2 denote multiply-clocked properties; and c, c1, c2 denote non-identical clocking event expressions. Due to clock flow, juxtaposition of two clocks nullifies the first. This and the nesting of clocking events within other property building operators mean that there are subtleties in the general interpretation of the restrictions about where the clock can change in multiply-clocked properties. For example,


主题

主题
18.2 包
主题
主题 | 描述
18.2.1 引用包中的数据 | 为了在包被导入的作用域内能够识别包中定义的项目，包必须存在。 使用一个包中所作声明的一种方法是使用域解析操作符“::”进行引用。
18.2.2 搜索顺序规则 | 对于从一个包中导入的声明，表格18-1为其描述了搜索顺序规则。为了方便以后的讨论，考虑下面的包声明：


主题

主题
18.11 模块实例
主题
主题 | 描述
18.11.1 Instantiation using positional port connections | Verilog has always permitted instantiation of modules using positional port connections, as shown in the alu_accum1 module example, below.
18.11.2 Instantiation using named port connections | Verilog has always permitted instantiation of modules using named port connections as shown in the alu_accum2 module example.
18.11.3 Instantiation using implicit .name port connections | SystemVerilog adds the capability to implicitly instantiate ports using a .name syntax if the instance-port name and size match the connecting variable-port name and size. This enhancement eliminates the requirement to list a port name twice when the port name and signal name are the same, while still listing all of the ports of the instantiated module for documentation purposes. In the following alu_accum3 example, all of the ports of the instantiated alu module match the names of the variables connected to the ports, except for the unconnected zero port, which is listed using a named port connection, showing that... more
18.11.4 Instantiation using implicit .* port connections | SystemVerilog adds the capability to implicitly instantiate ports using a .* syntax for all ports where the instance-port name and size match the connecting variable-port name and size. This enhancement eliminates the requirement to list any port where the name and size of the connecting variable match the name and size of the instance port. This implicit port connection style is used to indicate that all port names and sizes match the connections where emphasis is placed only on the exception ports. The implicit .* port connection syntax can greatly facilitate rapid block-level testbench generation where all of the testbench... more


主题

主题
18.12 端口连接规则
主题
主题
描述
18.12.1 变量的端口连接规则
如果一个端口声明具有一个变量数据类型，那么它的方向控制端口实例如何连接，变量的端口连接规则如下：
  • 一个输入端口可以连接到一个兼容类型的任意表达式。A continuous assignment shall be implied when a variable is connected to an input port declaration. Assignments to variables declared as an input port shall be illegal. If left unconnected, the port shall have the default initial value corresponding to the data type.
  • An output port can be connected to a variable (or a concatenation) of a compatible data type. A continuous assignment shall be implied when a variable is connected the output port of an instance. Procedural or continuous assignments to a variable connected to the output port of an instance shall be illegal.
  • An output port can... more
18.12.2 线网的端口连接规则
If a port declaration has a wire type (which is the default), or any other net type, then its direction controls how it can be connected as follows:
  • An input can be connected to any expression of a compatible data type. If left unconnected, it shall have the value 'z.
  • An output can be connected to a net type (or a concatenation of net types) or a compatible variable type (or a concatenation of variable types).
  • An inout can be connected to a net type (or a concatenation of net types) or left unconnected, but not to a variable type.... more
18.12.3 接口的端口连接规则
A port declaration can be a generic interface or named interface type. An interface port instance must always be connected to an interface instance or a higher-level interface port. An interface port cannot be left unconnected.

If a port declaration has a generic interface type, then it can be connected to an interface instance of any type. If a port declaration has a named interface type, then it must be connected to an interface instance of the identical type.
18.12.4 兼容的端口类型
The same rules for assignment compatibility are used for compatible port types for ports declared as an input or an output variable, or for output ports connected to variables. SystemVerilog does not change any of the other port connection compatibility rules
18.12.5 非压缩数组端口与实例数组
For an unpacked array port, the port and the array connected to the port must have the same number of unpacked dimensions, and each dimension of the port must have the same size as the corresponding dimension of the array being connected.

If the size and type of the port connection match the size and type of a single instance port, the connection shall be made to each instance in an array of instances.

If the port connection is an unpacked array, the unpacked array dimensions of each port connection shall be compared with the dimensions of the instance array.... more


主题

主题
19.2 接口语法
主题
主题 | 描述
19.2.1 Example without using interfaces | This example shows a simple bus implemented without interfaces. Note that the logic type can replace wire and reg if no resolution of multiple drivers is needed.
19.2.2 Interface example using a named bundle | The simplest form of a SystemVerilog interface is a bundled collection of variables or nets. When an interface is referenced as a port, the variables and nets in it are assumed to have ref and inout access, respectively. The following interface example shows the basic syntax for defining, instantiating and connecting an interface. Usage of the SystemVerilog interface capability can significantly reduce the amount of code required to model port connections.
19.2.3 Interface example using a generic bundle | A module header can be created with an unspecified interface reference as a place-holder for an interface to be selected when the module itself is instantiated. The unspecified interface is referred to as a “generic” interface reference. This generic interface reference can only be declared by using the list of port declaration style of reference. It shall be illegal to declare such a generic interface reference using the old Verilog-1995 list of port style. The following interface example shows how to specify a generic interface reference in a module definition.


主题

主题
19.4 modport
主题
主题 | 描述
19.4.1 An example of a named port bundle | This interface example shows how to use modports to control signal directions as in port declarations. It uses the modport name in the module definition.
19.4.2 An example of connecting a port bundle | This interface example shows how to use modports to restrict interface signal access and control their direction. It uses the modport name in the module instantiation.
19.4.3 An example of connecting a port bundle to a generic interface | This interface example shows how to use modports to control signal directions. It shows the use of the interface keyword in the module definition. The actual interface and modport are specified in the module instantiation.
19.4.4 Modport expressions | A modport expression allows elements of arrays and structures, concatenations of elements, aggregate expressions of elements declared in an interface to be included in a modport list. This modport expression is explicitly named with a port identifier, visible only through the modport connection. Like explicitly named ports in a module port declaration, port identifiers exist in their own namespace for each modport list. When modport item is just a simple port identifier, that identifier is used as both a reference to an interface item and a port identifier. Once a port identifier has been defined, there shall not be another... more
19.4.5 Clocking blocks and modports | The modport construct can also be used to specify the direction of clocking blocks declared within an interface. As with other modport declarations, the directions of the clocking block are those seen from the module in which the interface becomes a port. The syntax for this is shown below.


主题

主题
19.6 接口中的任务与函数
主题
主题 | 描述
19.6.1 An example of using tasks in an interface |
19.6.2 An example of using tasks in modports | This interface example shows how to use modports to control signal directions and task access in a full read/write interface.
19.6.3 An example of exporting tasks and functions | This interface example shows how to define tasks in one module and call them in another, using modports to control task access.
19.6.4 An example of multiple task exports | It is normally an error for more than one module to export the same task name. However, several instances of the same modport type can be connected to an interface, such as memory modules in the previous example. So that these can still export their read and write tasks, the tasks must be declared in the interface using the extern forkjoin keywords. The call to extern forkjoin task countslaves( ); in the example below behaves as:


主题

主题
19.8 虚拟接口
主题
主题 | 描述
19.8.1 Virtual interfaces and clocking blocks | Clocking blocks and interfaces can be combined to represent the interconnect between synchronous blocks. Moreover, because clocking blocks provide a procedural mechanism to assign values to both nets and variables, they are ideally suited to be used by virtual interfaces. For example:
19.8.2 Virtual interfaces modports and clocking blocks | As shown in the example above, once a virtual interface is declared, its clocking block can be referenced using dot-notation. However, this only works for interfaces with no modports. Typically, a device under test and its testbench exhibit modport direction. This common case can be handled by including the clocking in the corresponding modport as described in Section 19.4.5. The example below shows how modports used in conjunction with virtual interfaces facilitate the creation of abstract synchronous models.


主题

主题
20.4 定义覆盖点
主题
主题
描述
20.4.1 Specifying bins for transitions
The syntax for specifying transition bins accepts a subset of the sequence syntax described in Section 17:
20.4.2 Automatic bin creation for coverage points
If a coverage point does not define any bins, SystemVerilog automatically creates state bins. This provides an easy-to-use mechanism for binning different values of a coverage point. Users can either let the tool automatically create state bins for coverage points or explicitly define named bins for each coverage point.

When the automatic bin creation mechanism is used, SystemVerilog creates N bins to collect the sampled values of a coverage point. The value N is determined as follows:
  • For an enum coverage point, N is the cardinality of the enumeration.
  • For any other integral coverage point, N is the minimum of... more
20.4.3 Wildcard specification of coverage point bins
By default, a value or transition bin definition can specify 4-state values. When a bin definition includes an X or Z, it indicates that the bin count should only be incremented when the sampled value has an X or Z in the same bit positions, i.e., the comparison is done using ===. The wildcard bins definition causes all X, Z, or ? to be treated as wildcards for 0 or 1 (similar to the =?= operator). For example:
20.4.4 Excluding coverage point values or transitions
A set of values or transitions associated with a coverage-point can be explicitly excluded from coverage by specifying them as ignore_bins. For example:
20.4.5 Specifying Illegal coverage point values or transitions
A set of values or transitions associated with a coverage-point can be marked as illegal by specifying them as illegal_bins. For example:


主题

主题
20.5 Defining cross coverage
主题
主题 | 描述
20.5.1 Example of user-defined cross coverage and select expressions |
20.5.2 Excluding cross products | A group of bins can be excluded from coverage by specifying a select expression using ignore_bins. For example:
20.5.3 Specifying Illegal cross products | A group of bins can be marked as illegal by specifying a select expression using illegal_bins. For example:


主题

主题
20.6 Specifying coverage options
主题
主题 | 描述
20.6.1 Covergroup Type Options | The following table lists options that describe a particular feature (or property) of the covergroup type as a whole. They are analogous to static data members of classes. Table 20-3: Coverage group type (static) options


主题

主题
21.1 简介（一般信息）
主题
主题 | 描述
21.1.1 defparam语句的删除 | defparam语句可能会从SystemVerilog语言的未来版本中删除，参见26.2节。


主题

主题
23.15 $readmemb与$readmemh
主题
主题 | 描述
23.15.1 读取压缩的数据 | $readmemb and $readmemh are extended to unpacked arrays of packed data, associative arrays of packed data, and dynamic arrays of packed data. In such cases, the system tasks treat each packed element as the vector equivalent and perform the normal operation. When working with associative arrays, indexes must be of integral types.
23.15.2 读取两态类型 | $readmemb and $readmemh are extended to packed data of 2-state type, such as int or enumerated types. For 2-state integer types, reading proceeds the same as for conventional Verilog reg types (e.g. integer), with the exception that X or Z data is converted to 0. For enumerated types, the file data represents the ordinal value of the enumerated type. (See Section 3.10) If an enumeration ordinal is out of range for a given type, then an error shall be issued and no further reading shall take place.


主题

主题
23.16 $writememb and $writememh
主题
主题 | 描述
23.16.1 Writing packed data | writememb and $writememh treat packed data identically to readmemb and $readmemh. See Section 23.15.1
23.16.2 Writing 2-state types | $writememb and $writememh can write out data corresponding to unpacked arrays of 2-state types, such as int or enumerated types. For enumerated types, values in the file correspond to the ordinal values of the enumerated type. (See Section 3.10).
23.16.3 Writing addresses to output file | When $writememb and $writememh write out data corresponding to unpacked or dynamic arrays, address specifiers (@-words) shall not be written to the output file. When $writememb and $writememh write out data corresponding to associative arrays, address specifiers shall be written to the output file.


主题

主题
27.1.2 Data types
主题
主题 | 描述
27.1.2.1 Data representation | DPI does not add any constraints on how SystemVerilog-specific data types are actually implemented. Optimal representation can be platform dependent. The layout of 2- or 4-state packed structures and arrays is implementation- and platform-dependent. The implementation (representation and layout) of 4-state values, structures, and arrays is irrelevant for SystemVerilog semantics, and can only impact the foreign side of the interface.


主题

主题
27.1 概述
主题
主题 | 描述
27.1.1 Tasks and functions | DPI allows direct inter-language function calls between the languages on either side of the interface. Specifically, functions implemented in a foreign language can be called from SystemVerilog; such functions are referred to as imported functions. SystemVerilog functions that are to be called from a foreign code shall be specified in export declarations (see Section 27.6 for more details). DPI allows for passing SystemVerilog data between the two domains through function arguments and results. There is no intrinsic overhead in this interface. It is also possible to perform task enables across the language boundary. Foreign code can call SystemVerilog tasks, and... more
27.1.2 Data types | SystemVerilog data types are the sole data types that can cross the boundary between SystemVerilog and a foreign language in either direction (i.e., when an imported function is called from SystemVerilog code or an exported SystemVerilog function is called from a foreign code). It is not possible to import the data types or directly use the type syntax from another language. A rich subset of SystemVerilog data types is allowed for formal arguments of import and export functions, although with some restrictions and with some notational extensions. Function result types are restricted to small values, however (see Section 27.4.5). Formal... more


主题

主题
27.2 Two layers of the DPI
主题
主题 | 描述
27.2.1 DPI SystemVerilog layer | The SystemVerilog side of DPI does not depend on the foreign programming language. In particular, the actual function call protocol and argument passing mechanisms used in the foreign language are transparent and irrelevant to SystemVerilog. SystemVerilog code shall look identical regardless of what code the foreign side of the interface is using. The semantics of the SystemVerilog side of the interface is independent from the foreign side of the interface. This chapter does not constitute a complete interface specification. It only describes the functionality, semantics and syntax of the SystemVerilog layer of the interface. The other half of the interface,... more
27.2.2 DPI foreign language layer | The foreign language layer of the interface (which is transparent to SystemVerilog) shall specify how actual arguments are passed, how they can be accessed from the foreign code, how SystemVerilog-specific data types (such as logic and packed) are represented, and how to translate them to and from some predefined C-like types. The data types allowed for formal arguments and results of imported functions or exported functions are generally SystemVerilog types (with some restrictions and with notational extensions for open arrays). The user is responsible for specifying in their foreign code the native types equivalent to the SystemVerilog types used in... more


主题

主题
27.4.1 Required properties of imported tasks and functions — semantic constraints
主题
主题 | 描述
27.4.1.1 Instant completion of imported functions | Imported functions shall complete their execution instantly and consume zero-simulation time, similarly to native functions. Note that imported tasks can consume time, similar to native SystemVerilog tasks.
27.4.1.2 input, output and inout arguments | Imported functions can have input, output and inout arguments. The formal input arguments shall not be modified. If such arguments are changed within a function, the changes shall not be visible outside the function; the actual arguments shall not be changed. The imported function shall not assume anything about the initial values of formal output arguments. The initial values of output arguments are undetermined and implementation-dependent. The imported function can access the initial value of a formal inout argument. Changes that the imported function makes to a formal inout argument shall be visible outside the function.
27.4.1.3 Special properties pure and context | Special properties can be specified for an imported task or function: as pure or as context (see also Section 27.4.2 or 27.4.3 ). A function whose result depends solely on the values of its input arguments and with no side effects can be specified as pure. This can usually allow for more optimizations and thus can result in improved simulation performance. Section 27.4.2 details the rules that must be obeyed by pure functions. An imported task can never be declared pure. An imported task or function that is intended to call exported tasks or functions or to access SystemVerilog data... more
27.4.1.4 Memory management | The memory spaces owned and allocated by the foreign code and SystemVerilog code are disjoined. Each side is responsible for its own allocated memory. Specifically, an imported function shall not free the memory allocated by SystemVerilog code (or the SystemVerilog compiler) nor expect SystemVerilog code to free the memory allocated by the foreign code (or the foreign compiler). This does not exclude scenarios where foreign code allocates a block of memory, then passes a handle (i.e., a pointer) to that block to SystemVerilog code, which in turn calls an imported function (e.g. C standard function free) which directly or indirectly... more
27.4.1.5 Reentrancy of imported tasks | Since imported tasks can block (consume time), it is possible for an imported task’s C code to be simultaneously active in multiple execution threads. Standard reentrancy considerations must be made by the C programmer. Some examples of such considerations include safe use of static variables, and ensuring that only thread-safe C standard library calls (MT safe) are used.
27.4.1.6 C++ exceptions | It is possible to implement DPI imported tasks and functions using C++, as long as C linkage conventions are observed at the language boundary. If C++ is used, exceptions must not propagate out of any imported task or function. Undefined behavior will result if an exception crosses the language boundary from C++ into SystemVerilog.


主题

主题
27.4.6 形式参数的类型
主题
主题 | 描述
27.4.6.1 开放数组 | The size of the packed dimension, the unpacked dimension, or both dimensions can remain unspecified; such cases are referred to as open arrays (or unsized arrays). Open arrays allow the use of generic code to handle different sizes. Formal arguments of imported functions can be specified as open arrays. (Exported SystemVerilog functions cannot have formal arguments specified as open arrays.) A formal argument is an open array when a range of one or more of its dimensions is unspecified (denoted by using square brackets ([])). This is solely a relaxation of the argument-matching rules. An actual argument shall match the... more


主题

主题
27.4 导入的任务和函数
主题
主题
描述
27.4.1 Required properties of imported tasks and functions — semantic constraints
This section defines the semantic constraints imposed on imported tasks or functions. Some semantic restrictions are shared by all imported tasks or functions. Other restrictions depend on whether the special properties pure (see Section 27.4.2) or context (see Section 27.4.3) are specified for an imported task or function. A SystemVerilog compiler is not able to verify that those restrictions are observed and if those restrictions are not satisfied, the effects of such imported task or function calls can be unpredictable.
27.4.2 Pure functions
A pure function call can be safely eliminated if its result is not needed or if the previous result for the same values of input arguments is available somehow and can be reused without needing to recalculate. Only nonvoid functions with no output or inout arguments can be specified as pure. Functions specified as pure shall have no side effects whatsoever; their results need to depend solely on the values of their input arguments. Calls to such functions can be removed by SystemVerilog compiler optimizations or replaced with the values previously computed for the same values of the input arguments.... more
27.4.3 Context tasks and functions
Some DPI imported tasks or functions require that the context of their call is known. It takes special instrumentation of their call instances to provide such context; for example, an internal variable referring to the “current instance” might need to be set. To avoid any unnecessary overhead, imported task or function calls in SystemVerilog code are not instrumented unless the imported task or function is specified as context.

All DPI exported tasks or functions require that the context of their call is known. This occurs since SystemVerilog task or function declarations always occur in instantiable scopes, hence allowing a multiplicity... more
27.4.4 Import declarations
Each imported task or function shall be declared. Such declaration are referred to as import declarations. The syntax of an import declaration is similar to the syntax of SystemVerilog task or function prototypes (see Section 10.5).

Imported tasks or functions are similar to SystemVerilog tasks or functions. Imported tasks or functions can have zero or more formal input, output, and inout arguments. Imported functions can return a result or be defined as void functions. Imported tasks never return a result, and thus are always declared in foreign code as void functions.
27.4.5 Function result
Function result types are restricted to small values. The following SystemVerilog data types are allowed for imported function results:
  • void, byte, shortint, int, longint, real, shortreal, chandle, and string
  • packed bit arrays up to 32 bits and all types that are eventually equivalent to packed bit arrays up to 32 bits
  • scalar values of type bit and logic
The same restrictions apply for the result types of exported functions.
27.4.6 形式参数的类型
A rich subset of SystemVerilog data types is allowed for formal arguments of import and export tasks or functions. Generally, C compatible types, packed types and user defined types built of types from these two categories can be used for formal arguments of DPI tasks or functions. The set of permitted types is defined inductively.

The following SystemVerilog types are the only permitted types for formal arguments of import and export tasks or functions:
  • void, byte, shortint, int, longint, real, shortreal, chandle, and string
  • scalar values of type bit and logic
  • packed one dimensional arrays of type bit and logic... more


主题

主题
27.5.1 Argument passing
主题
主题 | 描述
27.5.1.1 “What You Specify Is What You Get” principle | The principle “What You Specify Is What You Get” guarantees the types of formal arguments of imported functions — an actual argument is guaranteed to be of the type specified for the formal argument, with the exception of open arrays (for which unspecified ranges are statically unknown). Formal arguments, other than open arrays, are fully defined by import declaration; they shall have ranges of packed or unpacked arrays exactly as specified in the import declaration. Only the declaration site of the imported function is relevant for such formal arguments. Another way to state this is that no compiler (either C... more


主题

主题
27.5 Calling imported functions
主题
主题 | 描述
27.5.1 Argument passing | Argument passing for imported functions is ruled by the WYSIWYG principle: What You Specify Is What You Get, see Section 27.5.1.1. The evaluation order of formal arguments follows general SystemVerilog rules. Argument compatibility and coercion rules are the same as for native SystemVerilog functions. If a coercion is needed, a temporary variable is created and passed as the actual argument. For input and inout arguments, the temporary variable is initialized with the value of actual argument with the appropriate coercion; for output or inout arguments, the value of the temporary variable is assigned to the actual argument with the appropriate... more
27.5.2 Value changes for output and inout arguments | The SystemVerilog simulator is responsible for handling value changes for output and inout arguments. Such changes shall be detected and handled after control returns from imported functions to SystemVerilog code. For output and inout arguments, the value propagation (i.e., value change events) happens as if an actual argument was assigned a formal argument immediately after control returns from imported functions. If there is more than one argument, the order of such assignments and the related value change propagation follows general SystemVerilog rules.


主题

主题
28.1 需求
主题
主题
描述
28.1.1 命名约定
All elements added by this interface shall conform to the Verilog Procedural Interface (VPI) interface naming conventions.
  • All names are prefixed by vpi.
  • All type names shall start with vpi, followed by initially capitalized words with no separators, e.g., vpiAssertCheck.
  • All callback names shall start with cb, followed by initially capitalized words with no separators, e.g., cbAssertionStart.
  • All function names shall start with vpi_, followed by all lowercase words separated by underscores (_), e.g., vpi_get_assert_info().


主题

主题
28.2 Extensions to VPI enumerations
主题
主题 | 描述
28.2.1 Object types | This section lists the object type VPI calls. The VPI reserved range for these calls is 700 - 729.
28.2.2 Object properties | This section lists the object property VPI calls. The VPI reserved range for these calls is 700 - 729.
28.2.3 Callbacks | This section lists the system callbacks. The VPI reserved range for these calls is 700 - 719. 1) Assertion
28.2.4 Control constants | This section lists the system control constant callbacks. The VPI reserved range for these calls is 730 - 759. 1) Assertion


主题

主题
28.3.2 Obtaining static assertion information
主题
主题 | 描述
28.3.2.1 Using vpi_get_assertion_info | Static information can be obtained directly from an assertion handle by using vpi_get_assertion_info(), as shown below.
28.3.2.2 Extending vpi_get() and vpi_get_str() | In addition to vpi_get_assertion_info, the following existing VPI functions are also extended:


主题

主题
28.3 Static information
主题
主题
描述
28.3.1 Obtaining assertion handles
SystemVerilog extends the VPI module iterator model (i.e., the instance) to encompass assertions, as shown in Figure 28-1.

The following steps highlight how to obtain the assertion handles for named assertions.

Figure 28-1 — Encompassing assertions

Note: Iteration on assertions from interfaces is not shown in Figure 28-1 since the interface object type is not currently defined in VPI. However the assertion API permits iteration on assertions from interface instance handles and obtaining static information on assertions used in interfaces (see Section 28.3.2.1).
1) Iterate all assertions in the design: use a NULL reference handle (ref) to vpi_iterate(), e.g.,

28.3.2 Obtaining static assertion information
The following information about an assertion is considered to be static.
  • Assertion name
  • Instance in which the assertion occurs
  • Module definition containing the assertion
  • Assertion type
    1. Sequence
    2. Assert
    3. Cover
    4. Property
    5. ImmediateAssert
  • Assertion source information: the file, line, and column where the assertion is defined.
  • Assertion clocking block/expression


主题

主题
28.4 Dynamic information
主题
主题 | 描述
28.4.1 Placing assertion system callbacks | Use vpi_register_cb(), setting the cb_rtn element to the function to be invoked and the reason element of the s_cb_data structure to one of the following values, to place an assertion system callback.
28.4.2 Placing assertions callbacks | Use vpi_register_assertion_cb() to place an assertion callback; the prototype is:


主题

主题
28.5 Control functions
主题
主题 | 描述
28.5.1 Assertion system control | Use vpi_control(), with one of the following operators and no other arguments, to obtain assertion system control information. Usage example: vpi_control(vpiAssertionSysReset) vpiAssertionSysReset discards all attempts in progress for all assertions and restore the entire assertion system to its initial state. Any pre-existing vpiAssertionStepSuccess and vpiAssertionStepFailure callbacks shall be removed; all other assertion callbacks shall remain. Usage example: vpi_control(vpiAssertionSysStop) vpiAssertionSysStop considers all attempts in progress as unterminated and disable any further assertions from being started. This control has no effect on pre-existing assertion callbacks. Usage example: vpi_control(vpiAssertionSysStart) vpiAssertionSysStart restarts the assertion system after it was stopped (e.g., due to vpiAssertionSysStop). Once... more
28.5.2 Assertion control | Use vpi_control(), with one of the following operators, to obtain assertion control information. — For the following operators, the second argument shall be a valid assertion handle. Usage example: vpi_control(vpiAssertionReset, assertionHandle) vpiAssertionReset discards all current attempts in progress for this assertion and resets this assertion to its initial state. Usage example: vpi_control(vpiAssertionDisable, assertionHandle) vpiAssertionDisable disables the starting of any new attempts for this assertion. This has no effect on any existing attempts. or if the assertion already disabled. By default, all assertions are enabled. Usage example: vpi_control(vpiAssertionEnable, assertionHandle) vpiAssertionEnable enables starting new attempts for this assertion. This has no effect... more


主题

主题
29.1 需求
主题
主题
描述
29.1.1 SystemVerilog API
The following criteria are used within this API.
1) This API shall be similar for all coverages
There are a wide number of coverage types available, with possibly different sets offered by different vendors. Maintaining a common interface across all the different types enhances portability and ease of use.
2) At a minimum, the following types of coverage shall be supported:
a) statement coverage
b) toggle coverage
c) fsm coverage
i) fsm states
ii) fsm transitions
c) assertion coverage
3) Coverage APIs shall be extensible in a transparent manner, i.e., adding a new coverage type shall not break any existing... more
29.1.2 Naming conventions
All elements added by this interface shall conform to the Verilog Procedural Interface (VPI) interface naming conventions.
  • All names are prefixed by vpi.
  • All type names shall start with vpi, followed by initially capitalized words with no separators, e.g., vpiCoverageStmt.
  • All callback names shall start with cb, followed by initially capitalized words with no separators, e.g., cbAssertionStart.
  • All function names shall start with vpi_, followed by all lowercase words separated by underscores (_), e.g., vpi_control().
29.1.3 Nomenclature
The following terms are used in this standard.
Statement coverage — whether a statement has been executed or not, where statement is anything defined as a statement in the LRM. Covered means it executed at least once. Some implementations also permit querying the execution count. The granularity of statement coverage can be per-statement or per-statement block (however defined).
FSM coverage — the number of states in a finite state machine (FSM) that this simulation reached. This standard does not require FSM automatic extraction, but a standard mechanism to force specific extraction is available via pragmas.
Toggle coverage — for each... more


主题

主题
29.2.2 Built-in coverage access system functions
主题
主题 | 描述
29.2.2.1 $coverage_control |
29.2.2.2 $coverage_get_max |
29.2.2.3 $coverage_get |
29.2.2.4 $coverage_merge |
29.2.2.5 $coverage_save |


主题

主题
29.2 SystemVerilog real-time coverage access
主题
主题 | 描述
29.2.1 Predefined coverage constants in SystemVerilog | The following predefined ‘defines represent basic real-time coverage capabilities accessible directly from SystemVerilog. — Coverage control
29.2.2 Built-in coverage access system functions |


主题

主题
29.3 FSM recognition
主题
主题 | 描述
29.3.1 Specifying the signal that holds the current state | Use the following pragma to identify the vector signal that holds the current state of the FSM:
29.3.2 Specifying the part-select that holds the current state | A part-select of a vector signal can be used to hold the current state of the FSM. When a coverage tool displays or reports FSM coverage data, it names the FSM after the signal that holds the current state. If a part-select holds the current state in the user’s FSM, the user needs to also specify a name for the FSM for the coverage tool to use. The FSM name is not the same as the enumeration name. Specify the part-select by using the following pragma:
29.3.3 Specifying the concatenation that holds the current state | Like specifying a part-select, a concatenation of signals can be specified to hold the current state (when including an FSM name and an enumeration name):
29.3.4 Specifying the signal that holds the next state | The signal that holds the next state of the FSM can also be specified with the pragma that specifies the enumeration name:
29.3.5 Specifying the current and next state signals in the same declaration | The tool assumes the first signal following the pragma holds the current state and the next signal holds the next state when a pragma is used for specifying the enumeration name in a declaration of multiple signals, e.g.,
29.3.6 Specifying the possible states of the FSM | The possible states of the FSM can also be specified with a pragma that includes the enumeration name:
29.3.7 Pragmas in one-line comments | These pragmas work in both block comments, between the /* and */ character strings, and one-line comments, following the // character string, e.g.,
29.3.8 Example | Example 29-2 — FSM specified with pragmas


主题

主题
29.4 VPI coverage extensions
主题
主题 | 描述
29.4.1 VPI entity/relation diagrams related to coverage |
29.4.2 Extensions to VPI enumerations | — Coverage control
29.4.3 Obtaining coverage information | To obtain coverage information, the vpi_get() function is extended with additional VPI properties that can be obtained from existing handles:
29.4.4 Controlling coverage |


主题

主题
30.3.2.2 Dynamic info
主题
主题 | 描述
30.3.2.2.1 Control constants |


主题

主题
30.3.2 Object properties
主题
主题 | 描述
30.3.2.1 Static info |
30.3.2.2 Dynamic info |


主题

主题
30.3 Extensions to VPI enumerations
主题
主题 | 描述
30.3.1 Object types | All objects in VPI have a vpiType. This API adds a new object type for data traversal, and two other objects types for object collection and traverse object collection.
30.3.2 Object properties | This section lists the object property VPI calls.
30.3.3 System callbacks | The access API adds no new system callbacks. The reader routines (methods) can be called whenever the user application has control and wishes to access data.


主题

主题
30.4.2 VPI collection
主题
主题 | 描述
30.4.2.1 Operations on collections | A traverse collection can be obtained (i.e. created) from a design collection using vpi_handle(). The call would take on the form of:


主题

主题
30.4 VPI object type additions
主题
主题
描述
30.4.1 Traverse object
To access the value changes of an object over time, the notion of a Value Change (VC) traverse handle is added. A value change traverse object is used to traverse and access value changes not just for the current value (as calling vpi_get_time() or vpi_get_value() on the object handle would) but for any point in time: past, present, or future. To create a value change traverse handle the routine vpi_handle() is called with a vpiTrvsObj vpiType:
30.4.2 VPI collection
In order to read data efficiently, it can be necessary to specify a group of objects. For example, when traversing data a user might wish to specify a list of objects to be marked as targets of data traversal. To do this grouping requires the notion of a collection. A collection represents a user-defined collection of VPI handles. The collection is an ordered list of VPI handles. The vpiType of a collection handle can be vpiCollection, vpi-ObjCollection, or vpiTrvsCollection:
  • A collection of type vpiCollection is a general collection of VPI handles of objects of any type.
  • The collection object of... more


主题

主题
30.8.3 Optionally loading objects
主题
主题 | 描述
30.8.3.1 Iterating the design for the loaded objects | The user shall be allowed to optionally iterate for the loaded objects in a specific instantiation scope using vpi_iterate(). This shall be accomplished by calling vpi_iterate() with the appropriate reference handle, and using the property vpiDataLoaded. This is shown below. a) Iterate all data read loaded objects in the design: use a NULL reference handle (ref_h) to
30.8.3.2 Iterating the object collection for its member objects | The user shall be allowed to iterate for the design objects in a design collection using vpi_iterate() and vpi_scan(). This shall be accomplished by creating an iterator for the members of the collection and then use vpi_scan() on the iterator handle e.g.


主题

主题
30.8.4 Reading an object
主题
主题 | 描述
30.8.4.1 Traversing value changes of objects | After getting a traverse vpiHandle, the application can do a forward or backward walk or jump traversal by using vpi_goto() on a vpiTrvsObj object type with the new traverse properties. Here is a sample code segment for the complete process from handle creation to traversal.
30.8.4.2 Jump Behavior | Jump behavior refers to the behavior of vpi_goto() with a vpiTime control constant, vpiTrvsObj type, and a jump time argument. The user specifies a time to which he or she would like the traverse handle to jump, but the specified time might or might not have value changes. In that case, the traverse handle shall point to the latest VC equal to or less than the time requested. In the example below, the whole simulation run is from time 10 to time 65, and a variable has value changes at time 10, 15 and 50. If a value change traverse... more
30.8.4.3 Dump off regions | When accessing a database, it is likely that there are gaps along the value time-line where possibly the data recording (e.g. dumping from simulator) was turned off. In this case the starting point of that interval shall be marked as a VC if the object had a stored value before that time. vpi_goto(), whether used to jump to that time or using next VC or previous VC traversal from a point before or after respectively, shall stop at that VC. Calling vpi_get_value() on the traverse object pointing to that VC shall have no effect on the value argument passed; the... more


主题

主题
30.8 Reading data
主题
主题 | 描述
30.8.1 VPI read initialization and load access initialization | Selecting an object is done in 3 steps: 1) The first step is to initialize the read access with a call to vpi_load_extension() to load the reader extension and set: a) Name of the reader library to be used specified as a character string. This is either a full pathname to this library or the single filename (without path information) of this library, assuming a vendor specific way of defining the location of such a library. The latter method is more portable and therefore recommended. Neither the full pathname, nor the single filename shall include an extension, the name of... more
30.8.2 Object selection for traverse access | In order to select an object for access, the user must first obtain the object handle. This can be done using the VPI routines (that are supported in the tool being used) for traversing the HDL hierarchy and obtaining an object handle based on the type of object relationship to another (top) handle. Any tool that implements this read API (e.g. waveform tool) shall implement at least a basic subset of the design navigation VPI routines that shall include vpi_handle_by_name() to permit the user to get a vpiHandle from an object name. It is left up to tool implementation to... more
30.8.3 Optionally loading objects | As mentioned earlier, vpi_load_init() allows the tool implementing the reader to load objects in a fashion that is invisible to the user. Optionally, if the user chooses to do their own loading at some point in time, then once the object handle is obtained they can use the VPI data load routine vpi_load() with the object’s vpiHandle to load the data for the specific object onto memory. Alternatively, for efficiency considerations, vpi_load() can be called with a design object collection handle of type vpiObjCollection. The collection must have already been created with vpi_create() and the (additional) selected object handles added... more
30.8.4 Reading an object | The sections above have outlined: — How to select an object for access, in other words, marking this object as a target for access. This is where the design navigation VPI is used. — How to call vpi_load_init() as a hint on the areas to be accessed, and/or optionally load an object into memory after obtaining a handle and then either loading objects individually or as a group using the object collection. — How to optionally iterate the design scope and the object collection to find the loaded objects if needed. In this section reading data is discussed. Reading an... more
30.8.5 Sample code using object (and traverse) collections |
30.8.6 Object-based traversal | Object based traversal can be performed by creating a traverse handle for the object and then moving it back and forth to the next or previous Value Change (VC) or by performing jumps in time. A traverse object handle for any object in the design can be obtained by calling vpi_handle() with a vpiTrvsObj type, and an object vpiHandle. This is the method described in Section 30.8.4, and used in all the code examples thus far. Using this method, the traversal would be object-based because the individual object traverse handles are created, and then the application can query the (value,... more
30.8.7 Time-ordered traversal | Alternatively, a user might wish to do a time-ordered traversal i.e. a time-based examination of values of several objects. This can be done by using a collection. The first step is to create a traverse collection of type vpiTrvsCollection of the objects to be traversed from the design object collection of type vpiObjCollection using vpi_handle() with a vpiTrvsCollection type and collection handle argument. vpi_goto() can then be called on the traverse collection to move to next or previous or do jump in time for the collection as a whole. A move to next (previous) VC means move to the next... more


主题

主题
30.12 VPI routines added in SystemVerilog
主题
主题 | 描述
30.12.1 VPI reader routines |


主题

主题
31.9 Ref Obj
主题
主题 | 描述
31.9.1 Examples | These objects are newly defined objects needed for supporting the full connectivity through ports where the ports are vpiInterface or vpiModport or any object inside modport or interface. RefObjs are dummy objects and they always have a handle to the original object.


主题

主题
31.25 Alias Statement
主题
主题 | 描述
31.25.1 Examples | alias a=b=c=d Results in 3 aliases: alias a=d alias b=d alias c=d d is Rhs for all.


主题

主题
A.1 源文本
主题
主题
描述
A.1.1 库源文本
A.1.2 配置源文本
A.1.3 模块和原语源文本
A.1.4 模块参数和端口
A.1.5 模块条目
A.1.6 接口条目
A.1.7 程序条目
A.1.8 类条目
A.1.9 Constraints
constraint_declaration ::= [ static ] constraint constraint_identifier constraint_block
constraint_block ::= { { constraint_block_item } }
constraint_block_item ::=
solve identifier_list before identifier_list ;
| constraint_expression
constraint_expression ::=
expression_or_dist ;
| expression –> constraint_set
| if ( expression ) constraint_set [ else constraint_set ]
| foreach ( array_identifier [ loop_variables ] ) constraint_set
constraint_set ::=
constraint_expression
| { { constraint_expression } }
dist_list ::= dist_item { , dist_item }
dist_item ::= value_range [ dist_weight ]
dist_weight ::=
:= expression
| :/ expression
constraint_prototype ::= [ static ] constraint constraint_identifier ;
extern_constraint_declaration ::=
[ static ] constraint class_scope constraint_identifier constraint_block
identifier_list ::= identifier... more
A.1.10 Package items
package_item ::=
package_or_generate_item_declaration
| specparam_declaration
| anonymous_program
| timeunits_declaration18
package_or_generate_item_declaration ::=
net_declaration
| data_declaration
| task_declaration
| function_declaration
| dpi_import_export
| extern_constraint_declaration
| class_declaration
| class_constructor_declaration
| parameter_declaration ;
| local_parameter_declaration
| covergroup_declaration
| overload_declaration
| concurrent_assertion_item_declaration
| ;
anonymous_program ::= program ; { anonymous_program_item } endprogram
anonymous_program_item ::=
task_declaration
| function_declaration
| class_declaration
| covergroup_declaration
| class_constructor_declaration
| ;


主题

主题
A.2.1 声明类型
主题
主题
描述
A.2.1.1 模块参数声明
A.2.1.2 Port declarations
inout_declaration ::=
inout port_type list_of_port_identifiers
input_declaration ::=
input port_type list_of_port_identifiers
| input data_type list_of_variable_identifiers
output_declaration ::=
output port_type list_of_port_identifiers
| output data_type list_of_variable_port_identifiers
interface_port_declaration ::=
interface_identifier list_of_interface_identifiers
| interface_identifier . modport_identifier list_of_interface_identifiers
ref_declaration ::= ref data_type list_of_port_identifiers
A.2.1.3 Type declarations
data_declaration15 ::=
[ const ] [ lifetime ] variable_declaration
| type_declaration
| package_import_declaration
| virtual_interface_declaration
package_import_declaration ::=
import package_import_item { , package_import_item } ;
package_import_item ::=
package_identifier :: identifier
| package_identifier :: *
genvar_declaration ::= genvar list_of_genvar_identifiers ;
net_declaration14 ::=
net_type_or_trireg [ drive_strength | charge_strength ] [ vectored | scalared ]
[ signing ] { packed_dimension } [ delay3 ] list_of_net_decl_assignments ;
type_declaration ::=
typedef data_type type_identifier variable_dimension ;
| typedef interface_instance_identifier . type_identifier type_identifer ;
| typedef [ enum | struct | union | class ] type_identifier ;
variable_declaration ::=
data_type list_of_variable_decl_assignments ;
lifetime ::= static | automatic


主题

主题
A.2.2 Declaration data types
主题
主题 | 描述
A.2.2.1 Net and variable types | casting_type ::= simple_type | size | signing data_type ::= integer_vector_type [ signing ] { packed_dimension } | integer_atom_type [ signing ] | non_integer_type | struct_union [ packed [ signing ] ] { struct_union_member { struct_union_member } } { packed_dimension }13 | enum [ enum_base_type ] { enum_name_declaration { , enum_name_declaration } } | string | chandle | virtual [ interface ] interface_identifier | [ class_scope | package_scope ] type_identifier { packed_dimension } | class_type | event | ps_covergroup_identifier data_type_or_implicit ::= data_type | [ signing ] { packed_dimension } enum_base_type ::= integer_atom_type [ signing ] | integer_vector_type [ signing ] [... more
A.2.2.2 Strengths | drive_strength ::= ( strength0 , strength1 ) | ( strength1 , strength0 ) | ( strength0 , highz1 ) | ( strength1 , highz0 ) | ( highz0 , strength1 ) | ( highz1 , strength0 ) strength0 ::= supply0 | strong0 | pull0 | weak0 strength1 ::= supply1 | strong1 | pull1 | weak1 charge_strength ::= ( small ) | ( medium ) | ( large )
A.2.2.3 Delays | delay3 ::= # delay_value | # ( mintypmax_expression [ , mintypmax_expression [ , mintypmax_expression ] ] ) delay2 ::= # delay_value | # ( mintypmax_expression [ , mintypmax_expression ] ) delay_value ::= unsigned_number | real_number | ps_identifier | time_literal


主题

主题
A.2 声明
主题
主题
描述
A.2.1 声明类型
A.2.2 Declaration data types
A.2.3 Declaration lists
list_of_defparam_assignments ::= defparam_assignment { , defparam_assignment }
list_of_genvar_identifiers ::= genvar_identifier { , genvar_identifier }
list_of_interface_identifiers ::= interface_identifier { unpacked_dimension }
{ , interface_identifier { unpacked_dimension } }
list_of_net_decl_assignments ::= net_decl_assignment { , net_decl_assignment }
list_of_net_identifiers ::= net_identifier { unpacked_dimension }
{ , net_identifier { unpacked_dimension } }
list_of_param_assignments ::= param_assignment { , param_assignment }
list_of_port_identifiers ::= port_identifier { unpacked_dimension }
{ , port_identifier { unpacked_dimension } }
list_of_udp_port_identifiers ::= port_identifier { , port_identifier }
list_of_specparam_assignments ::= specparam_assignment { , specparam_assignment }
list_of_tf_variable_identifiers ::= port_identifier variable_dimension [ = expression ]
{ , port_identifier variable_dimension [ = expression ] }
list_of_type_assignments ::=... more
A.2.4 Declaration assignments
defparam_assignment ::= hierarchical_parameter_identifier = constant_mintypmax_expression
net_decl_assignment ::= net_identifier { unpacked_dimension } [ = expression ]
param_assignment ::= parameter_identifier { unpacked_dimension } = constant_param_expression
specparam_assignment ::=
specparam_identifier = constant_mintypmax_expression
| pulse_control_specparam
type_assignment ::= type_identifier = data_type
pulse_control_specparam ::=
PATHPULSE$ = ( reject_limit_value [ , error_limit_value ] ) ;
| PATHPULSE$specify_input_terminal_descriptor$specify_output_terminal_descriptor
= ( reject_limit_value [ , error_limit_value ] ) ;
error_limit_value ::= limit_value
reject_limit_value ::= limit_value
limit_value ::= constant_mintypmax_expression
variable_decl_assignment ::=
variable_identifier variable_dimension [ = expression ]
| dynamic_array_variable_identifier [ ] [ = dynamic_array_new ]
| class_variable_identifier [ = class_new ]
| [ covergroup_variable_identifier ] = new [ ( list_of_arguments ) ]16... more
A.2.5 Declaration ranges
unpacked_dimension ::= [ constant_range ]
| [ constant_expression ]
packed_dimension11 ::=
[ constant_range ]
| unsized_dimension
associative_dimension ::=
[ data_type ]
| [ * ]
variable_dimension12 ::=
{ sized_or_unsized_dimension }
| associative_dimension
| queue_dimension
queue_dimension ::= [ $ [ : constant_expression ] ]
unsized_dimension11 ::= [ ]
sized_or_unsized_dimension ::= unpacked_dimension | unsized_dimension
A.2.6 Function declarations
function_data_type ::= data_type | void
function_data_type_or_implicit ::=
function_data_type
| [ signing ] { packed_dimension }
function_declaration ::= function [ lifetime ] function_body_declaration
function_body_declaration ::=
function_data_type_or_implicit
[ interface_identifier . | class_scope ] function_identifier ;
{ tf_item_declaration }
{ function_statement_or_null }
endfunction [ : function_identifier ]
| function_data_type_or_implicit
[ interface_identifier . | class_scope ] function_identifier ( [ tf_port_list ] ) ;
{ block_item_declaration }
{ function_statement_or_null }
endfunction [ : function_identifier ]
function_prototype ::= function function_data_type function_identifier ( [ tf_port_list ] )
dpi_import_export ::=
import "DPI" [ dpi_function_import_property ] [ c_identifier = ] dpi_function_proto ;
| import "DPI" [ dpi_task_import_property ] [... more
A.2.7 Task declarations
task_declaration ::= task [ lifetime ] task_body_declaration
task_body_declaration ::=
[ interface_identifier . | class_scope ] task_identifier ;
{ tf_item_declaration }
{ statement_or_null }
endtask [ : task_identifier ]
| [ interface_identifier . | class_scope ] task_identifier ( [ tf_port_list ] ) ;
{ block_item_declaration }
{ statement_or_null }
endtask [ : task_identifier ]
tf_item_declaration ::=
block_item_declaration
| tf_port_declaration
tf_port_list ::=
tf_port_item { , tf_port_item }
tf_port_item ::=
{ attribute_instance }
[ tf_port_direction ] data_type_or_implicit
port_identifier variable_dimension [ = expression ]
tf_port_direction ::= port_direction | const ref
tf_port_declaration ::=
{ attribute_instance } tf_port_direction data_type_or_implicit list_of_tf_variable_identifiers ;
task_prototype ::= task task_identifier (... more
A.2.8 Block item declarations
block_item_declaration ::=
{ attribute_instance } data_declaration
| { attribute_instance } local_parameter_declaration
| { attribute_instance } parameter_declaration ;
| { attribute_instance } overload_declaration
overload_declaration ::=
bind overload_operator function data_type function_identifier ( overload_proto_formals ) ;
overload_operator ::= + | ++ | – | – – | * | ** | / | % | == | != | < | <= | > | >= | =
overload_proto_formals ::= data_type {, data_type}
A.2.9 Interface declarations
virtual_interface_declaration ::=
virtual [ interface ] interface_identifier list_of_virtual_interface_decl ;
modport_declaration ::= modport modport_item { , modport_item } ;
modport_item ::= modport_identifier ( modport_ports_declaration { , modport_ports_declaration } )
modport_ports_declaration ::=
{ attribute_instance } modport_simple_ports_declaration
| { attribute_instance } modport_hierarchical_ports_declaration
| { attribute_instance } modport_tf_ports_declaration
| { attribute_instance } modport_clocking_declaration
modport_clocking_declaration ::= clocking clocking_identifier
modport_simple_ports_declaration ::=
port_direction modport_simple_port { , modport_simple_port }
modport_simple_port ::=
port_identifier
| . port_identifier ( [ expression ] )
modport_hierarchical_ports_declaration ::=
interface_instance_identifier [ [ constant_expression ] ] . modport_identifier
modport_tf_ports_declaration ::=
import_export modport_tf_port { , modport_tf_port }
modport_tf_port ::=
method_prototype
| tf_identifier
import_export ::= import | export... more
A.2.10 Assertion declarations
concurrent_assertion_item ::= [ block_identifier : ] concurrent_assertion_statement
concurrent_assertion_statement ::=
assert_property_statement
| assume_property_statement
| cover_property_statement
assert_property_statement::=
assert property ( property_spec ) action_block
assume_property_statement::=
assume property ( property_spec ) ;
cover_property_statement::=
cover property ( property_spec ) statement_or_null
expect_property_statement ::=
expect ( property_spec ) action_block
property_instance ::=
ps_property_identifier [ ( [ actual_arg_list ] ) ]
concurrent_assertion_item_declaration ::=
property_declaration
| sequence_declaration
property_declaration ::=
property property_identifier [ ( [ list_of_formals ] ) ] ;
{ assertion_variable_declaration }
property_spec ;
endproperty [ : property_identifier ]
property_spec ::=
[clocking_event ] [ disable iff ( expression_or_dist ) ] property_expr
property_expr ::=
sequence_expr
| ( property_expr )
| not... more
A.2.11 Covergroup declarations
covergroup_declaration ::=
covergroup covergroup_identifier [ ( [ tf_port_list ] ) ] [ coverage_event ] ;
{ coverage_spec_or_option ; }
endgroup [ : covergroup_identifier ]
coverage_spec_or_option ::=
{attribute_instance} coverage_spec
| {attribute_instance} coverage_option ;
coverage_option ::=
option.member_identifier = expression
| type_option.member_identifier = expression
coverage_spec ::=
cover_point
| cover_cross
coverage_event ::=
clocking_event
| @@( block_event_expression )
block_event_expression :: =
block_event_expression or block_event_expression
| begin hierarchical_btf_identifier
| end hierarchical_btf_identifier
hierarchical_btf_identifier :: =
hierarchical_tf_identifier
| hierarchical_block_identifier
| hierarchical _identifier [ class_scope ] method_identifier
cover_point ::= [ cover_point_identifer : ] coverpoint expression [ iff ( expression ) ] bins_or_empty
bins_or_empty ::=
{ {attribute_instance} { bins_or_options ;... more


主题

主题
A.3 Primitive instances
主题
主题
描述
A.3.1 Primitive instantiation and instances
gate_instantiation ::=
cmos_switchtype [delay3] cmos_switch_instance { , cmos_switch_instance } ;
| enable_gatetype [drive_strength] [delay3] enable_gate_instance { , enable_gate_instance } ;
| mos_switchtype [delay3] mos_switch_instance { , mos_switch_instance } ;
| n_input_gatetype [drive_strength] [delay2] n_input_gate_instance { , n_input_gate_instance } ;
| n_output_gatetype [drive_strength] [delay2] n_output_gate_instance
{ , n_output_gate_instance } ;
| pass_en_switchtype [delay2] pass_enable_switch_instance { , pass_enable_switch_instance } ;
| pass_switchtype pass_switch_instance { , pass_switch_instance } ;
| pulldown [pulldown_strength] pull_gate_instance { , pull_gate_instance } ;
| pullup [pullup_strength] pull_gate_instance { , pull_gate_instance } ;
cmos_switch_instance ::= [ name_of_instance ] ( output_terminal , input_terminal ,
ncontrol_terminal , pcontrol_terminal )
enable_gate_instance ::=... more
A.3.2 Primitive strengths
pulldown_strength ::=
( strength0 , strength1 )
| ( strength1 , strength0 )
| ( strength0 )
pullup_strength ::=
( strength0 , strength1 )
| ( strength1 , strength0 )
| ( strength1 )
A.3.3 Primitive terminals
enable_terminal ::= expression
inout_terminal ::= net_lvalue
input_terminal ::= expression
ncontrol_terminal ::= expression
output_terminal ::= net_lvalue
pcontrol_terminal ::= expression
A.3.4 Primitive gate and switch types
cmos_switchtype ::= cmos | rcmos
enable_gatetype ::= bufif0 | bufif1 | notif0 | notif1
mos_switchtype ::= nmos | pmos | rnmos | rpmos
n_input_gatetype ::= and | nand | or | nor | xor | xnor
n_output_gatetype ::= buf | not
pass_en_switchtype ::= tranif0 | tranif1 | rtranif1 | rtranif0
pass_switchtype ::= tran | rtran


主题

主题
A.4.1 Instantiation
主题
主题
描述
A.4.1.1 Module instantiation
module_instantiation ::=
module_identifier [ parameter_value_assignment ] hierarchical_instance { , hierarchical_instance } ;
parameter_value_assignment ::= # ( list_of_parameter_assignments )
list_of_parameter_assignments ::=
ordered_parameter_assignment { , ordered_parameter_assignment }
| named_parameter_assignment { , named_parameter_assignment }
ordered_parameter_assignment ::= param_expression
named_parameter_assignment ::= . parameter_identifier ( [ param_expression ] )
hierarchical_instance ::= name_of_instance ( [ list_of_port_connections ] )
name_of_instance ::= instance_identifier { unpacked_dimension }
list_of_port_connections17 ::=
ordered_port_connection { , ordered_port_connection }
| named_port_connection { , named_port_connection }
ordered_port_connection ::= { attribute_instance } [ expression ]
named_port_connection ::=
{ attribute_instance } . port_identifier [ ( [ expression ] ) ]
| { attribute_instance } .*
A.4.1.2 Interface instantiation
interface_instantiation ::=
interface_identifier [ parameter_value_assignment ] hierarchical_instance { , hierarchical_instance } ;
A.4.1.3 Program instantiation
program_instantiation ::=
program_identifier [ parameter_value_assignment ] hierarchical_instance { , hierarchical_instance } ;


主题

主题
A.4.2 Generated instantiation
主题
主题
描述
A.4.2.1 Generated module instantiation
generated_module_instantiation ::= generate { generate_module_item } endgenerate
generate_module_item ::=
generate_module_conditional_statement
| generate_module_case_statement
| generate_module_loop_statement
| [ generate_block_identifier : ] generate_module_block
| module_or_generate_item
generate_module_conditional_statement ::=
if ( constant_expression ) generate_module_item [ else generate_module_item ]
generate_module_case_statement ::=
case ( constant_expression ) genvar_module_case_item { genvar_module_case_item }endcase
genvar_module_case_item ::=
constant_expression { , constant_expression } : generate_module_item
| default [ : ] generate_module_item
generate_module_loop_statement ::=
for ( genvar_decl_assignment ; constant_expression ; genvar_assignment )
generate_module_named_block
genvar_assignment ::=
genvar_identifier assignment_operator constant_expression
| inc_or_dec_operator genvar_identifier
| genvar_identifier inc_or_dec_operator
genvar_decl_assignment ::=
[ genvar ] genvar_identifier = constant_expression
generate_module_named_block ::=
begin : generate_block_identifier { generate_module_item } end [ : generate_block_identifier... more
A.4.2.2 Generated interface instantiation
generated_interface_instantiation ::= generate { generate_interface_item } endgenerate
generate_interface_item ::=
generate_interface_conditional_statement
| generate_interface_case_statement
| generate_interface_loop_statement
| [ generate_block_identifier : ] generate_interface_block
| interface_or_generate_item
generate_interface_conditional_statement ::=
if ( constant_expression ) generate_interface_item [ else generate_interface_item ]
generate_interface_case_statement ::=
case ( constant_expression ) genvar_interface_case_item { genvar_interface_case_item } endcase
genvar_interface_case_item ::=
constant_expression { , constant_expression } : generate_interface_item
| default [ : ] generate_interface_item
generate_interface_loop_statement ::=
for ( genvar_decl_assignment ; constant_expression ; genvar_assignment )
generate_interface_named_block
generate_interface_named_block ::=
begin : generate_block_identifier { generate_interface_item } end [ : generate_block_identifier ]
| generate_block_identifier : generate_interface_block
generate_interface_block ::=
begin [ : generate_block_identifier ]
{ generate_interface_item }
end [ :... more


主题

主题
A.4 Module, interface and generated instantiation
主题
主题 | 描述
A.4.1 Instantiation |
A.4.2 Generated instantiation |


主题

主题
A.5 UDP declaration and instantiation
主题
主题
描述
A.5.1 UDP declaration
udp_nonansi_declaration ::=
{ attribute_instance } primitive udp_identifier ( udp_port_list ) ;
udp_ansi_declaration ::=
{ attribute_instance } primitive udp_identifier ( udp_declaration_port_list ) ;
udp_declaration ::=
udp_nonansi_declaration udp_port_declaration { udp_port_declaration }
udp_body
endprimitive [ : udp_identifier ]
| udp_ansi_declaration
udp_body
endprimitive [ : udp_identifier ]
| extern udp_nonansi_declaration
| extern udp_ansi_declaration
| { attribute_instance } primitive udp_identifier ( .* ) ;
{ udp_port_declaration }
udp_body
endprimitive [ : udp_identifier ]
A.5.2 UDP ports
udp_port_list ::= output_port_identifier , input_port_identifier { , input_port_identifier }
udp_declaration_port_list ::= udp_output_declaration , udp_input_declaration { , udp_input_declaration }
udp_port_declaration ::=
udp_output_declaration ;
| udp_input_declaration ;
| udp_reg_declaration ;
udp_output_declaration ::=
{ attribute_instance } output port_identifier
| { attribute_instance } output reg port_identifier [ = constant_expression ]
udp_input_declaration ::= { attribute_instance } input list_of_udp_port_identifiers
udp_reg_declaration ::= { attribute_instance } reg variable_identifier
A.5.3 UDP body
udp_body ::= combinational_body | sequential_body
combinational_body ::= table combinational_entry { combinational_entry } endtable
combinational_entry ::= level_input_list : output_symbol ;
sequential_body ::= [ udp_initial_statement ] table sequential_entry { sequential_entry } endtable
udp_initial_statement ::= initial output_port_identifier = init_val ;
init_val ::= 1’b0 | 1’b1 | 1’bx | 1’bX | 1’B0 | 1’B1 | 1’Bx | 1’BX | 1 | 0
sequential_entry ::= seq_input_list : current_state : next_state ;
seq_input_list ::= level_input_list | edge_input_list
level_input_list ::= level_symbol { level_symbol }
edge_input_list ::= { level_symbol } edge_indicator { level_symbol }
edge_indicator ::= ( level_symbol level_symbol ) | edge_symbol
current_state ::= level_symbol
next_state ::= output_symbol... more
A.5.4 UDP instantiation
udp_instantiation ::= udp_identifier [ drive_strength ] [ delay2 ] udp_instance { , udp_instance } ;
udp_instance ::= [ name_of_instance ] ( output_terminal , input_terminal { , input_terminal } )


主题

主题
A.6.7 Case statements
主题
主题 | 描述
A.6.7.1 Patterns | pattern ::= variable_identifier | .* | . constant_expression | tagged member_identifier [ pattern ] | { pattern { , pattern } } | { member_identifier : pattern { , member_identifier : pattern } }


主题

主题
A.6 Behavioral statements
主题
主题
描述
A.6.1 Continuous assignment and net alias statements
continuous_assign ::=
assign [ drive_strength ] [ delay3 ] list_of_net_assignments ;
| assign [ delay_control ] list_of_variable_assignments ;
list_of_net_assignments ::= net_assignment { , net_assignment }
list_of_variable_assignments ::= variable_assignment { , variable_assignment }
net_alias ::= alias net_lvalue = net_lvalue { = net_lvalue } ;
net_assignment ::= net_lvalue = expression
A.6.2 Procedural blocks and assignments
initial_construct ::= initial statement_or_null
always_construct ::= always_keyword statement
always_keyword ::= always | always_comb | always_latch | always_ff
blocking_assignment ::=
variable_lvalue = delay_or_event_control expression
| hierarchical_dynamic_array_variable_identifier = dynamic_array_new
| [ implicit_class_handle . | class_scope | package_scope ] hierarchical_variable_identifier
select = class_new
| operator_assignment
operator_assignment ::= variable_lvalue assignment_operator expression
assignment_operator ::=
= | += | -= | *= | /= | %= | &= | |= | ^= | <<= | >>= | <<<= | >>>=
nonblocking_assignment ::= variable_lvalue <= [ delay_or_event_control ] expression
procedural_continuous_assignment ::=
assign variable_assignment
| deassign variable_lvalue
| force variable_assignment
| force net_assignment
| release variable_lvalue
| release... more
A.6.3 Parallel and sequential blocks
action_block ::=
statement_or_null
| [ statement ] else statement_or_null
seq_block ::=
begin [ : block_identifier ] { block_item_declaration } { statement_or_null }
end [ : block_identifier ]
par_block ::=
fork [ : block_identifier ] { block_item_declaration } { statement_or_null }
join_keyword [ : block_identifier ]
join_keyword ::= join | join_any | join_none
A.6.4 Statements
statement_or_null ::=
statement
| { attribute_instance } ;
statement ::= [ block_identifier : ] { attribute_instance } statement_item
statement_item ::=
blocking_assignment ;
| nonblocking_assignment ;
| procedural_continuous_assignment ;
| case_statement
| conditional_statement
| inc_or_dec_expression ;
| subroutine_call_statement
| disable_statement
| event_trigger
| loop_statement
| jump_statement
| par_block
| procedural_timing_control_statement
| seq_block
| wait_statement
| procedural_assertion_statement
| clocking_drive ;
| randsequence_statement
| randcase_statement
| expect_property_statement
function_statement ::= statement
function_statement_or_null ::=
function_statement
| { attribute_instance } ;
variable_identifier_list ::= variable_identifier { , variable_identifier }
A.6.5 Timing control statements
procedural_timing_control_statement ::=
procedural_timing_control statement_or_null
delay_or_event_control ::=
delay_control
| event_control
| repeat ( expression ) event_control
delay_control ::=
# delay_value
| # ( mintypmax_expression )
event_control ::=
@hierarchical_event_identifier
| @ ( event_expression )
| @*
| @ (*)
| @ sequence_instance
event_expression ::=
[ edge_identifier ] expression [ iff expression ]
| sequence_instance [ iff expression ]
| event_expression or event_expression
| event_expression , event_expression
procedural_timing_control ::=
delay_control
| event_control
| cycle_delay
jump_statement ::=
return [ expression ] ;
| break ;
| continue ;
wait_statement ::=
wait ( expression ) statement_or_null
| wait fork ;
| wait_order ( hierarchical_identifier [... more
A.6.6 Conditional statements
conditional_statement ::=
if ( cond_predicate ) statement_or_null [ else statement_or_null ]
| unique_priority_if_statement
unique_priority_if_statement ::=
[ unique_priority ] if ( cond_predicate ) statement_or_null
{ else if ( cond_predicate ) statement_or_null }
[ else statement_or_null ]
unique_priority ::= unique | priority
cond_predicate ::=
expression_or_cond_pattern { && expression_or_cond_pattern }
expression_or_cond_pattern ::=
expression | cond_pattern
cond_pattern ::= expression matches pattern
A.6.7 Case statements
case_statement ::=
[ unique_priority ] case_keyword ( expression ) case_item { case_item } endcase
| [ unique_priority ] case_keyword ( expression ) matches case_pattern_item { case_pattern_item }
endcase
case_keyword ::= case | casez | casex
case_item ::=
expression { , expression } : statement_or_null
| default [ : ] statement_or_null
case_pattern_item ::=
pattern [ && expression ] : statement_or_null
| default [ : ] statement_or_null
randcase_statement ::=
randcase randcase_item { randcase_item } endcase
randcase_item ::= expression : statement_or_null
A.6.8 Looping statements
loop_statement ::=
forever statement_or_null
| repeat ( expression ) statement_or_null
| while ( expression ) statement_or_null
| for ( for_initialization ; expression ; for_step )
statement_or_null
| do statement_or_null while ( expression ) ;
| foreach ( array_identifier [ loop_variables ] ) statement
for_initialization ::=
list_of_variable_assignments
| data_type list_of_variable_assignments { , data_type list_of_variable_assignments }
for_step ::= for_step_assignment { , for_step_assignment }
for_step_assignment ::=
operator_assignment
| inc_or_dec_expression
loop_variables ::= [ index_variable_identifier ] { , [ index_variable_identifier ] }
A.6.9 Subroutine call statements
subroutine_call_statement :=
subroutine_call ;
| void ’ ( function_subroutine_call ) ;
A.6.10 Assertion statements
procedural_assertion_statement ::=
concurrent_assertion_statement
| immediate_assert_statement
immediate_assert_statement ::=
assert ( expression ) action_block
A.6.11 Clocking block
clocking_declaration ::= [ default ] clocking [ clocking_identifier ] clocking_event ;
{ clocking_item }
endclocking [ : clocking_identifier ]
clocking_event ::=
@identifier
| @ ( event_expression )
clocking_item :=
default default_skew ;
| clocking_direction list_of_clocking_decl_assign ;
| { attribute_instance } concurrent_assertion_item_declaration
default_skew ::=
input clocking_skew
| output clocking_skew
| input clocking_skew output clocking_skew
clocking_direction ::=
input [ clocking_skew ]
| output [ clocking_skew ]
| input [ clocking_skew ] output [ clocking_skew ]
| inout
list_of_clocking_decl_assign ::= clocking_decl_assign { , clocking_decl_assign }
clocking_decl_assign ::= signal_identifier [ = hierarchical_identifier ]
clocking_skew ::=
edge_identifier [ delay_control ]
| delay_control
clocking_drive ::=
clockvar_expression... more
A.6.12 Randsequence
randsequence_statement ::= randsequence ( [ production_ identifier ] )
production { production }
endsequence
production ::= [ function_data_type ] production_name [ ( tf_port_list ) ] : rs_rule { | rs_rule } ;
rs_rule ::= rs_production_list [ := expression [ rs_code_block ] ]
rs_production_list ::=
rs_prod { rs_prod }
| rand join [ ( expression ) ] production_item production_item { production_item }
rs_code_block ::= { { data_declaration } { statement_or_null } }
rs_prod ::=
production_item
| rs_code_block
| rs_if_else
| rs_repeat
| rs_case
production_item ::= production_identifier [ ( list_of_arguments ) ]
rs_if_else ::= if ( expression ) production_item [ else production_item... more


主题

主题
A.7.5 System timing checks
主题
主题
描述
A.7.5.1 System timing check commands
system_timing_check ::=
$setup_timing_check
| $hold_timing_check
| $setuphold_timing_check
| $recovery_timing_check
| $removal_timing_check
| $recrem_timing_check
| $skew_timing_check
| $timeskew_timing_check
| $fullskew_timing_check
| $period_timing_check
| $width_timing_check
| $nochange_timing_check
$setup_timing_check ::=
$setup ( data_event , reference_event , timing_check_limit [ , [ notifier ] ] ) ;
$hold_timing_check ::=
$hold ( reference_event , data_event , timing_check_limit [ , [ notifier ] ] ) ;
$setuphold_timing_check ::=
$setuphold ( reference_event , data_event , timing_check_limit , timing_check_limit
[ , [ notifier ] [ , [ stamptime_condition ] [ , [ checktime_condition ]
[ , [ delayed_reference ] [ , [ delayed_data ] ] ] ] ] ]... more
A.7.5.2 System timing check command arguments
checktime_condition ::= mintypmax_expression
controlled_reference_event ::= controlled_timing_check_event
data_event ::= timing_check_event
delayed_data ::=
terminal_identifier
| terminal_identifier [ constant_mintypmax_expression ]
delayed_reference ::=
terminal_identifier
| terminal_identifier [ constant_mintypmax_expression ]
end_edge_offset ::= mintypmax_expression
event_based_flag ::= constant_expression
notifier ::= variable_identifier
reference_event ::= timing_check_event
remain_active_flag ::= constant_mintypmax_expression
stamptime_condition ::= mintypmax_expression
start_edge_offset ::= mintypmax_expression
threshold ::=constant_expression
timing_check_limit ::= expression
A.7.5.3 System timing check event definitions
timing_check_event ::=
[timing_check_event_control] specify_terminal_descriptor [ &&& timing_check_condition ]
controlled_timing_check_event ::=
timing_check_event_control specify_terminal_descriptor [ &&& timing_check_condition ]
timing_check_event_control ::=
posedge
| negedge
| edge_control_specifier
specify_terminal_descriptor ::=
specify_input_terminal_descriptor
| specify_output_terminal_descriptor
edge_control_specifier ::= edge [ edge_descriptor { , edge_descriptor } ]
edge_descriptor1 ::= 01 | 10 | z_or_x zero_or_one | zero_or_one z_or_x
zero_or_one ::= 0 | 1
z_or_x ::= x | X | z | Z
timing_check_condition ::=
scalar_timing_check_condition
| ( scalar_timing_check_condition )
scalar_timing_check_condition ::=
expression
| ~ expression
| expression == scalar_constant
| expression === scalar_constant
| expression != scalar_constant
| expression !== scalar_constant
scalar_constant ::= 1’b0 | 1’b1 | 1’B0 |... more


主题

主题
A.7 Specify section
主题
主题
描述
A.7.1 Specify block declaration
specify_block ::= specify { specify_item } endspecify
specify_item ::=
specparam_declaration
| pulsestyle_declaration
| showcancelled_declaration
| path_declaration
| system_timing_check
pulsestyle_declaration ::=
pulsestyle_onevent list_of_path_outputs ;
| pulsestyle_ondetect list_of_path_outputs ;
showcancelled_declaration ::=
showcancelled list_of_path_outputs ;
| noshowcancelled list_of_path_outputs ;
A.7.2 Specify path declarations
path_declaration ::=
simple_path_declaration ;
| edge_sensitive_path_declaration ;
| state_dependent_path_declaration ;
simple_path_declaration ::=
parallel_path_description = path_delay_value
| full_path_description = path_delay_value
parallel_path_description ::=
( specify_input_terminal_descriptor [ polarity_operator ] => specify_output_terminal_descriptor )
full_path_description ::=
( list_of_path_inputs [ polarity_operator ] *> list_of_path_outputs )
list_of_path_inputs ::=
specify_input_terminal_descriptor { , specify_input_terminal_descriptor }
list_of_path_outputs ::=
specify_output_terminal_descriptor { , specify_output_terminal_descriptor }
A.7.3 Specify block terminals
specify_input_terminal_descriptor ::=
input_identifier [ [ constant_range_expression ] ]
specify_output_terminal_descriptor ::=
output_identifier [ [ constant_range_expression ] ]
input_identifier ::= input_port_identifier | inout_port_identifier | interface_identifier.port_identifier
output_identifier ::= output_port_identifier | inout_port_identifier | interface_identifier.port_identifier
A.7.4 Specify path delays
path_delay_value ::=
list_of_path_delay_expressions
| ( list_of_path_delay_expressions )
list_of_path_delay_expressions ::=
t_path_delay_expression
| trise_path_delay_expression , tfall_path_delay_expression
| trise_path_delay_expression , tfall_path_delay_expression , tz_path_delay_expression
| t01_path_delay_expression , t10_path_delay_expression , t0z_path_delay_expression ,
tz1_path_delay_expression , t1z_path_delay_expression , tz0_path_delay_expression
| t01_path_delay_expression , t10_path_delay_expression , t0z_path_delay_expression ,
tz1_path_delay_expression , t1z_path_delay_expression , tz0_path_delay_expression ,
t0x_path_delay_expression , tx1_path_delay_expression , t1x_path_delay_expression ,
tx0_path_delay_expression , txz_path_delay_expression , tzx_path_delay_expression
t_path_delay_expression ::= path_delay_expression
trise_path_delay_expression ::= path_delay_expression
tfall_path_delay_expression ::= path_delay_expression
tz_path_delay_expression ::= path_delay_expression
t01_path_delay_expression ::= path_delay_expression
t10_path_delay_expression ::= path_delay_expression
t0z_path_delay_expression ::= path_delay_expression
tz1_path_delay_expression ::= path_delay_expression
t1z_path_delay_expression ::= path_delay_expression
tz0_path_delay_expression ::= path_delay_expression
t0x_path_delay_expression ::= path_delay_expression
tx1_path_delay_expression ::= path_delay_expression
t1x_path_delay_expression ::= path_delay_expression
tx0_path_delay_expression ::= path_delay_expression
txz_path_delay_expression ::=... more
A.7.5 System timing checks


主题

主题
A.8 Expressions
主题
主题
描述
A.8.1 Concatenations
concatenation ::=
{ expression { , expression } }
| { struct_member_label : expression { , struct_member_label : expression } }
| { array_member_label : expression { , array_member_label : expression } }
constant_concatenation ::=
{ constant_expression { , constant_expression } }
| { struct_member_label : constant_expression { , struct_member_label : constant_expression } }
| { array_member_label : constant_expression { , array_member_label : constant_expression } }
struct_member_label ::=
default
| type_identifier
| variable_identifier
array_member_label ::=
default
| type_identifier
| constant_expression
constant_multiple_concatenation ::= { constant_expression constant_concatenation }
module_path_concatenation ::= { module_path_expression { , module_path_expression } }
module_path_multiple_concatenation ::= { constant_expression module_path_concatenation... more
A.8.2 Subroutine calls
constant_function_call ::= function_subroutine_call25
tf_call ::= ps_or_hierarchical_tf_identifier { attribute_instance } [ ( list_of_arguments ) ]
system_tf_call ::= system_tf_identifier [ ( list_of_arguments ) ]
subroutine_call ::=
tf_call
| system_tf_call
| method_call
| randomize_call
function_subroutine_call ::= subroutine_call
list_of_arguments ::=
[ expression ] { , [ expression ] } { , . identifier ( [ expression ] ) }
| . identifier ( [ expression ] ) { , . identifier ( [ expression ] ) }
method_call ::= method_call_root . method_call_body
method_call_body ::=
method_identifier { attribute_instance } [ ( list_of_arguments ) ]
| built_in_method_call
built_in_method_call ::=
array_manipulation_call
| randomize_call
array_manipulation_call ::=
array_method_name {... more
A.8.3 Expressions
inc_or_dec_expression ::=
inc_or_dec_operator { attribute_instance } variable_lvalue
| variable_lvalue { attribute_instance } inc_or_dec_operator
conditional_expression ::= cond_predicate ? { attribute_instance } expression : expression
constant_expression ::=
constant_primary
| unary_operator { attribute_instance } constant_primary
| constant_expression binary_operator { attribute_instance } constant_expression
| constant_expression ? { attribute_instance } constant_expression : constant_expression
constant_mintypmax_expression ::=
constant_expression
| constant_expression : constant_expression : constant_expression
constant_param_expression ::=
constant_mintypmax_expression | data_type | $
param_expression ::= mintypmax_expression | data_type
constant_range_expression ::=
constant_expression
| constant_part_select_range
constant_part_select_range ::=
constant_range
| constant_indexed_range
constant_range ::= constant_expression : constant_expression
constant_indexed_range ::=
constant_expression +: constant_expression
| constant_expression -: constant_expression
expression ::=
primary
| unary_operator { attribute_instance... more
A.8.4 Primaries
constant_primary ::=
primary_literal
| ps_parameter_identifier
| ps_specparam_identifier
| genvar_identifier
| [ package_scope | class_scope ] enum_identifier
| constant_concatentation
| constant_multiple_concatenation
| constant_function_call
| ( constant_mintypmax_expression )
| constant_cast
module_path_primary ::=
number
| identifier
| module_path_concatenation
| module_path_multiple_concatenation
| function_subroutine_call
| ( module_path_mintypmax_expression )
primary ::=
primary_literal
| [ implicit_class_handle . | class_scope | package_scope ] hierarchical_identifier select
| empty_queue
| concatenation
| multiple_concatenation
| function_subroutine_call
| ( mintypmax_expression )
| cast
| streaming_expression
| sequence_method_call
| $23
| null
time_literal5 ::=
unsigned_number time_unit
| fixed_point_number time_unit
time_unit ::= s | ms | us | ns | ps | fs |... more
A.8.5 Expression left-side values
net_lvalue ::=
ps_or_hierarchical_net_identifier constant_select
| { net_lvalue { , net_lvalue } }
variable_lvalue ::=
[ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select
| { variable_lvalue { , variable_lvalue } }
A.8.6 Operators
unary_operator ::=
+ | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
binary_operator ::=
+ | - | * | / | % | == | != | === | !== | =?= | !?= | && | || | **
| < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<
inc_or_dec_operator ::= ++ | --
unary_module_path_operator ::=
! | ~ | & | ~& | | | ~| | ^ | ~^... more
A.8.7 Numbers
number ::=
integral_number
| real_number
integral_number ::=
decimal_number
| octal_number
| binary_number
| hex_number
decimal_number ::=
unsigned_number
| [ size ] decimal_base unsigned_number
| [ size ] decimal_base x_digit { _ }
| [ size ] decimal_base z_digit { _ }
binary_number ::= [ size ] binary_base binary_value
octal_number ::= [ size ] octal_base octal_value
hex_number ::= [ size ] hex_base hex_value
sign ::= + | -
size ::= non_zero_unsigned_number
non_zero_unsigned_number1 ::= non_zero_decimal_digit { _ | decimal_digit}
real_number1 ::=
fixed_point_number
| unsigned_number [ . unsigned_number ] exp [ sign ] unsigned_number
fixed_point_number1 ::= unsigned_number . unsigned_number
exp ::= e |... more
A.8.8 Strings
string_literal ::= " { Any_ASCII_Characters }


主题

主题
A.9 General
主题
主题
描述
A.9.1 Attributes
attribute_instance ::= (* attr_spec { , attr_spec } *)
attr_spec ::= attr_name [ = constant_expression ]
attr_name ::= identifier
A.9.2 Comments
comment ::=
one_line_comment
| block_comment
one_line_comment ::= // comment_text \n
block_comment ::= /* comment_text */
comment_text ::= { Any_ASCII_character }
A.9.3 Identifiers
array_identifier ::= identifier
block_identifier ::= identifier
bin_identifier ::= identifier
c_identifier2 ::= [ a-zA-Z_ ] { [ a-zA-Z0-9_ ] }
cell_identifier ::= identifier
class_identifier ::= identifier
class_variable_identifier ::= variable_identifier
clocking_identifier ::= identifier
config_identifier ::= identifier
constraint_identifier ::= identifier
covergroup_identifier ::= identifier
covergroup_variable_identifier ::= variable_identifier
cover_point_identifier ::= identifier
dynamic_array_variable_identifier ::= variable_identifier
enum_identifier ::= identifier
escaped_identifier ::= \ {any_ASCII_character_except_white_space} white_space
formal_identifier ::= identifier
function_identifier ::= identifier
generate_block_identifier ::= identifier
genvar_identifier ::= identifier
hierarchical_block_identifier ::= hierarchical_identifier
hierarchical_dynamic_array_variable_identifier ::= hierarchical_variable_identifier
hierarchical_event_identifier ::= hierarchical_identifier
hierarchical_identifier ::= [ $root . ] { identifier { [ constant_expression ] } . } identifier
hierarchical_net_identifier ::= hierarchical_identifier
hierarchical_parameter_identifier ::= hierarchical_identifier... more
A.9.4 White space
white_space ::= space | tab | newline | eof4


主题

主题
D.2 List declaration
主题
主题 | 描述
D.2.1 Declaring list variables | List variables are declared by providing a specialization of the generic list class:
D.2.2 Declaring list iterators | List iterators are declared by providing a specialization of the generic List_Iterator class:


主题

主题
D.3 Linked list class prototypes
主题
主题
描述
D.3.1 List_Iterator class prototype
D.3.2 List class prototype
class List#(parameter type T);
extern function new();
extern function int size();
extern function int empty();
extern function void push_front( T value );
extern function void push_back( T value );
extern function T front();
extern function T back();
extern function void pop_front();
extern function void pop_back();
extern function List_Iterator#(T) start();
extern function List_Iterator#(T) finish();
extern function void insert( List_Iterator#(T) position, T value );
extern function void insert_range( List_Iterator#(T) position,
first, last );
extern function void erase( List_Iterator#(T) position );
extern function void erase_range( List_Iterator#(T) first, last );
extern function void set( List_Iterator#(T) first, last );
extern function void swap( List#(T) lst... more


主题

主题
D.4 List_Iterator methods
主题
主题
描述
D.4.1 next()
function void next();
next changes the iterator so that it refers to the next element in the list.
D.4.2 prev()
function void prev();
prev changes the iterator so that it refers to the previous element in the list.
D.4.3 eq()
function int eq( List_Iterator#(T) iter );
eq compares two iterators, and returns 1 if both iterators refer to the same list element. Otherwise, it returns 0.
if( i1.eq(i2) ) $display("both iterators refer to the same element");
D.4.4 neq()
D.4.5 data()
function T data();
data returns the data stored in the element at the given iterator location.


主题

主题
D.5 List methods
主题
主题
描述
D.5.1 size()
function int size();
size returns the number of elements stored in the list.
while ( list1.size > 0 ) begin // loop while still elements in the list
...
end
D.5.2 empty()
function int empty();
empty returns 1 if the number elements stored in the list is zero, 0 otherwise.
if ( list1.empty )
$display( "list is empty" );
D.5.3 push_front()
function void push_front( T value );
push_front inserts the specified value at the front of the list.
List#(int) numbers;
numbers.push_front(10);
numbers.push_front(5); // numbers contains { 5 , 10 }
D.5.4 push_back()
function void push_back( T value );
push_back inserts the specified value at the end of the list.
List#(string) names;
names.push_back("Donald");
names.push_back("Mickey"); // names contains { "Donald", "Mickey" }
D.5.5 front()
function T front();
front returns the data stored in the first element of the list (valid only if the list is not empty).
D.5.6 back()
function T back();
back returns the data stored in the last element of the list (valid only if the list is not empty).
List#(int) numbers;
numbers.push_front(3);
numbers.push_front(2);
numbers.push_front(1);
$display( numbers.front, numbers.back ); // displays 1 3
D.5.7 pop_front()
function void pop_front();
pop_front removes the first element of the list. If the list is empty, this method is illegal and can generate an error.
D.5.8 pop_back()
function void pop_back();
pop_back removes the last element of the list. If the list is empty, this method is illegal and can generate an error.
while ( lp.size > 1 ) begin // remove all but the center element from
// an odd-sized list lp
lp.pop_front();
lp.pop_back();
end
D.5.9 start()
function List_Iterator#(T) start();
start returns an iterator to the position of the first element in the list.
D.5.10 finish()
function List_Iterator#(T) finish();
finish returns an iterator to a position just past the last element in the list. The last element in the last can be accessed using finish.prev.
List#(int) lst; // display contents of list lst in position order
for ( List_Iterator#(int) p = lst.start; p.neq(lst.finish); p.next )
$display( p.data );
D.5.11 insert()
function void insert( List_Iterator#(T) position, T value );
insert inserts the given data (value) into the list at the position specified by the iterator (before the element, if any, that was previously at the iterator’s position). If the iterator is not a valid position within the list, then this operation is illegal and can generate an error.
function void add_sort( List#(byte) L, byte value );
for ( List_Iterator#(byte) p = L.start; p.neq(L.finish) ; p.next )
if ( p.data > value ) begin
lst.insert( p, value ); // Add to sorted list (ascending order)
return;
end
endfunction
D.5.12 insert_range()
function void insert_range( List_Iterator#(T) position, first, last );
insert_range inserts the elements contained in the list range specified by the iterators first and last at the specified list position (before the element, if any, that was previously at the position iterator). All the elements from first up to, but not including, last are inserted into the list. If the last iterator refers to an element before the first iterator, the range wraps around the end of the list. The range iterators can specify a range either in another list or in the same list as being inserted.

If the position... more
D.5.13 erase()
function void erase( List_Iterator#(T) position );
erase removes form the list the element at the specified position. After erase() returns, the position iterator becomes invalid.
list1.erase( list1.start ); // same as pop_front
If the position iterator is not a valid position within the list, this operation is illegal and can generate an error.
D.5.14 erase_range()
function void erase_range( List_Iterator#(T) first, last );
erase_range removes from a list the range of elements specified by the first and last iterators. This operation removes elements from the first iterator’s position up to, but not including, the last iterator’s position. If the last iterator refers to an element before the first iterator, the range wraps around the end of the list.
list1.erase_range( list1.start, list1.finish ); // Remove all elements from
// list1
If the range iterators are invalid (i.e., they refer to different lists or to invalid positions), then this operation is illegal and can generate an error.
D.5.15 set()
function void set( List_Iterator#(T) first, last );
set assigns to the list object the elements that lie in the range specified by the first and last iterators. After this method returns, the modified list shall have a size equal to the range specified by first and last. This method copies the data from the first iterator’s position up to, but not including, the last iterator’s position. If the last iterator refers to an element before the first iterator, the range wraps around the end of the list.
list2.set( list1.start, list2.finish ); // list2 is a copy of list1
If the... more
D.5.16 swap()
function void swap( List#(T) lst );
swap exchanges the contents of two equal-size lists.
list1.swap( list2 ); // swap the contents of list1 to list2 and vice-versa
Swapping a list with itself has no effect. If the lists are of different sizes, this method can issue a warning.
D.5.17 clear()
function void clear();
clear removes all the elements from a list, but not the list itself (i.e., the list header itself).
list1.clear(); // list1 becomes empty
D.5.18 purge()
function void purge();
purge removes all the list elements (as in clear) and the list itself. This accomplishes the same effect as assigning null to the list. A purged list must be re-created using new before it can be used again.
list1.purge(); // same as list1 = null


主题

主题
E.3 Portability
主题
主题 | 描述
E.3.1 Binary compatibility | Binary compatibility means an application compiled for a given platform shall work with every SystemVerilog simulator on that platform.
E.3.2 Source-level compatibility | Source-level compatibility means an application needs to be re-compiled for each SystemVerilog simulator andimplementation-specific definitions shall be required for the compilation.


主题

主题
E.4 Include files
主题
主题 | 描述
E.4.1 svdpi.h include file | Applications which use the Direct Programming Interface with C code usually need this main include file. The include file svdpi.h defines the types for canonical representation of 2-state (bit) and 4-state (logic) values and passing references to SystemVerilog data objects. The file also provides function headers and defines a number of helper macros and constants. This document fully defines the svdpi.h file. The content of svdpi.h does not depend on any particular implementation or platform; all simulators shall use the same file. For more details on svdpi.h, see Annex E.9.1. Applications which only use svdpi.h shall be binary-compatible with all... more
E.4.2 svdpi_src.h include file | This is an auxiliary include file. svdpi_src.h defines data structures for implementation-specific representation of 2-state and 4-state SystemVerilog packed arrays. The interface specifies the contents of this file, i.e., what symbols are defined. The actual definitions of those symbols, however, are implementation-specific and shall be provided by vendors. Applications that require the svdpi_src.h file are only source-level compatible, i.e., they need to be compiled with the version of svdpi_src.h provided for a particular implementation of SystemVerilog. If, however, an application makes use of the details of the implementation-specific representation of packed arrays and thus it requires vendor specific include files,... more


主题

主题
E.5 Semantic constraints
主题
主题 | 描述
E.5.1 Types of formal arguments | The principle “What You Specify Is What You Get” guarantees the types of formal arguments of imported functions — an actual argument is guaranteed to be of the type specified for the formal argument, with the exception of open arrays (for which unspecified ranges are statically unknown). Formal arguments, other than open arrays, are fully defined by imported declaration; they shall have ranges of packed or unpacked arrays exactly as specified in the imported declaration. Only the SystemVerilog declaration site of the imported function is relevant for such formal arguments. Formal arguments defined as open arrays have the size and... more
E.5.2 input arguments | Formal arguments specified in SystemVerilog as input must not be modified by the foreign language code. See also Section 27.4.1.2.
E.5.3 output arguments | The initial values of formal arguments specified in SystemVerilog as output are undetermined and implementation-dependent. See also Section 27.4.1.2.
E.5.4 Value changes for output and inout arguments | The SystemVerilog simulator is responsible for handling value changes for output and inout arguments. Such changes shall be detected and handled after the control returns from C code to SystemVerilog code.
E.5.5 context and non-context tasks and functions | Also refer to Section 27.4.3. Some DPI imported tasks or functions or other interface functions called from them require that the context of their call be known. It takes special instrumentation of their call instances to provide such context; for example, a variable referring to the “current instance” might need to be set. To avoid any unnecessary overhead, imported tasks and function calls in SystemVerilog code are not instrumented unless the imported tasks or function is specified as context in its SystemVerilog import declaration. All DPI export tasks and functions require that the context of their call is known. This... more
E.5.6 pure functions | See also Section 27.4.2. Only non-void functions with no output or inout arguments can be specified as pure. Functions specified as pure in their corresponding SystemVerilog import declarations shall have no side effects; their results need to depend solely on the values of their input arguments. Calls to such functions can be removed by SystemVerilog compiler optimizations or replaced with the values previously computed for the same values of the input arguments. Specifically, a pure function is assumed not to directly or indirectly (i.e., by calling other functions): — perform any file operations — read or write anything in the... more
E.5.7 Memory management | See also Section 27.4.1.4. The memory spaces owned and allocated by C code and SystemVerilog code are disjoined. Each side is responsible for its own allocated memory. Specifically, C code shall not free the memory allocated by SystemVerilog code (or the SystemVerilog compiler) nor expect SystemVerilog code to free the memory allocated by C code (or the C compiler). This does not exclude scenarios in which C code allocates a block of memory, then passes a handle (i.e., a pointer) to that block to SystemVerilog code, which in turn calls a C function that directly (if it is the standard... more


主题

主题
E.6 Data types
主题
主题
描述
E.6.1 Limitations
Packed arrays can have an arbitrary number of dimensions; though they are eventually always equivalent to a one-dimensional packed array and treated as such. If the packed part of an array in the type of a formal argument in SystemVerilog is specified as multi-dimensional, the SystemVerilog compiler linearizes it. Although the original ranges are generally preserved for open arrays, if the actual argument has a multidimensional packed part of the array, it shall be normalized into an equivalent one-dimensional packed array.

NOTE—The actual argument can have both packed and unpacked parts of an array; either can be multidimensional.
E.6.2 Duality of types: SystemVerilog types vs. C types
A value that crosses the Direct Programming Interface is specified in SystemVerilog code as a value of SystemVerilog type, while the same value shall be specified in C code as a value of C type. Therefore, each data type that is passed through the Direct Programming Interface requires two matching type definitions: the SystemVerilog definition and C definition.

The user needs to provide such matching definitions. Specifically, for each SystemVerilog type used in the import declarations or export declarations in SystemVerilog code, the user shall provide the equivalent type definition in C reflecting the argument passing mode for the particular... more
E.6.3 Data representation
DPI imposes the following additional restrictions on the representation of SystemVerilog data types.
  • SystemVerilog types that are not packed and that do not contained packed elements have C compatible representation.
  • Basic integer and real data types are represented as defined in Annex E.6.4.
  • Enumeration types are represented as the types associated with them. Enumerated names are not available on C side of interface.
  • Representation of packed types is implementation-dependent.
  • Unpacked arrays embedded in a structure have C compatible layout regardless of the type of elements. Similarly, standalone arrays passed as actuals to a sized formal argument have C compatible representation.... more
E.6.4 Basic types
Table E-1 defines the mapping between the basic SystemVerilog data types and the corresponding C types.

Table E-1: Mapping data types

?Encodings for bit and logic are given in file svdpi.h. Refer to Annex E.9.1.1.

The DPI interface also supports the SystemVerilog and C unsigned integer data types that correspond to the mappings Table E-1 shows for their signed equivalents.

Note that input mode arguments of type byte unsigned and shortint unsigned are not equivalent to bit[7:0] or bit[15:0], respectively, since the former are passed as C types unsigned char and unsigned short and the latter are passed as C... more

E.6.5 Normalized ranges
Packed arrays are treated as one-dimensional; the unpacked part of an array can have an arbitrary number of dimensions. Normalized ranges mean [n-1:0] indexing for the packed part and [0:n-1] indexing for a dimension of the unpacked part of an array. Normalized ranges are used for accessing all arguments but open arrays. The canonical representation of packed arrays also uses normalized ranges.
E.6.6 Mapping between SystemVerilog ranges and normalized ranges
The SystemVerilog ranges for a formal argument specified as an open array are those of the actual argument for a particular call. Open arrays are accessible, however, by using their original ranges and the same indexing as in the SystemVerilog code.

For all other types of arguments, i.e., all arguments but open arrays, the SystemVerilog ranges are defined in the corresponding SystemVerilog import or export declaration. Normalized ranges are used for accessing such arguments in C code. The mapping between SystemVerilog ranges and normalized ranges is defined as follows.
  1. If a packed part of an array has more than one... more
E.6.7 Canonical representation of packed arrays
The Direct Programming Interface defines the canonical representation of packed 2-state (type svBitVec32) and 4-state arrays (type svLogicVec32). This canonical representation is derived from on the Verilog legacy PLI’s avalue/bvalue representation of 4-state vectors. Library functions provide the translation between the representation used in a simulator and the canonical representation of packed arrays.

A packed array is represented as an array of one or more elements (of type svBitVec32 for 2-state values and svLogicVec32 for 4-state values), each element representing a group of 32 bits.The first element of an array contains the 32 least-significant bits, next element contains the 32... more


主题

主题
E.7 Argument passing modes
主题
主题
描述
E.7.1 Overview
Imported and exported function arguments are generally passed by some form of a reference, with the exception of small values of SystemVerilog input arguments (see Annex E.11.7), which are passed by value. Similarly, the function result, which is restricted to small values, is passed by value, i.e., directly returned.

Actual arguments passed by reference typically are passed without changing their representation from the one used by a simulator. There is no inherent copying of arguments (other than any copying resulting from coercing).

Access to packed arrays via canonical representation involves copying arguments and does incur some overhead, however. Alternatively, for... more
E.7.2 Calling SystemVerilog tasks and functions from C
There is no difference in argument passing between calls from SystemVerilog to C and calls from C to System- Verilog. Tasks and functions exported from SystemVerilog cannot have open arrays as arguments. Apart from this restriction, the same types of formal arguments can be declared in SystemVerilog for exported tasks and functions and imported tasks and functions. A task or function exported from SystemVerilog shall have the same function header in C as would an imported function with the same function result type and same formal argument list. In the case of arguments passed by reference, an actual argument to... more
E.7.3 Argument passing by value
Only small values of formal input arguments (see Annex E.11.7) are passed by value. Function results are also directly passed by value. The user needs to provide the C-type equivalent to the SystemVerilog type of a formal argument if an argument is passed by value.
E.7.4 Argument passing by reference
For arguments passed by reference, their original simulator-defined representation shall be used and a reference (a pointer) to the actual data object is passed. The actual argument is usually allocated by a caller. The caller can also pass a reference to an object already allocated somewhere else, for example, its own formal argument passed by reference.

If an argument of type T is passed by reference, the formal argument shall be of type T*. However, packed arrays can also be passed using generic pointers void* (typedefed accordingly to svBitPackedArrRef or svLogicPackedArrRef).
E.7.5 Allocating actual arguments for SystemVerilog-specific types
This is relevant only for calling exported SystemVerilog functions from C code. The caller is responsible for allocating any actual arguments that are passed by reference.

Static allocation requires knowledge of the relevant data type. If such a type involves SystemVerilog packed arrays, their actual representation needs to be known to C code; thus, the file svdpi_src.h needs to be included, which makes the C code implementation-dependent and not binary compatible.

Sometimes binary compatibility can be achieved by using dynamic allocation functions. The functions svSizeOfLogicPackedArr() and svSizeOfBitPackedArr() provide the size of the actual representation of a packed array, which can... more
E.7.6 Argument passing by handle—open arrays
Arguments specified as open (unsized) arrays are always passed by a handle, regardless of direction of the SystemVerilog formal argument, and are accessible via library functions. The actual implementation of a handle is simulator-specific and transparent to the user. A handle is represented by the generic pointer void * (typedefed to svOpenArrayHandle). Arguments passed by handle shall always have a const qualifier, because the user shall not modify the contents of a handle.
E.7.7 input arguments
input arguments of imported functions implemented in C shall always have a const qualifier.

input arguments, with the exception of open arrays, are passed by value or by reference, depending on the size. ‘Small’ values of formal input arguments are passed by value. The following data types are considered small:
  • byte, shortint, int, longint, real, shortreal
  • chandle, string
  • bit (i.e., 2-state) packed arrays up to 32 bits (canonical representation shall be used, like for a function result; thus a small packed bit array shall be represented as const svBitVec32) input arguments of other types are passed by reference.
If an... more
E.7.8 inout and output arguments
inout and output arguments, with the exception of open arrays, are always passed by reference. Specifically, packed arrays are passed, accordingly, as svBitPackedArrRef or svLogicPackedArrRef. The same rules about unused bits apply as in Annex E.11.7.
E.7.9 Function result
Types of a function result are restricted to the following SystemVerilog data types (see Table E-1 for the corresponding C type):
  • byte, shortint, int, longint, real, shortreal, chandle, string
  • packed bit arrays up to 32 bits
  • scalar values of type bit and logic
Encodings for bit and logic are given in file svdpi.h. Refer to Annex E.9.1.1.

If the function result type is a packed bit array, the returned value shall be represented using the canonical representation svBitVec32. If a packed bit array is smaller than 32 bits, the most significant bits are unused and their contents are undetermined.


主题

主题
E.8 Context tasks and functions
主题
主题 | 描述
E.8.1 Overview of DPI and VPI context | Both DPI task and functions and VPI/PLI functions might need to understand their context. However, the meaning of the term is different for the two categories of task and functions. DPI imported tasks and functions are essentially proxies for native SystemVerilog tasks and functions. Native SystemVerilog tasks and functions always operate in the scope of their declaration site. For example, a native SystemVerilog function f() can be declared in a module m which is instantiated as top.i1_m. The top.i1_m instance of f() can be called via hierarchical reference from code in a distant design region. Function f() is said to... more
E.8.2 Context of imported and export tasks and functions | DPI imported and export tasks and functions can be declared anywhere a normal SystemVerilog task or function can be declared. Specifically, this means that they can be declared in module, program, interface, or generate declarative scope. A context imported task or function executes in the context of the instantiated scope surrounding its declaration. This means that such tasks and functions can see other variables in that scope without qualification. As explained in Annex E.8.1, this should not be confused with the context of the task’s or function’s call site, which can actually be anywhere in the SystemVerilog design hierarchy. The... more
E.8.3 Working with DPI context tasks and functions in C code | DPI defines a small set of functions to help programmers work with DPI context tasks and functions. The term scope is used in the task or function names for consistency with other SystemVerilog terminology. The terms scope and context are equivalent for DPI tasks and functions. There are functions that allow the user to retrieve and manipulate the current operational scope. It is an error to use these functions with any C code that is not executing under a call to a DPI context imported task or function. There are also functions that provide users with the power to set... more
E.8.4 Example 1 — Using DPI context functions | SV Side:
E.8.5 Relationship between DPI and VPI/PLI interfaces | DPI allows C code to run in the context of a SystemVerilog simulation, thus it is natural for users to consider using VPI/PLI C code from within imported tasks and functions. There is no specific relationship defined between DPI and the existing Verilog programming interfaces (VPI and PLI). Programmers must make no assumptions about how DPI and the other interfaces interact. In particular, note that a vpiHandle is not equivalent to an svOpenArrayHandle, and the two must not be interchanged and passed between functions defined in two different interface standards. If a user wants to call VPI or PLI functions... more


主题

主题
E.9.1 Binary compatibility include file svdpi.h
主题
主题
描述
E.9.1.1 Scalars of type bit and logic
/* canonical representation */
#define sv_0 0
#define sv_1 1
#define sv_z 2 /* representation of 4-st scalar z */
#define sv_x 3 /* representation of 4-st scalar x */
/* common type for ’bit’ and ’logic’ scalars. */
typedef unsigned char svScalar;
typedef svScalar svBit; /* scalar */
typedef svScalar svLogic; /* scalar *
E.9.1.2 Canonical representation of packed arrays
/* 2-state and 4-state vectors, modelled upon PLI’s avalue/bvalue */
#define SV_CANONICAL_SIZE(WIDTH) (((WIDTH)+31)>>5)
typedef unsigned int
svBitVec32;/* (a chunk of) packed bit array */
typedef struct { unsigned int c; unsigned int d;}
svLogicVec32; /* (a chunk of) packed logic array */
/* Since the contents of the unused bits is undetermined, the following macros
can be handy */
#define SV_MASK(N) (~(-1<<(N)))
#define SV_GET_UNSIGNED_BITS(VALUE,N)\
((N)==32?(VALUE):((VALUE)&SV_MASK(N)))
#define SV_GET_SIGNED_BITS(VALUE,N)\
((N)==32?(VALUE):\
(((VALUE)&(1<<((N)1)))?((VALUE)|~SV_MASK(N)):((VALUE)&SV_MASK(N))))
E.9.1.3 Implementation-dependent representation
/* a handle to a scope (an instance of a module or an interface) */
typedef void *svScope;
/* a handle to a generic object (actually, unsized array) */
typedef void* svOpenArrayHandle;
/* reference to a standalone packed array */
typedef void* svBitPackedArrRef;
typedef void* svLogicPackedArrRef;
/* total size in bytes of the simulator’s representation of a packed array */
/* width in bits */
int svSizeOfBitPackedArr(int width);
int svSizeOfLogicPackedArr(int width);
E.9.1.4 Translation between the actual representation and the canonical representation


主题

主题
E.9 Include files
主题
主题 | 描述
E.9.1 Binary compatibility include file svdpi.h | Applications which use the Direct Programming Interface with C code usually need this main include file. The include file svdpi.h defines the types for canonical representation of 2-state (bit) and 4-state (logic) values and passing references to SystemVerilog data objects, provides function headers, and defines a number of helper macros and constants. This document fully defines the svdpi.h file. The content of svdpi.h does not depend on any particular implementation or platform; all simulators shall use the same file. The following subsections (and Annex E.10.3.1) detail the contents of the svdpi.h file.
E.9.2 Source-level compatibility include file svdpi_src.h | Only two symbols are defined: the macros that allow declaring variables to represent the SystemVerilog packed arrays of type bit or logic.
E.9.3 Example 2 — binary compatible application | SystemVerilog:
E.9.4 Example 3— source-level compatible application | SystemVerilog:


主题

主题
E.10.3 Access to packed arrays via canonical representation
主题
主题 | 描述
E.10.3.1 Bit selects | This subsection defines the bit selects portion of the svdpi.h file (see Annex E.9.1 for more details).
E.10.3.2 Part selects | logic. Array slices are not supported for unpacked arrays. Additionally, 64-bit wide part select can be read as a single value of type unsigned long long. Functions for part selects only allow access (read/write) to a narrow subrange of up to 32 bits. A canonical representation shall be used for such narrow vectors. If the specified range of part select is not fully contained within the normalized range of an array, the behavior is undetermined. For the convenience, bit type part selects are returned as a function result. In addition to a general function for narrow part selects (<= 32-bits),... more


主题

主题
E.10 Arrays
主题
主题 | 描述
E.10.1 Multidimensional arrays | Packed arrays shall be one-dimensional. Unpacked arrays can have an arbitrary number of dimensions.
E.10.2 Direct access to unpacked arrays | Unpacked arrays, with the exception of formal arguments specified as open arrays, shall have the same layout as used by a C compiler; they are accessed using C indexing (see Annex E.6.6).
E.10.3 Access to packed arrays via canonical representation | Packed arrays are accessible via canonical representation; this C-layer interface provides functions for moving data between implementation representation and canonical representation (any necessary conversion is performed on-the-fly (see Annex E.9.1.3)), and for bit selects and limited (up to 32-bit) part selects. (Bit selects do not involve any canonical representation.)


主题

主题
E.11 Open arrays
主题
主题
描述
E.11.1 Actual ranges
The formal arguments defined as open arrays have the size and ranges of the actual argument, as determined on a per-call basis. The programmer shall always have a choice whether to specify a formal argument as a sized array or as an open (unsized) array.

In the former case, all indices are normalized on the C side (i.e., 0 and up) and the programmer needs to know the size of an array and be capable of determining how the ranges of the actual argument map onto C-style ranges (see Annex E.6.6).

Tip: programmers can decide to use [n:0]name[0:k] style ranges... more
E.11.2 Array querying functions
These functions are modelled upon the SystemVerilog array querying functions and use the same semantics (see Section 23.7).

If the dimension is 0, then the query refers to the packed part (which is one-dimensional) of an array, and dimensions > 0 refer to the unpacked part of an array.
E.11.3 Access functions
Similarly to sized arrays, there are functions for copying data between the simulator representation and the canonical representation and to obtain the actual address of SystemVerilog data object or of an individual element of an unpacked array. This information might be useful for simulator-specific tuning of the application. Depending on the type of an element of an unpacked array, different access methods shall be used when working with elements.
  • Packed arrays ( bit or logic) are accessed via copying to or from the canonical representation.
  • Scalars (1-bit value of type bit or logic) are accessed (read or written) directly.
  • Other... more
E.11.4 Access to the actual representation
The following functions provide an actual address of the whole array or of its individual elements. These functions shall be used for accessing elements of arrays of types compatible with C. These functions are also useful for vendors, because they provide access to the actual representation for all types of arrays.

If the actual layout of the SystemVerilog array passed as an argument for an open unpacked array is different than the C layout, then it is not possible to access such an array as a whole; therefore, the address and size of such an array shall be undefined (zero... more
E.11.5 Access to elements via canonical representation
The following functions copy a single vector from a canonical representation to an element of an open array or other way round. The element of an array is identified by indices, bound by the ranges of the actual argument, i.e., the original SystemVerilog ranges are used for indexing.
E.11.6 Access to scalar elements (bit and logic)
Another group of functions is needed for scalars (i.e., when an element of an array is a simple scalar, bit, or logic):
E.11.7 Access to array elements of other types
If an array’s elements are of a type compatible with C, there is no need to use canonical representation. In such situations, the elements are accessed via pointers, i.e., the actual address of an element shall be computed first and then used to access the desired element.
E.11.8 Example 4— two-dimensional open array
SystemVerilog:
E.11.9 Example 5 — open array
SystemVerilog:
E.11.10 Example 6 — access to packed arrays
SystemVerilog:
E.11.11 Example 7 — binary compatible calls of exported functions
This example demonstrates the source compatibility include file svdpi_src.h is not needed if a C function dynamically allocates the data structure for simulator representation of a packed array to be passed to an exported SystemVerilog function.

SystemVerilog:


主题

主题
G.2 Object code inclusion
主题
主题
描述
G.2.1 Bootstrap file
The object code bootstrap file has the following syntax.
  1. The first line contains the string #!SV_LIBRARIES.
  2. An arbitrary amount of entries follow, one entry per line, where every entry holds exactly one library location. Each entry consists only of the pathname_without_extension of the object code file to be loaded and can be surrounded by an arbitrary number of blanks; at least one blank shall precede the entry in the line. The value pathname_without_extension is equivalent to the value of the switch -sv_lib.
  3. Any amount of comment lines can be interspersed between the entry lines; a comment line starts with the... more
G.2.2 Examples
1) If the pathname root has been set by the switch -sv_root to /home/user and the following object files need to be included:
/home/user/myclibs/lib1.so
/home/user/myclibs/lib3.so
/home/user/proj1/clibs/lib4.so
/home/user/proj3/clibs/lib2.so
then use either of the methods in Example 7-1. Both methods are equivalent.

Example 7-1 — Using a simple bootstrap file or a switch list

2) If the current working directory is /home/user, using the series of switches shown in Example 7-2 (left column) result in loading the following files (right column).

Example 7-2 — Using a combination of -sv_lib and -sv_root switches

3) Further, using the set of switches and contents of... more


主题

主题
H.2.3 Derived forms
主题
主题 | 描述
H.2.3.1 Derived non-overlapping implication operator | ? ( R1 |=> P ) (( R1 ##1 1 ) |-> P ) . ? ( S1 |=> Q ) ((S1 ##1 @(1) 1 ) |-> Q ) .
H.2.3.2 Derived consecutive repetition operators | ? Let m > 0. R [*m] ( R ##1 R ##1 ... ##1 R ) // m copies of R . ? R [*0:$] ( R [*0] or R [*1:$] ) . ? Let m < n. R [*m:n] ( R [*m] or R [*m +1] or ... or R [*n]) . ? Let m > 1. R [*m:$] ( R [*m – 1] ##1 R [*1:$]) .
H.2.3.3 Derived delay and concatenation operators | Let m < n. ? ( ##[m:n] R ) (1[*m:n] ##1 R ) . ? ( ##[m:$] R ) (1[*m:$] ##1 R ) . ? ( ##m R ) (1[*m] ##1 R ) . ? Let m > 0. ( R1 ##[m:n] R2 ) ( R1 ##1 1[*m – 1:n – 1] ##1 R2 ) . ? Let m > 0. ( R1 ##[m:$] R2 ) ( R1 ##1 1[*m – 1:$] ##1 R2 ) . ? Let m > 1. ( R1 ##m R2 ) ( R1 ##1 1[*m – 1] ##1 R2 ) . ? ( R1 ##[0:0]... more
H.2.3.4 Derived non-consecutive repetition operators | Let m < n. ? b [->m:n] ( !b [*0:$] ##1 b )[*m:n] . ? b [->m:$] ( !b [*0:$] ##1 b )[*m:$] . ? b [->m] ( !b [*0:$] ##1 b)[*m] . ? b [=m:n] ( b [->m:n] ##1 !b [*0:$] ) . ? b [=m:$] ( b [->m:$] ##1 !b [*0:$] ) . ? b [=m] ( b [->m] ##1 !b [*0:$] ) .
H.2.3.5 Other derived operators | ? ( R1 and R2 ) ((( R1 ##1 1[*0:$]) intersect R2 ) or ( R1 intersect ( R2 ##1 1[*0:$]))) . ? ( R1 within R2 ) ((1[*0:$] ##1 R1 ##1 1[*0:$]) intersect R2 ) . ? ( b throughout R ) (( b [*0:$]) intersect R ) . ? ( R, v = e ) ( R ##0 ( 1, v = e )) . ? ( R, v1 = e1,... ,vk = ek) (( R, v1 = e1) ##0 ( 1, v2 = e2 ,... , vk = ek )) for k > 1 ? ( if... more


主题

主题
H.2 抽象语法
主题
主题 | 描述
H.2.1 Abstract grammars | In the following abstract grammars, b denotes a boolean expression, v denotes a local variable name, and e denotes an expression. The abstract grammar for unclocked sequences is R
H.2.2 Notations | Throughout the sequel, the following notational conventions will be used: b, c denote boolean expressions; v denotes a local variable name; e denotes an expression; R, R1, R2 denote unclocked sequences; S, S1, S2 denote clocked sequences; P, P1, P2 denote unclocked properties; Q denotes a clocked property; A denotes an assertion; i, j, k, m, n denote non-negative integer constants.
H.2.3 Derived forms | Internal parentheses are omitted in compositions of the (associative) operators ##1 and or.


主题

主题
H.3.3 Satisfaction without local variables
主题
主题 | 描述
H.3.3.1 Neutral satisfaction | w denotes a non-empty finite or infinite word over Σ. Assume that all properties, sequences, and unclocked property fragments do not involve local variables. Neutral satisfaction of assertions: For the definition of neutral satisfaction of assertions, b denotes the boolean expression representing the enabling condition for the assertion. Intuitively, b is derived from the conditions in the context of a procedural assertion, while b is “1” for a declarative assertion. ? w, b always @(c) assert property P iff for every 0 < i < |w| such that w i c and w i b, w i.. @(c) P. ?... more
H.3.3.2 Weak and strong satisfaction by finite words | This subsection defines weak and strong satisfaction, denoted – and + (respectively) of an assertion A by a finite (possibly empty) word w over Σ. These relations are defined in terms of the relation of neutral satisfaction by infinite words as follows: ? w – A iff w Tω A. ? w + A iff w⊥ω A. A tool checking for satisfaction of A by the finite word w should return: ? “holds strongly” if w + A. ? “fails” if w A. ? “holds (but does not hold strongly)” if w A and w + A. ? “pending” if... more


主题

主题
H.3.6 Satisfaction with local variables
主题
主题 | 描述
H.3.6.1 Neutral satisfaction | w denotes a non-empty finite or infinite word over Σ. L0, L1 denote local variable contexts. The rules defining neutral satisfaction of an assertion are identical to those without local variables, but with the understanding that the underlying properties can have local variables. Neutral satisfaction of properties: ? w Q iff w, {} Q. ? w, L0 Q iff w, L0 Q’, where Q’ is the unclocked property that results from Q by applying the rewrite rules. ? w, L0 disable iff (b) P iff either w, L0 P or there exists 0 < k < |w| such that w... more
H.3.6.2 Weak and strong satisfaction by finite words | The definition is identical to that without local variables, but with the understanding that the underlying properties can have local variables.


主题

主题
H.3 语义
主题
主题 | 描述
H.3.1 Rewrite rules for clocks | The semantics of clocked sequences and properties is defined in terms of the semantics of unclocked sequences and properties. The following rewrite rules define the transformation of a clocked sequence or property into an unclocked version that is equivalent for the purposes of defining the satisfaction relation. In this transformation, it is required that the conditions in event controls not be dependent upon any local variables. ? @(c) b ( !c [*0:$] ##1 c & b ) . ? @(c)( 1, v = e ) ( @(c) 1 ##0 ( 1, v = e )) . ? @(c)( P )... more
H.3.2 Tight satisfaction without local variables | Tight satisfaction is denoted by . For unclocked sequences without local variables, tight satisfaction is defined as follows. w, x, y, z denote finite words over Σ. ? w b iff |w| = 1 and w0 b . ? w ( R ) iff w R . ? w ( R1 ##1 R2 ) iff there exist x, y such that w = xy and x R1 and y R2 . ? w ( R1 ##0 R2 ) iff there exist x, y, z such that w = xyz and |y| = 1, and xy R1 and yz R2 .... more
H.3.3 Satisfaction without local variables |
H.3.4 Local variable flow | This subsection defines inductively how local variable names flow through unclocked sequences. Below, “U” denotes set union, “ ” denotes set intersection, “–” denotes set difference, and “{}” denotes the empty set. The function “sample” takes a sequence as input and returns a set of local variable names as output. Intuitively, this function returns the set of local variable names that are sampled (i.e., assigned) in the sequence. The function “block” takes a sequence as input and returns a set of local variable names as output. Intuitively, this function returns the set of local variable names that are blocked from... more
H.3.5 Tight satisfaction with local variables | A local variable context is a function that assigns values to local variable names. If L is a local variable context, then dom(L) denotes the set of local variable names that are in the domain of L. If D dom(L), then L|D means the local variable context obtained from L by restricting its domain to D. In the presence of local variables, tight satisfaction is a four-way relation defining when a finite word w over the alphabet Σ together with an input local variable context L0 satisfies an unclocked sequence R and yields an output local variable context L1. This... more
H.3.6 Satisfaction with local variables |


主题

主题
H.4 Extended Expressions
主题
主题 | 描述
H.4.1 Extended booleans | w denotes a non-empty finite or infinite word over Σ, j denotes an integer such that 0 < j < |w|, and T(V) denotes an instance of a clocked or unclocked sequence that is passed the local variables V as actual arguments. ? w j,L0,L1 T(V).ended iff there exist 0 < i < j and L such that both w i, j, {}, L T(V) and L1 = L0 |D U LV , where D = dom(L0) – (dom(L) V). ? w j,L0,L1 @(c)(T(V).matched) iff there exists 0 < i < j such that w i,L0,L1 T(V).ended and w i+1,... more
H.4.2 Past | w denotes a non-empty finite or infinite word over Σ, and j denotes an integer such that 0 < j < |w|. ? Let n > 1. If there exist 0 < i < j such that w i, j , {}, {} (c ##1 c [->n – 1]), then @(c)$past(e, n)[w j] = e[w i]. Otherwise, @(c)$past(e, n)[w j] has the value x. ? $past(e) $past(e,1) .


主题

主题
第七章 操作符与表达式
主题
主题
描述
7.1 简介（一般信息）
SystemVerilog操作符是Verilog和C语言操作符的组合。在这两种语言中，操作数的类型和尺寸是固定的，因此操作符具有固定的类型和尺寸。SystemVerilog保持了操作符的固定类型和尺寸。这能够产生有效的编码。

Verilog不包含赋值操作符或递增及递减操作符。SystemVerilog包含了C语言的赋值操作符，例如+=，以及C语言的递增和递减操作符（++和--）。

Verilog-2001加入了有符号线网和reg变量，以及有符号文本值。对于有符号整数和无符号整数的结合规则，Verilog和C语言存在差异。SystemVerilog使用Verilog-2001的规则。
7.2 操作符语法
7.3 赋值操作符
除了简单赋值操作符（=）之外，SystemVerilog包含了C语言赋值操作符以及特殊的位级赋值操作符：+=、 -=、 *=、 /=、 %=、 &=、 |=、 ^=、 <<=、 >>=、 <<<=、 以及 >>>=。除了左侧索引表达式仅仅计算一次之外，赋值操作符在语义上等价于一个阻塞赋值。例如：
7.4 对logic和bit类型的操作
当一个二元操作符包含一个bit类型的操作数和一个logic类型的操作数的时候，结果的数据类型是logic。如果一个操作数的类型是int而另一个操作数的类型是integer的时候，那么结果的数据类型是integer。

对于!=和==操作符，如果任何一个操作数包含X或Z，那么就像Verilog-2001一样，返回一个X。如果结果被转换成bit类型（例如在一个if语句中），那么结果被转换成0。

一元缩减操作符（& ~& | ~| ^ ~^）可以应用于任何整数类型（包括压缩数组）。如果压缩类型是一个四态类型，那么操作符应该返回类型为logic的值；如果压缩类型是一个两态类型，那么返回值的类型是bit。
7.5 通配等式与通配不等式
SystemVerilog 3.1引入了如下所述的通配比较操作符。

表 7-1：通配等式与通配不等式操作符

7.6 实操作符
shortreal类型的操作数与Verilog real类型的操作数具有相同的操作限制。一元操作符++和--可以应用于类型为real和shortreal的操作数（按1.0递增或递减）。赋值操作符+=、-=、*=、/=也可以具有real和shortreal类型的操作数。

除了三元操作符中?之前的操作数外，如果任一操作数是real类型的，那么结果就是real类型的。另外，除了三元操作符中?之前的操作数外，如果任一操作数是shortreal类型的，那么结果就是shortreal类型的。

实操作数还可以用在下面的表达式中：
7.7 尺寸
一个表达式的位宽由操作数和上下文决定，它与Verilog遵从相同的规则。在SystemVerilog中，可以使用强制类型转换来设置中间值的尺寸。

在Verilog中，当一条赋值语句的左侧和右侧具有不同尺寸的时候，工具可以发布一条警告信息。使用SystemVerilog的尺寸强制转换，可以阻止掉这些警告信息。
7.8 符号
确定SystemVerilog表达式符号的规则应该与Verilog相同。通过类型转换将shortreal转换成integer应该是有符号的。
7.9 操作符优先级与关联性
操作符的优先级与关联性在表7-2中列出。最先列出的操作符具有最高优先级。

表 7-2：操作符优先级与关联性

7.10 内建方法
SystemVerilog引入了类和方法调用语法，其中一个任务或函数通过使用圆点符号（.）调用。
7.11 静态前缀
对于一个选择片来讲，选择片的“最长静态前缀”被非正式地定义为一个分析工具能够在确立完成后确定其值的最长的那一部分。当描述隐式敏感列表（参见9.2节）以及为逻辑端口的驱动描述错误条件（参见5.6 线网、reg、与logic ）的时候，我们使用这个概念。本节余下的部分定义由什么组成了一个选择片的最长静态前缀。

域选择被定义成一个层次化的名字，其中最后一个层次分割符（“.”）的右侧标识了类型为结构体或联合体的变量的一个域。域选择前缀被定义成域选择中最后一个层次分割符左侧的部分。

一个索引选择是一个单纯的索引操作。索引选择前缀或者是一个标识符或者是另外一个索引选择（在多维选择的情况下）。数组选择、位选择、部分选择、以及索引部分选择都是索引选择的例子。

静态前缀的定义是递归的并且具有如下的定义：
  1. 一个标识符是一个静态前缀
  2. 如果一个域选择前缀是一个静态前缀，那么这个域选择是一个静态前缀
  3. 如果一个索引选择前缀是一个静态前缀并且选择表达式是一个常量表达式，那么这个索引选择是一个静态前缀。

最长静态前缀的定义如下：
  1. 如果一个标识符不是一个静态前缀表达式的域选择前缀或索引选择前缀，那么它是一个最长静态前缀
  2. 如果一个域选择不是一个静态前缀表达式的域选择前缀或索引选择前缀，那么它是一个最长静态前缀
  3. 如果一个索引选择不是一个静态前缀表达式的域选择前缀或索引选择前缀，那么它是一个最长静态前缀
例子：
7.12 串联
与Verilog一样，花括号（{ }）被用来表示串联。串联被当作一个压缩的位向量来看待。它可以使用在一条赋值语句或一个表达式的左侧。
7.13 非压缩数组表达式
表达式中也可以使用花括号来为非压缩数组赋值。与C语言不同的是，表达式必须在元素与元素之间达到匹配，并且花括号必须匹配数组维数。在数组中对应元素类型的赋值关联文中，每一个表达式的元素都会被计算。这也就意味着，与上面的相似赋值不同，下面的例子不会发布尺寸警告信息：
7.14 结构体表达式
结构体表达式（压缩的和非压缩的）可以使用花括号和逗号由成员表达式构建，其中成员表达式以成员声明的顺序排列。复制操作符可以用来设置准确的成员数目。每一个成员表达式应该在对结构体中对应成员类型赋值的关联文中计算。结构体表达式也可以使用成员的名字来构建。
7.15 标签联合体表达式与成员访问
7.16 集合表达式
非压缩结构体和数组变量、文本值、以及表达式都可以作为集合表达式使用。一个非压缩数组的多维分片也可以用作集合表达式。

集合表达式可以在通过赋值语句、通过一个端口、或作为任务或函数的自变量进行拷贝。集合表达式也可以使用相等或不等操作符进行比较。为了进行拷贝或比较，集合表达式的类型必须是赋值兼容的。参见5.8.2 赋值兼容 。
7.17 操作符过载
有多种算术算法可能非常有用：饱和算法，任意尺寸的浮点数运算，进位保留算法等。使用普通的算术操作符而不是依赖于函数调用有利于代码的可读性。
7.18 流操作符（压缩/非压缩）
在3.16节描述了位流强制类型转换，当转换操作可以仅仅使用一个强制类型转换方便地表达，并且位流的特定顺序并不重要的时候，这种方法最为有用。然而，有时位流需要匹配于一个特定的组织形式。流操作符将位流类型（参见3.16节）以用户指定的顺序压缩到一个位序列当中。当流操作符使用在表达式左侧的时候，它执行相反的操作：将位流解压缩成一个或多个变量。如果正在被压缩的数据包含任何四态类型，那么压缩操作的结果是四态类型，否则，结果为两态类型。将四态类型的位流解压缩成两态类型变量是通过一个向两态变量的强制类型转换实现的，反之亦然。

位流串联的语法如下：
7.19 条件操作符
7.20 集合成员资格
SystemVerilog支持单一值集合以及集合成员资格操作符。

集合成员资格操作符的语法如下：


主题

主题
第三十一章 SystemVerilog VPI Object Model
主题
主题
描述
31.1 简介（一般信息）
SystemVerilog extends the Verilog Procedural Interface (VPI) object diagrams to support SystemVerilog constructs. The VPI object diagrams document the properties of objects and the relationships of objects. How these diagrams illustrate this information is explained in Section 26 of the IEEE Std. 1364-2001 Verilog standard. The SystemVerilog extensions to the VPI diagrams are in the form of changes to or additions to the diagrams contained in 1364-2001 Verilog standard.

The following table summarizes the changes and additions made to the Verilog VPI object diagrams:

Table 31-4: Verilog VPI object diagram changes and additions

31.2 Instance

NOTES

  1. Top-level instances shall be accessed using vpi_iterate() with a NULL reference object.
  2. Passing a NULL handle to vpi_get() with types vpiTimePrecision or vpiTimeUnit shall return the smallest time precision of all instances in the design.
  3. If an instance is an element within an array, the vpiIndex transition is used to access the index within the array. If the instance is not part of an array, this transition shall return NULL.
  4. Compilation units are represented as packages that have a vpiUnit property set to TRUE. Such implicitly declared packages shall have implementation dependent names.
31.3 Interface

NOTE
All interfaces are instances and all relations and properties in the Instances diagram also apply.

31.4 Program

NOTE
All programs are instances and all relations and properties in the Instances diagram also apply.

31.5 Module (supersedes IEEE 1364-2001 26.6.1)

31.6 Modport
31.7 Interface tf decl

NOTE
vpiIterate(vpiTaskFunc) can return more than one task/function declaration for modport tasks/functions with an access type of vpiForkJoin, because the task or function can be imported from multiple module instances.

31.8 Ports (supersedes IEEE 1364-2001 26.6.5)

NOTES

  1. vpiPortType shall be one of the following three types: vpiPort, vpiInterfacePort, and vpiModportPort. Port type depends on the formal, not on the actual.
  2. vpi_get_delays, vpi_put_delays delays shall not be applicable for vpiInterfacePort.
  3. vpiHighConn shall indicate the hierarchically higher (closer to the top module) port connection.
  4. vpiLowConn shall indicate the lower (further from the top module) port connection.
  5. vpiLowConn of a vpiInterfacePort shall always be vpiRefObj.
  6. Properties scalar and vector shall indicate if the port is 1 bit or more than 1 bit. They shall not indicate anything about what is connected to the port.
  7. Properties index and name shall... more
31.9 Ref Obj
31.10 Variables (supersedes IEEE 1364-2001 section 26.6.8)

NOTES
1) A var select is a word selected from a variable array.
2) The boolean property vpiArray shall be TRUE if the variable handle references an array of variables, and FALSE otherwise. If the variable is an array, iterate on vpiVarSelect to obtain handles to each variable in the array.
3) To obtain the members of a union and structure, see the relations in Section 31.21
4) The range relation is valid only when vpiArray is true. When applied to array vars this relation returns only unpacked ranges. When applied to logic and bit variables, it returns only the... more

31.11 Var Select (supersedes IEEE 1364-2001 26.6.8)
31.12 Typespec

NOTES
1) If the vpiTypedef is TRUE and the typedef creates an alias of another typedef, then the vpiTypedefAlias shall return a non null handle which represents the handle to the aliased typedef. For example:
31.13 Variable Drivers and Loads (supersedes IEEE 1364-2001 26.6.23)

NOTES
1) vpiDrivers/Loads for a structure, union, or class variable will include the following:
— Driver/Load for the whole variable
— Driver/Load for any bit/part select of that variable
— Driver/Load of any member nested inside that variable
2) vpiDrivers/Loads for any variable array should include the following:
— Driver/Load for entire array/vector or any portion of an array/vector to which a handle can be obtained.
31.14 Instance Arrays (supersedes IEEE 1364-2001 26.6.2)

NOTE
1) Param assignments can only be obtained from non-primitive instance arrays.
2) To obtain all the dimensions of a multi-dimensional array, the range iterator must be used. Using the vpiLeftRange/vpiRightRange properties will only return the last dimension of a multidimensional array.
31.15 Scope (supersedes IEEE 1364-2001 26.6.3)

NOTE
1: Unnamed scopes shall have valid names, though tool dependent.
2: The vpiImport iterator shall return all objects imported into the current scope via import statements. Note that only objects actually referenced through the import shall be returned, rather than items potentially made visible as a result of the import. Refer to Section 18.2.2 for more details.
31.16 IO Declaration (supersedes IEEE 1364-2001 26.6.4)

vpiDirection returns vpiRef for pass by ref ports.
31.17 Clocking Block
31.18 Class Object Definition

NOTE
  1. ClassDefn handle is a new concept. It does not correspond to any vpiUserDefined (class object) in the design. Rather it represents the actual type definition of a class.
  2. Should not call vpi_get_value/vpi_put_value on the non-static variables obtained from the class definition handle.
  3. Iterator to constraints returns only normal constraints and not inline constraints.
  4. To get constraints inherited from base classes, you will need to traverse the extend relation to obtain the base class.
  5. The vpiDerivedClasses iterator returns all the classes derived from the given class.
  6. The relation to vpiExtend exists whenever a one class is derived from another class... more
31.19 Constraint, constraint ordering, distribution,
31.20 Constraint expression
31.21 Class Variables

NOTES
1) vpiWaiting/Process iterator on mailbox/semaphores will show the processes waiting on the object:
— Waiting process means either frame or task/function handle.
2) vpiMessage iterator shall return all the messages in a mailbox.
3) vpiClassDefn returns the ClassDefn which was used to create the handle. vpiActualDefn returns
the ClassDefn that handle object points to when the query is made. The difference can be seen in
the example below:
class Packet
...
endclass : Packet
class LinkedPacket extends Packet
...
endclass : LinkedPacket
LinkedPacket l = new;
Packet p = l;
In this example, the vpiClassDefn of variable "p" is... more
31.22 Structure/Union

NOTES
vpi_get_value/vpi_put_value cannot be used to access values of entire unpacked structures and unpacked unions.
31.23 Named Events (supersedes IEEE 1364-2001 26.6.11)

NOTE
The new iterator (vpiWaitingProcesses) returns all waiting processes, identified by their frame, for that named event.

NOTE
vpi_iterate(vpiIndex, named_event_handle) shall return the set of indices for a named event within an array, starting with the index for the named event and working outward. If the named event is not part of an array, a NULL shall be returned.
31.24 Task, Function Declaration (supersedes IEEE 1364-2001 26.6.18)

NOTE
5) A Verilog HDL function shall contain an object with the same name, size, and type as the function.
6) vpiInterfaceTask/vpiInterfaceFunction shall be true if task/function is declared inside an interface or a modport of an interface.
7) For function where return type is a user-defined type, vpi_handle (vpiReturn,Function_handle) shall return the implicit variable handle representing the return of the function from which the user can get the details of that user-defined type.
8) vpiReturn will always return a var object, even for simple returns.
31.25 Alias Statement
31.26 Frames (supersedes IEEE 1364-2001 26.6.20)

NOTES
1) The following callbacks shall be supported on frames:
— cbStartOfFrame: triggers whenever any frame gets executed.
— cbEndOfFrame: triggers when a particular thread is deleted after all storage is deleted.
31.27 Threads

NOTES
The following callbacks shall be supported on threads
— cbStartOfThread: triggers whenever any thread is created
— cbEndOfThread: triggers when a particular thread gets deleted after storage is deleted.
— cbEnterThread: triggers whenever a particular thread resumes execution
31.28 tf call (supersedes IEEE 1364-2001 26.6.19)

NOTE:
1) the vpiWith relation is only available for randomize methods (see Section 12.6) and for array locator methods (see Section 4.15.1).
2) For methods (method func call, method task call), the vpiPrefix relation will return the object to which the method is being applied. For example, for the class method invocation
packet.send();
the prefix for the "send" method is the class var "packet"
31.29 Module path, path term (supersedes IEEE 1364-2001 26.6.15)

NOTE:
1) specify blocks can occur in both modules and interfaces. For backwards compatibility the vpiModule relation has been preserved; however this relation will return NULL for specify blocks in interfaces. For new code it is recommended that the vpiInstance relation be used instead.
31.30 Concurrent assertions

NOTE
Clocking event is always the actual clocking event on which the assertion is being evaluated, regardless of whether this is explicit or implicit (inferred)
31.31 Property Decl
31.32 Property Specification

NOTE
Variables are declarations of property variables. You cannot get the value of these variables.

NOTES:
1. within the context of a property expr, vpiOpType can be any one of vpiNotOp, vpiImplyOp, vpiDelayedImplyOp, vpiAndOp, vpiOrOp, vpiIfOp, vpiIfElseOp
Operands to these operations will be provided in the same order as show in the BNF.
31.33 Multiclock Sequence Expression
31.34 Sequence Declaration

NOTE:
the vpiArgument iterator shall return the sequence instance arguments in the order that the formals for the sequence are declared, so that the correspondence between each argument and its respective formal can be made. If a formal has a default value, that value will appear as the argument should the instantiation not provide a value for that argument.
31.35 Sequence Expression

Notes:
2. Within a sequence expression, vpiOpType can be any one of vpiAndOp, vpiIntersectOp, vpiOr, vpiFirstMatchOp, vpiThroughoutOp, vpiWithinOp, vpiUnaryCycleDelayOp, vpiCycleDelayOp, vpiRepeatOp, vpiConsecutiveRepeatOp or vpiGotoRepeatOp.
3. For operations, the operands are provided in the same order as the operands appear in BNF, with the following exceptions:
vpiUnaryCycleDelayOp: arguments will be: sequence, left range, right range. Right range will only be given if different than left range.
vpiCycleDelayOp: argument will be: LHS sequence, rhs sequence, left range, right range. Right range will only be provided if different than left range.
all the repeat operators: the first argument will be the sequence being... more
31.36 Attribute (supersedes IEEE 1364-2001 26.6.42)
31.37 Atomic Statement (supersedes IEEE 1364-2001 26.6.27)
31.38 If, if else, return, case, do while (supersedes IEEE 1364-2001 26.6.35, 26.6.36)
31.39 waits, disables, expect, foreach (supersedes IEEE 1364 26.6.38)
31.40 Simple expressions (supersedes IEEE 1364-2001 26.6.25)
31.41 Expressions (supersedes IEEE 1364-2001 26.6.26)

NOTES:
1) For an operator whose type is vpiMultiConcat, the first operand shall be the multiplier expression. The remaining operands shall be the expressions within the concatenation.
2) The property vpiDecompile will return a string with a functionally equivalent expression to the original expression within the HDL. Parenthesis shall be added only to preserve precedence. Each operand and operator shall be separated by a single space character. No additional white space shall be added due to parenthesis.
3) New vpiOpTypes: vpiInsideOp, vpiMatchOp, vpiCastOp, vpiPreIncOp, vpiPostIncOp, vpiPreDecOp, vpiPostDecOp, vpiIffOp, vpiCycleDelayOp. The cast operation is represented as a unary operation, with its... more
31.42 Event control (supersedes IEEE 1364-2001 26.6.30)

NOTE—For event control associated with assignment, the statement shall always be NULL.
31.43 Event stmt (supersedes IEEE 1364-2001 26.6.27)
31.44 Process (supersedes IEEE 1364-2001 26.6.27)

NOTE- vpiAlwaysType can be one of: vpiAlwaysComb, vpiAlwaysFF, vpiAlwaysLatch
31.45 Assignment (supersedes IEEE 1364-2001 26.6.28)

NOTE: vpiOpType will return vpiAssignmentOp for normal non-blocking ’=’ assignments, and the operator combined with the assignment for the operators described in section 7.3.

For example, the assignment


主题

主题
第三十章 SystemVerilog数据读API
主题
主题
描述
30.1 简介（一般信息）
This chapter extends the SystemVerilog VPI with read facilities so that the Verilog Procedural Interface (VPI) acts as an Application Programming Interface (API) for data access and tool interaction irrespective of whether the data is in memory or a persistent form such as a database, and also irrespective of the tool the user is interacting with.

SystemVerilog is both a design and verification language consequently its VPI has a wealth of design and verification data access mechanisms. This makes the VPI an ideal vehicle for tool integration in order to replace arcane, inefficient, and error-prone file-based data exchanges with a... more
30.2 需求
SystemVerilog adds several design and verification constructs including:
  • C data types such as int, struct, union, and enum.
  • Advanced built-in data types such as string.
  • User defined data types and corresponding methods.
  • Data types and facilities that enhance the creation and functionality of testbenches.
The access API shall be implemented by all tools as a minimal set for a standard means for user-tool or tooltool interaction that involves SystemVerilog object data querying (reading). In other words, there is no need for a simulator to be running for this API to be in effect; it is a set of API routines... more
30.3 Extensions to VPI enumerations
These extensions shall be appended to the contents of the vpi_user.h file, described in IEEE Std. 1364- 2001, Annex G. The numbers in the range 800 - 899 are reserved for the read data access portion of the VPI.
30.4 VPI object type additions
30.5 Object model diagrams
A traverse object of type vpiTrvsObj is related to its parent object; it is a means to access the value data of said object. An object can have several traverse objects each pointing and moving in a different way along the value data horizon. This is shown graphically in the model diagram below. The traversable class is a representational grouping consisting of any object that:
  • Has a name
  • Can take on a value accessible with vpi_get_value(), the value must be variable over time (i.e. necessitates creation of a traverse object to access the value over time).
The class includes nets,... more
30.6 Usage extensions to VPI routines
Several VPI routines, that have existed before SystemVerilog, have been extended in usage with the addition of new object types and/or properties. While the extensions are fairly obvious, they are emphasized here again to turn the reader’s attention to the extended usage.

Table 30-1: Usage extensions to Verilog 2001 VPI routines

30.7 VPI routines added in SystemVerilog
This section lists all the VPI routines added in SystemVerilog.

Table 30-2: VPI routines

Table 30-3: Reader VPI routines

30.8 Reading data
Reading data is performed in 3 steps:
  1. A design object must be selected for traverse access from a database (or from memory).
  2. Indicate the intent to access data. This is typically done by a vpi_load_init() call as a hint from the user to the tool on which areas of the design are going to be accessed. The tool shall then load the data in an invisible fashion to the user (for example, either right after the call, or at traverse handle creation, or usage). Alternatively, if the user wishes he can (also) choose to add a specific vpi_load() call (this... more
30.9 Optionally unloading the data
The implementation tool should handle unloading the unused data in a fashion invisible to the user. Managing the data caching and memory hierarchy is left to tool implementation but it should be noted that failure to unload can affect the tool performance and capacity.

The user can optionally choose to call vpi_unload() to unload the data from (active) memory if the user application is done with accessing the data.

Calling vpi_unload() before releasing (freeing) traverse (collection) handles that are manipulating the data using vpi_free_object() is not recommended practice by users; the behavior of traversal using existing handles is not defined... more
30.10 Reading data from multiple databases and/or different read library providers
The VPI routine vpi_load_extension() is used to load VPI extensions. Such extensions include reader libraries from such tools as waveform viewers. vpi_load_extension() shall return a pointer to a function pointer structure with the following definition.
30.11 VPI routines extended in SystemVerilog
Table 30-1 lists the usage extensions. They are repeated here the additional extended usage with traverse (collection) handles of vpi_get_time() for clarity.
30.12 VPI routines added in SystemVerilog
This section describes the additional VPI routines in detail.


主题

主题
第三章 数据类型
主题
主题
描述
3.1 简介（一般信息）
为了能够平滑地从/向C语言移植，SystemVerilog支持C语言内建的数据类型，并具有C编译器给出的含义。然而，为了避免int和long数据类型的重复所带来的混淆，在SystemVerilog中，int是32位的，longint是64位的。C语言中float类型在SystemVerilog中称为shortreal，这样就不会与Verilog-2001的real类型混淆。

Verilog-2001具有线网数据类型，它具有0、1、X或Z的值，加上7种强度，具有120个值。Verilog-2001还具有诸如reg（具有0、1、X或Z这四种值）一类的变量数据类型。它们不仅仅是不同的数据类型，而且在使用上也是不同的。SystemVerilog加入了另外一个四值数据类型，这个数据类型被称为logic（参见3.3.2节和5.6节）。

SystemVerilog加入了字符串、chandle和class数据类型，并且增强了Verilog的event数据类型。

Verilog-2001通过使用reg数据类型提供了任意固定长度的算术运算。reg类型的各个位可能具有X或Z的值，然而相对于一个位数组来讲，因为这种数据类型的操作符计算必须检查X和Z，并且需要两倍的数据存储空间，它相对来说缺乏效率。SystemVerilog加入了一个bit数据类型，这种数据类型仅具有0或1两种值。参见3.3.2节中有关两态数据类型的内容。

在从一个较少位数向较多位数自动转换的时候，如果是无符号数则会引起0扩展，如果是有符号数则会引起符号扩展，并且这种情况不会引起警告信息。而从一个较多位数向较少位数自动转换的时候，则会引起警告信息。在logic和bit之间自动转换的时候不会引起警告信息。在从logic值转换到bit值的时候，1转换成1，其它值均转换成0。

typedef可以引入用户定义的数据类型，用户定义的数据类型必须在其使用之前定义。数据类型还可以作为模块或接口的参数，这就使得他们可以像面向对象编程中的类模板一样使用。一个例程在写入的时候可以反转任何数组中元素的顺序，而这在C语言和Verilog中是不可能的。

由于结构体标签和联合体标签具有分离的命名空间，因此它们在C语言中较为复杂。SystemVerilog遵从C的语法，但没有可选的结构体标签。

参见第四章中有关数组的说明。
3.2 数据类型语法
3.3 整数数据类型
SystemVerilog提供了几种整数数据类型，它们是Verilog和C数据类型的结合：

表格3-1：整数数据类型

3.4 real与shortreal数据类型
real1数据类型来自于Verilog-2001，与C语言中的double数据类型相同。shortreal数据类型是一个SystemVerilog数据类型，与C语言中的float数据类型相同。
3.5 void数据类型
void数据类型代表数据不存在。这种类型可以用作函数的返回类型，表示没有返回值。这种数据类型还可以用于标签联合体的成员（参见3.11节）。
3.6 chandle数据类型
chandle数据类型代表使用DPI直接编程接口传递的指针的存储空间（参见第二十七章）。这种类型的尺寸依赖于使用的平台，但在工具运行的机器上应该至少大到能够容纳一个指针。

chandle数据类型的声明语法如下：
3.7 string数据类型
SystemVerilog包含一个string数据类型，它是一个可变尺寸、动态分配的字节数组。SystemVerilog还包含许多特殊的方法来对字符串进行操作。

Verilog也支持字符串文本，但这种支持仅仅是在词法级别上。在Verilog中，字符串文本表现为一个具有宽度为8位整数倍的压缩数组。当一个字符串文本被赋值到一个具有不同尺寸的integral类型的压缩数组变量的时候，它或者被截短到变量的尺寸或者必要时在左侧填补0。

在SystemVerilog中，字符串文本的表现行为与Verilog相同。然而，SystemVerilog还支持string数据类型，我们可以将一个字符串文本赋值到这种数据类型。当使用string数据类型来替代一个integral变量的时候，字符串可以具有任意的长度并且不会发生截短现象。当文本字符串赋值到一个string数据类型或者在一个使用string类型操作数的表达式中使用的时候，它会被隐式地转换成string数据类型。

string类型的变量可以从0到N-1（数组的最后一个元素）进行索引，而且可以作用于一个特殊的空字符串：""。从一个字符串读取一个元素会产生一个字节。
3.8 event数据类型
event数据类型是Verilog命名事件的增强。SystemVerilog事件为一个同步对象提供了一个句柄。与Verilog一样，事件变量可以被显式地触发以及等待。更进一步，SystemVerilog事件还具有一个稳固的触发状态，它在整个时间步值间隔内持续。此外，一个事件变量可以被赋值为另外一个事件变量或者被赋值为特殊的null值。当赋值为另外一个事件变量的时候，这两个事件变量均指向相同的同步对象。当赋值为null的时候，同步对象与事件变量之间的关系被切断。事件还可以作为任务的参数传递。

event的声明语法如下：
3.9 用户定义的类型
3.10 枚举
3.11 结构体与联合体
3.12 类
类是数据以及一组对数据进行操作的子程序的集合。类中的数据被称为类属性，它的子程序被称为方法。类属性和方法一起定义了一个类实例或对象的内容和能力。
3.13 单一类型与集合类型
数据类型可以分为两类：单一类型与集合类型。一个单一类型应该是除非压缩结构体、非压缩联合体、或非压缩数组（参见第四章有关数组的内容）之外的任何数据类型。一个集合类型应该是任何非压缩结构体、非压缩联合体、或非压缩数组数据类型。一个单一变量或表达式代表一个单一的值、符号、或句柄。集合表达式和变量代表一组单一值。integral类型总是单一的，即使它们可以被分片成多个单一值。

通过定义这些类别，操作符和函数能够简单地将这些数据类型当作一个集合组来引用。例如：某些函数能够递归地解析一个集合类型直到获得一个单一值，然后就可以对每一个单一值进行操作。

注意：虽然类是一种数据类型，但没有直接的类变量或表达式，而仅仅存在类对象的句柄，并且类对象的句柄为单一值。因此，类不需要按这种方式分类（参见第十一章有关类的内容）。
3.14 强制类型转换
3.15 $cast动态强制类型转换
在由于不同的数据类型而导致变量不能正常赋值的情况下，SystemVerilog提供了$cast系统任务来进行赋值操作。$cast可以作为任务或函数来调用。

$case的语法如下：
3.16 位流强制类型转换
强制类型转换还可以应用于非压缩数组以及非压缩结构体。这样就使得通过显式强制类型转换在位流类型之间自由地转换成为可能。可以压缩成一个位流的类型称为位流类型。位流类型包含下列的类型：
  • 任何integral、压缩、或字符串类型
  • 非压缩数组、结构体、或上述类型的类
  • 任何上述类型的动态尺寸数组（动态的、联合的、或队列）

这个定义是递归的，例如，一个包含int队列的结构体是一个位流类型。

假定A具有source_t的位流类型，B具有dest_t的位流类型，那么我们可以使用显式强制类型转换将A转换到B：


主题

主题
第九章 进程
主题
主题
描述
9.1 简介（一般信息）
Verilog-2001具有定义了静态进程的always和initial块。

在一个用来建模组合逻辑的always块中，如果忘记了else语句会产生一个不期望的锁存器。为了避免这个错误，SystemVerilog加入了专门的always_comb和always_latch块，它向仿真、综合和形式验证工具指明设计意图。SystemVerilog还加入了一个always_ff块来指示时序逻辑。

在系统建模过程中，Verilog的一个主要限制是缺乏动态创建进程的能力，这种能力在操作系统中经常出现。虽然Verilog具有fork...jion结构，但它仍然被限制成静态的。

SystemVerilog既具有由always、initial或fork引入的静态进程，也具有由fork...join_any和fork...join_none引入的动态进程。

SystemVerilog为每一个initial或always块、fork...join块中的每一条并行语句以及为每一个动态进程均创建了一个执行线程。每一条连续赋值语句也被认为是它自己的线程。

SystemVerilog 3.1通过增强fork...join结构加入了动态进程的能力，这种方式对于Verilog用户来说是非常自然的。SystemVerilog 3.1还引入了动态进程控制结构，它能够使用动态、父子关系来中止或等待进程。它们是wait fork和disable fork。
9.2 组合逻辑
SystemVerilog提供了一个特殊的always_comb过程来建模组合逻辑行为。例如：
9.3 锁存逻辑
SystemVerilog还包含了一个特殊的always_latch过程来建模锁存逻辑行为。例如：
9.4 时序逻辑
SystemVerilog的always_ff过程可以用来建模可综合的时序逻辑行为。例如：
9.5 连续赋值
在Verilog中，连续赋值只能驱动线网，而不能驱动变量。

SystemVerilog去除了这个限制，允许连续赋值驱动任何类型的变量。线网可以被多个连续赋值驱动，或者被原语和连续赋值混合驱动。而变量仅仅能够被一个连续赋值或一个原语驱动。对于被一个连续赋值或原语输出驱动的变量来说，在其声明或任何过程赋值中包含初始化是错误的。参见5.6节。
9.6 fork...join
fork...join能够从它的每一个并行语句中产生并发进程。

fork...join块的声明语法如下：
9.7 进程执行线程
SystemVerilog为下列进程产生一个执行线程：
  • 每一个initial块
  • 每一个always块
  • fork...join（或join_any，或jion_none）语句组中的每一个并行语句
  • 每一个动态进程
每一个连续赋值也可以认为是它自己的线程
9.8 进程控制
SystemVerilog提供了一些结构，它们允许一个进程能够中止其它进程，或者等待其它进程的结束。wait fork等待进程的结束。disable fork结构停止进程的执行。
9.9 精细的进程控制
进程是一个内建的类，一旦一个进程被启动，就允许这个进程访问和控制另外一个进程。用户可以声明进程类型的变量，并且能够通过任务对它们进行安全的传递，或者将它们结合到其它对象中。进程类的原型如下：


主题

主题
第二十一章 参数
主题
主题
描述
21.1 简介（一般信息）
Verilog-2001提供了三种结构来定义编译时常量：parameter、localparam和specparam语句。

SystemVerilog提供了四种方法来设置设计中的参数常量的值。每一个参数在声明时必须指定一个缺省值。我们可以使用下列方法之一来改变每一个模块实例的缺省参数值：
  • 隐含的内联参数重定义（例如：foo #(value, value) u1(...);）
  • 显式的内联参数重定义（例如：#(.name(value), .name(value)) u1 (...); ）
  • defparam语句，使用层次化路径名来重新定义每一个参数
21.2 参数声明语法


主题

主题
第二十七章 直接编程接口（DPI）
主题
主题 | 描述
27.1 概述 | Direct Programming Interface (DPI) is an interface between SystemVerilog and a foreign programming language. It consists of two separate layers: the SystemVerilog layer and a foreign language layer. Both sides of DPI are fully isolated. Which programming language is actually used as the foreign language is transparent and irrelevant for the SystemVerilog side of this interface. Neither the SystemVerilog compiler nor the foreign language compiler is required to analyze the source code in the other’s language. Different programming languages can be used and supported with the same intact SystemVerilog layer. For now, however, SystemVerilog 3.1 defines a foreign language layer... more
27.2 Two layers of the DPI | DPI consists of two separate layers: the SystemVerilog layer and a foreign language layer. The SystemVerilog layer does not depend on which programming language is actually used as the foreign language. Although different programming languages can be supported and used with the intact SystemVerilog layer, SystemVerilog 3.1 defines a foreign language layer only for the C programming language. Nevertheless, SystemVerilog code shall look identical and its semantics shall be unchanged for any foreign language layer. Different foreign languages can require that the SystemVerilog implementation shall use the appropriate function call protocol, argument passing and linking mechanisms. This shall be, however,... more
27.3 Global name space of imported and exported functions | Every task or function imported to SystemVerilog must eventually resolve to a global symbol. Similarly, every task or function exported from SystemVerilog defines a global symbol. Thus the tasks and functions imported to and exported from SystemVerilog have their own global name space of linkage names, different from compilation- unit scope name space. Global names of imported and exported tasks and functions must be unique (no overloading is allowed ) and shall follow C conventions for naming; specifically, such names must start with a letter or underscore, and can be followed by alphanumeric characters or underscores. Exported and imported tasks... more
27.4 导入的任务和函数 | 导入函数的使用与SystemVerilog原生函数类似。
27.5 Calling imported functions | The usage of imported functions is identical as for native SystemVerilog functions., hence the usage and syntax for calling imported functions is identical as for native SystemVerilog functions. Specifically, arguments with default values can be omitted from the call; arguments can be passed by name, if all formal arguments are named.
27.6 Exported functions | DPI allows calling SystemVerilog functions from another language. However, such functions must adhere to the same restrictions on argument types and results as are imposed on imported functions. It is an error to export a function that does not satisfy such constraints. SystemVerilog functions that can be called from foreign code need to be specified in export declarations. Export declarations are allowed to occur only in the scope in which the function being exported is defined. Only one export declaration per function is allowed in a given scope. Note that class member functions cannot be exported, but all other SystemVerilog... more
27.7 Exported tasks | SystemVerilog allows tasks to be called from a foreign language, similar to functions. Such tasks are termed “exported tasks”. All aspects of exported functions described above in Section 27.6 apply to exported tasks. This includes legal declaration scopes as well as usage of the optional c_identifier. It is never legal to call an exported task from within an imported function. These semantics are identical to native SystemVerilog semantics, in which it is illegal for a function to perform a task enable. It is legal for an imported task to call an exported task only if the imported task is declared... more
27.8 Disabling DPI tasks and functions | It is possible for a disable statement to disable a block that is currently executing a mixed language call chain. When a DPI import task or function is disabled, the C code is required to follow a simple disable protocol. The protocol gives the C code the opportunity to perform any necessary resource cleanup, such as closing open file handles, closing open VPI handles, or freeing heap memory. An imported task or function is said to be in the disabled state when a disable statement somewhere in the design targets either it or a parent for disabling. Note that the... more


主题

主题
第二十三章 系统任务与系统函数
主题
主题
描述
23.1 简介（一般信息）
SystemVerilog加入了几个将在下面几节中描述的系统任务和系统函数。

另外，SystemVerilog扩展了几个Verilog-2001系统任务的行为，这些扩展将在23.14节中描述。
23.2 确立时的typeof函数
23.3 typename函数
23.4 表达式尺寸系统函数
23.5 范围系统函数
23.6 Shortreal转换
Verilog 2001 defines a real data type, and the system functions $realtobits and $bitstoreal to permit exact bit pattern transfers between a real and a 64 bit vector. SystemVerilog adds the shortreal type, and in a parallel manner, $shortrealtobits and $bitstoshortreal are defined to permit exact bit transfers between a shortreal and a 32 bit vector.
23.7 数组查询系统函数
23.8 断言严重性系统任务
23.9 断言控制系统任务
23.10 断言系统函数
23.11 随机数系统函数
To supplement the Verilog $random system function, SystemVerilog provides three special system functions for generating pseudorandom numbers, $urandom, $urandom_range and $srandom. These system functions are presented in Section 12.12.
23.12 程序控制
In addition to the normal simulation control tasks ($stop and $finish), a program can use the $exit control task. When all programs exit, the simulation finishes and an implicit call to $finish is made. The usage of $exit is presented in Section 16.6 on program blocks.
23.13 覆盖系统函数
SystemVerilog has several built-in system functions for obtaining test coverage information: $coverage_control, $coverage_get_max, $coverage_get, $coverage_merge and $coverage_save. The coverage system functions are described in Section 29.2.
23.14 对Verilog-2001系统任务的增强
SystemVerilog adds system tasks and system functions as described in the following sections. In addition, SystemVerilog extends the behavior of the following:
  • %u and %z format specifiers:
    • For packed data, %u and %z are defined to operate as though the operation were applied to the equivalent vector.
    • For unpacked struct data, %u and %z are defined to apply as though the operation were performed on each member in declaration order.
    • For unpacked union data, %u and %z are defined to apply as though the operation were performed on the first member in declaration order.
    • %u and %z are not defined... more
23.15 $readmemb与$readmemh
23.16 $writememb and $writememh
SystemVerilog introduces system tasks $writememb and $writememh:
23.17 File format considerations for multi-dimensional unpacked arrays
In SystemVerilog, $readmemb, $readmemh, $writememb and $writememh can work with multi-dimensional unpacked arrays.

The file contents are organized in row-major order, with each dimension’s entries ranging from low to high address. This is backward compatible with plain Verilog memories.

In this organization, the lowest dimension (i.e. the right-most dimension in the array declaration) varies the most rapidly. There is a hierarchical sense to the file data. The higher dimensions contain words of lowerdimension data, sorted in row-major order. Each successive lower dimension is entirely enclosed as part of higher dimension words.

As an example of file format organization, here is... more
23.18 System task arguments for multi-dimensional unpacked arrays
The $readmemb, $readmemh, $writememb, and $writememh signatures are shown below:


主题

主题
第二十九章 SystemVerilog覆盖API
主题
主题
描述
29.1 需求
This chapter defines the Coverage Application Programming Interface (API) in SystemVerilog.
29.2 SystemVerilog real-time coverage access
This section describes the mechanisms in SystemVerilog through which SystemVerilog code can query and control coverage information. Coverage information is provided to SystemVerilog by means of a number of built-in system functions (described in Section 29.2.2) using a number of predefined constants (described in Section 29.2.1) to describe the types of coverage and the control actions to be performed.
29.3 FSM recognition
Coverage tools need to have automatic recognition of many of the common FSM coding idioms in Verilog/ SystemVerilog. This standard does not attempt to describe or require any specific automatic FSM recognition mechanisms. However, the standard does prescribe a means by which non-automatic FSM extraction occurs. The presence of any of these standard FSM description additions shall override the tool’s default extraction mechanism.

Identification of an FSM consists of identifying the following items:
  1. the state register (or expression)
  2. the next state register (this is optional)
  3. the legal states.
29.4 VPI coverage extensions


主题

主题
第二十二章 配置库
主题
主题 | 描述
22.1 简介（一般信息） | Verilog-2001提供了指定设计配置的能力，它指定了模块实例与特定Verilog HDL源代码之间的绑定信息。配置使用库。一个库是模块、原语、及其它配置的集合。分离的库映射文件指定了包含在库中的单元的源代码位置。库映射文件的名字典型情况下指定成仿真器或其它读入Verilog源代码的软件工具的调用选项。 SystemVerilog为Verilog配置加入了对接口的支持。
22.2 库 | 一个库是许多单元的命名集合。一个单元可以是一个模块、宏模块、原语、接口、程序、包或配置。一个配置是源代码与设计中的每一个实例之间的绑定规范。


主题

主题
第二十五章 编译器指令
主题
主题 | 描述
25.1 简介（一般信息） | Verilog provides the ‘define text substitution macro compiler directive. A macro can contain arguments, whose values can be set for each instance of the macro. For example:
25.2 `define宏 | In Verilog, the `define macro text can include a backslash ( \ ) at the end of a line to show continuation on the next line. In SystemVerilog, the macro text can also include `", `\`" and ``. An `" overrides the usual lexical meaning of ", and indicates that the expansion should include an actual quotation mark. This allows string literals to be constructed from macro arguments. A `\`" indicates that the expansion should include the escape sequence \", e.g.
25.3 `include | The syntax of the ‘include compiler directive is:


主题

主题
第二十八章 SystemVerilog断言API
主题
主题
描述
28.1 需求
SystemVerilog提供了断言的能力以便提供下列功能：
  • 一个用户的C语言代码与断言事件相互作用。
  • 编写第三方的断言“波形”转储工具。
  • 编写第三方的断言覆盖工具。
  • 编写第三方的断言调试工具。
28.2 Extensions to VPI enumerations
These extensions shall be appended to the contents of the vpi_user.h file, described in IEEE Std. 1364-2001, Annex G. The numbers in the range 700 - 799 are reserved for the assertion portion of the VPI.
28.3 Static information
This section defines how to obtain assertion handles and other static assertion information.
28.4 Dynamic information
This section defines how to place assertion system and assertion callbacks.
28.5 Control functions
This section defines how to obtain assertion system control and assertion control information.


主题

主题
第二十六章 考虑从SystemVerilog中删除的功能
主题
主题 | 描述
26.1 简介（一般信息） | Certain Verilog language features can be simulation inefficient, easily abused, and the source of design problems. These features are being considered for removal from the SystemVerilog language, if there is an alternate method for these features. The Verilog language features that have been identified in this standard as ones which can be removed from Verilog are defparam and procedural assign/deassign.
26.2 defparam语句 | The SystemVerilog committee has determined, based on the solicitation of input from tool implementers and tools users, that the defparam method of specifying the value of a parameter can be a source of design errors, and can be an impediment to tool implementation. The defparam statement does not provide a capability that cannot be done by another method, which avoids these problems. Therefore, the committee has placed the defparam statement on a deprecation list. This means is that a future revision of the Verilog standard might not require support for this feature. This current standard still requires tools to support... more
26.3 过程赋值与解赋值语句 | The SystemVerilog committee has determined, based on the solicitation of input from tool implementers and tools users, that the procedural assign and deassign statements can be a source of design errors, and can be an impediment to tool implementation. The procedural assign/deassign statements do not provide a capability that cannot be done by another method, which avoids these problems. Therefore, the committee has placed the procedural assign/deassign statements on a deprecation list. This means that a future revision of the Verilog standard might not require support for theses statements. This current standard still requires tools to support the procedural assign/deassign... more


主题

主题
第二十章 覆盖
主题
主题
描述
20.1 简介（一般信息）
Functional verification comprises a large portion of the resources required to design and validate a complex system. Often, the validation must be comprehensive without redundant effort. To minimize wasted effort, coverage is used as a guide for directing verification resources by identifying tested and untested portions of the design.

Coverage is defined as the percentage of verification objectives that have been met. It is used as a metric for evaluating the progress of a verification project in order to reduce the number of simulation cycles spent in verifying a design Broadly speaking, there are two types of coverage metrics. Those... more
20.2 定义覆盖模型：covergroup
The covergroup construct encapsulates the specification of a coverage model. Each covergroup specification can include the following components:
  • A clocking event that synchronizes the sampling of coverage points
  • A set of coverage points
  • Cross coverage between coverage points
  • Optional formal arguments
  • Coverage options
The covergroup construct is a user-defined type. The type definition is written once, and multiple instances of that type can be created in different contexts. Similar to a class, once defined, a covergroup instance can be created via the new() operator. A covergroup can be defined in a module, program, interface, or class.
20.3 在类中使用covergroup
By embedding a coverage group within a class definition, the covergroup provides a simple way to cover a subset of the class properties. This integration of coverage with classes provides an intuitive and expressive mechanism for defining the coverage model associated with a class. For example, In class xyz, defined below, members m_x and m_y are covered using an embedded covergroup:
20.4 定义覆盖点
A covergroup can contain one or more coverage points. A coverage point can be an integral variable or an integral expression. Each coverage point includes a set of bins associated with its sampled values or its valuetransitions. The bins can be explicitly defined by the user or automatically created by SystemVerilog. The syntax for specifying coverage points is given below.
20.5 Defining cross coverage
A coverage group can specify cross coverage between two or more coverage points or variables. Cross coverage is specified using the cross construct. When a variable V is part of a cross coverage, SystemVerilog implicitly creates a coverage point for the variable, as if it had been created by the statement coverpoint V;. Thus, a cross involves only coverage points. Expressions cannot be used directly in a cross; a coverage point must be explicitly defined first.

The syntax for specifying cross coverage is given below.
20.6 Specifying coverage options
Options control the behavior of the covergroup, coverpoint and cross. There are two types of options: those that are specific to an instance of a covergroup, and those that specify an option for the covergroup type as a whole.

The following table lists instance specific covergroup options and their description. Each instance of a covergroup can initialize an instance specific option to a different value. The initialized option value affects only
that instance.

Table 20-1: Instance specific coverage options

20.7 Predefined coverage methods
The following coverage methods are provided for the covergroup. These methods can be invoked procedurally at any time.

Table 20-5: Predefined coverage methods

20.8 Predefined coverage system tasks and functions
SystemVerilog provides the following system tasks and functions to help manage coverage data collection.

$set_coverage_db_name ( name ) — Sets the filename of the coverage database into which coverage information is saved at the end of a simulation run.

$load_coverage_db ( name ) — Load from the given filename the cumulative coverage information for all coverage group types.

$get_coverage ( ) — Returns as a real number in the range 0 to 100 the overall coverage of all coverage group types. This number is computed as described above.
20.9 Organization of option and type_option members
The type and type_option members of a covergroup, coverpoint, and cross items are implicitly declared structures with the following composition:


主题

主题
第二章 文本值
主题
主题 | 描述
2.1 简介（一般信息） | SystemVerilog文本值词法约定是Verilog文本值词法约定的扩展。SystemVerilog加入了文本时间值、文本数组值、文本结构体，并对文本字符串进行了增强。
2.2 文本值语法 |
2.3 整数和逻辑文本 | 文本整数值和文本逻辑值可以是带有尺寸标识的，也可以是不带有尺寸标识的。对于值的符号、截短和向左扩展，SystemVerilog与Verilog-2001遵守相同的规则。 SystemVerilog还加入了一个使用撇号（'）作为前缀来说明无尺寸1位值的能力，此时在撇号（'）与值之间没有基限定符。无尺寸值的所有位均被设置成这个指定的位值。在一个自决的关联文中，这些文本具有1位的宽度，并且值被当作是无符号的。
2.4 实数文本 | 定点格式（例如1.2）和指数格式（例如2.0e10）的缺省类型是real。可以使用强制类型转换将文本real值转换为shortreal类型（例如shortreal'(1.2)）。 强制类型转换在3.14节中描述。
2.5 时间文本 | 时间文本使用整数或定点格式的数紧跟着一个时间单位来表示（fs ps ns us ms s step），在时间单位和数之间没有空格。例如：
2.6 字符串文本 | 字符串文本由引号包围并且拥有自己的数据类型。非打印字符或其它特殊字符都使用一个反斜杠（\）作为开始。SystemVerilog加入了下列特殊字符串字符：
2.7 数组文本 | 数组文本在语法上与C语言的初始化设置类似，但数组文本允许使用复制操作符（{{}}）。
2.8 结构体文本 | 结构体文本在语法上类似于C语言的初始化设置。结构体文本必须具有一个类型，无论是通过上下文关联还是通过强制类型转换。


主题

主题
第五章 数据声明
主题
主题 | 描述
5.1 简介（一般信息） | 在SystemVerilog中存在几种形式的数据：文本值（参见第二章）、参数（参见第二十一章）、常量、变量、线网、以及属性（参见第六章）。 在Verilog-2001中，常量可以是文本值、genvar参数、localparam和specparam。Verilog-2001还具有变量和线网。变量必须使用过程语句写入，线网必须通过连续赋值或端口写入。 SystemVerilog扩展了变量的功能，变量既可以使用过程语句写入，也可以像wire那样使用单一的连续赋值进行驱动。由于关键字reg在许多情况下不再描述用户意图，所以加入了关键字logic作为等价于reg的更为精确的描述。Verilog-2001已经不赞成使用术语“寄存器”，取而代之的是术语“变量”。 除了隐式线网之外，SystemVerilog遵从Verilog中关于数据必须在其使用之前声明的规定。隐式线网的规则与Verilog-2001中的规定相同。 变量可以是静态的（在实例化的时候分配存储空间并且永远不会释放），也可以自动的（在进入变量作用范围（例如任务、函数或块）时分配并在退出时释放）。C语言具有static和auto关键字。SystemVerilog遵从Verilog中关于静态缺省存储类，以及自动的任务和函数的规则，但允许在这些任务和函数中使用静态存储覆盖一个特定变量的动态存储。
5.2 数据声明语法 |
5.3 常量 | 常量是永远也不会改变的命名数据变量。SystemVerilog中有三种类型的常量，它们分别使用关键字localparam、specparam和const声明。所有这三种类型的常量都使用一个文本值来初始化。
5.4 变量 | 变量声明包含一个数据类型紧跟着一个或多个变量实例。
5.5 作用范围与生命周期 | 在模块、接口、任务或函数外声明的任何数据都具有全局的作用范围（可以在其声明后的任何地方使用），并且具有一个静态的生命周期（在整个确立和仿真时间内存在）。 在模块或接口内但在任务、进程或函数之外声明的SystemVerilog数据具有本地的作用范围，并具有静态的生命周期（在模块或接口的生命周期内存在）。这大致等价于C语言中在函数外声明的静态数据，它对于文件来说是本地的。 在自动任务、函数或块内声明的数据具有调用期或激活期内的生命周期，并且具有本地的作用范围。这大致等价于C的自动变量。 在一个静态任务、函数或块内声明的数据缺省情况下具有静态的生命周期并具有本地的作用范围。 注意：在SystemVerilog中，数据既可以在未命名的块中声明也可以在命名的块中声明。这些数据对未命名的块及其底层的嵌套块都是可见的。但不能使用层次化引用来通过名字访问数据。 Verilog-2001允许将任务和函数声明成automatic的，这使得任务或函数内的所有存储空间都是自动的。SystemVerilog允许一个静态任务或函数内的特定数据被显式地声明成automatic的。声明成自动的数据具有调用或块内的生命周期，并且在每次进入调用或块内的时候进行初始化。fork...jion、fork...jion_any或fork...join_one块的生命周期应该包含块内所有进程的执行。一个包含任何fork...jion块范围的生命周期包括fork...jion块的生命周期。 SystemVerilog也允许数据被显式地声明成静态的。在一个自动任务、函数或块内声明的静态数据具有静态的生命周期并且对于块来说具有本地的作用范围。这类似于C语言中在一个函数内声明的静态数据。
5.6 线网、reg、与logic | Verilog-2001指出，线网可以使用一个或多个连续赋值语句、原语输出或模块端口写入。多驱动的结果值由线网类型的解析函数确定。线网不能使用过程赋值语句。如果端口一侧的线网被端口另一侧的变量所驱动，那么隐含是连续赋值。force语句可以覆盖线网的值。当其被释放以后，线网返回到解析的值。 Verilog-2001还指出，一个或多个过程语句可以对变量执行写操作，包括过程连续赋值。最后一次执行的写入操作确定变量的值。变量不能被连续赋值。force语句覆盖过程赋值语句，它轮流覆盖正常的赋值。变量不能通过端口写入，它必须通过一个隐含的由连续赋值驱动的线网写入。 在SystemVerilog中，所有变量现在都可以通过连续赋值写入，或者通过一个或多个过程语句写入，包括过程连续赋值。在一个被写入的逻辑变量的最长静态前缀扩展中（关于一个最长静态前缀扩展的定义，参见9.2.1节），对其中任何项使用连续赋值或过程赋值与连续赋值的混合来执行写入操作都是错误的。所有数据类型都可以通过一个端口写入。 SystemVerilog变量可以是其它数据类型的压缩或非压缩集合。对变量中独立元素的多个赋值被单独地检查。左侧包含了一个分片的赋值被看作是对整个分片的单一赋值。使用过程赋值与连续赋值的混合形式写入一个压缩结构体或压缩数组类型是错误的。因此，一个非压缩结构体或非压缩数组中的一个元素可以过程化赋值，而另一个元素可以进行连续赋值。并且，一个压缩结构体或压缩数组的每一个元素都可以使用单一的连续赋值。例如，对于下面的结构体声明：
5.7 信号别名 | Verilog assign语句是单向赋值并可以结合一个延时和强度变化。为了建模一个双向短路连接，很有必要使用alias语句。一个别名列表的成员是那些共享相同物理网络的信号。下面的例子实现了总线A和总线B之间的字节顺序交换。
5.8 类型兼容性 | 为了使操作数是合法的，某些SystemVerilog结构和操作要求某种程度的类型兼容。SystemVerilog具有四种层次的类型兼容，形式上进行如下的定义：等价、赋值兼容、强制转换兼容、以及不等价。 注意：这里没有定义相同类型这一类别，因为SystemVerilog语言中没有哪种结构需要这种类别。例如，就像下面定义的那样，int可以与bit signed [0:31]互换，只要在语法上这样做是合法的。用户可以使用$typename系统函数（参见23.3节，typname函数）或通过使用PLI来定义自己的类型标识层次。


主题

主题
第八章 过程语句和控制流
主题
主题 | 描述
8.1 简介（一般信息） | 过程语句通过下列语句引入：
8.2 语句 |
8.3 阻塞赋值与无阻塞赋值 |
8.4 选择语句 |
8.5 循环语句 |
8.6 跳转语句 |
8.7 final块 | final块类似于intial块，它们都定义了一个过程化的语句块，不同的是，final块仅仅在仿真时间的尾部无延时地执行。典型情况下，final块用来显示有关仿真的统计信息。
8.8 命名块与语句标签 |
8.9 disable | SystemVerilog具有break和continue来中断或继续循环的执行。Verilog-2001的disable也可以用来中断或继续一个循环，但不如break或continue好用。disable也可以用来关闭一个命名的未包含disable语句的块。如果那个块当前正在执行，会立即跳转到块之后的语句。如果块是一个循环体，那么它与continue起相同的作用。如果块当前没有执行，那么disable没有任何效果。 SystemVerilog可以在任务中使用return，但也支持disable。如果disable被应用到一个命名的任务，那么这个任务中所有当前正在运行的部分都会被关闭。
8.10 事件控制 |
8.11 电平敏感的序列控制 | 我们可以延迟过程代码的执行直到一个序列终结状态为“真”。为了达到这个目的，我们可以使用电平敏感的wait语句并结合内建方法triggered来实现，这个内建方法能够返回一个命名序列当前的结束状态。 如果指定的序列已经在特定的时间点（在当前的时间步值内）上到达了它的结束点，那么triggered方法返回“真”，否则返回“假”。一个序列的触发状态在Observe区域内设置，并且在时间步值的余下部分保持（也就是说直到仿真时间进入到下一步）。 例如：
8.12 过程赋值与解赋值的移除 | SystemVerilog当前支持过程赋值与解赋值语句。然而，这些语句在语言的未来版本中可能会被移除。参见26.3节。


主题

主题
第六章 属性
主题
主题 | 描述
6.1 简介（一般信息） | 在Verilog-2001中，用户可以为Verilog对象（例如模块、实例、wire等）加入命名的属性。属性还可以在扩展的SystemVerilog结构中指定，并作为BNF的一部分（参见附录A）。SystemVerilog还为属性定义了一个缺省的数据类型。
6.2 缺省属性类型 | 一个没有值的属性的缺省类型是bit，它的值为1。另外，属性接受表达式的类型。


主题

主题
第十一章 类
主题
主题
描述
11.1 简介
SystemVerilog引入了一个面向对象的类数据抽象。类允许对象动态地产生、删除、赋值、以及通过对象句柄访问。对象句柄为语言提供了一种安全的、类似于指针的机制。类提供了继承和抽象建模的能力，这就将不带有任何类型安全性问题的C函数指针的优点引入到了SystemVerilog中，因此，它为Verilog带来了真正的多态性。
11.2 语法
11.3 概述
类是一种数据类型，它包含了数据以及对数据进行操作的子程序（函数和任务）。类的数据被称为类属性，它的子程序被称为方法，无论是类属性还是方法都是类的成员。类属性和方法结合在一起，定义了某种类型的对象的内容和能力。

例如，一个数据包可以是一个对象。它可能具有一个命令域、一个地址、一个序列号、一个时戳、以及一个数据包净荷。另外，一个数据包可以实现多项不同的任务：初始化数据包、设置命令、读取数据包的状态、或者检查序列号。尽管每一个数据包都是不同的，然而作为一个类，数据包具有某些固有的属性，这些固有属性可以在类的定义中进行说明。
11.4 对象（类实例）
类定义了一个数据类型。对象是类的实例。在使用一个类的时候，需要首先声明一个类型为该类的变量（这个变量保存了一个对象句柄），然后使用new函数产生该类的一个对象，然后再将它赋值给变量。
11.5 对象属性
一个对象的数据域可以通过将类属性名限定到一个实例名的方法来使用。继续使用先前的例子，Packet对象p的命令域可以按如下方式使用：
11.6 对象方法
我们可以使用与访问类属性相同的语法来访问一个对象的方法：
11.7 构造器
SystemVerilog没有要求C++那样的复杂的内存分配和释放。一个对象的构造是直接的，并且碎片收集象Java中那样是隐含的并且是自动的。它没有内存泄漏或其它微妙的行为，而这些往往成为C++程序员的噩梦。

SystemVerilog提供了一种机制在产生对象的时候初始化一个实例。当对象被产生的时候，例如：
11.8 静态类属性
前面的例子仅仅声明了实例类属性。每一个类的实例（也就是Packet类型的每一个对象）的每一个变量都有它自己的拷贝。有时要求所有的实例共享变量的一个版本。这些类属性使用关键字static产生。下面的例子演示了一个类的所有实例需要访问一个共用的文件描述符的情况：
11.9 静态方法
方法也可以被声明成静态的。一个静态方法遵从于所有的类范围和访问规则，但在表现上它就像一个常规的子例程一样可以在类的外部被调用，即使没有该类的实例。一个静态方法不能访问非静态的成员（类属性和方法），但它可以直接访问静态类属性或调用同一个类的静态方法。在一个静态方法体内部访问非静态成员或访问特殊的this句柄是非法的，并且会导致一个编译错误。静态方法不能是虚拟的。
11.10 this
this关键字被用来明确地引用当前实例的类属性或类方法。this关键字指示了一个预定义的对象句柄，这个句柄引用了被用来调用this在其中使用的子例程的对象。this关键字应该仅仅使用在非静态的类方法中，否则会发布一个错误。例如，下面的声明是一个用来编写初始化任务的基本方法：
11.11 赋值、重命名与拷贝
声明一个类变量仅仅产生一个名字，这个名字表示了一个对象。因此：
11.12 继承与子类
前一节定义了一个称为Packet的类。我们可以扩展这个类以便使packet串接在一起形成一个链表。一种解决方案是产生一个新的被称为LinkedPacket的类，它包含一个类型为Packet的变量：packet_c。

为了引用Packet类属性，需要引用变量packet_c。
11.13 过载成员
子类对象也是它们的父类对象的有效表示。例如，每一个LinkPacket对象都是一个完全合法的Packet对象。

一个LinkedPacket对象的句柄可以赋值到一个Packet变量：
11.14 super
super关键字在一个继承类的内部使用，可以用来引用其父类的成员。当父类成员被继承类成员过载的时候就有必要使用super关键字来访问负类的成员。
11.15 强制类型转换
将一个子类变量赋值给层次树中较高的类变量是合法的。将一个超类变量直接赋值给一个子类变量则是非法的。然而，如果超类句柄引用了指定子类的句柄，那么将一个超类句柄赋值给一个子类变量则是合法的。

为了检查赋值是否合法，需要使用动态强制类型转换函数$cast（参见3.15节）。

$cast()的语法如下：
11.16 串接构造器
一个子类在实例化的时候会调用类方法new()。在函数中定义的任何代码执行之前，new()执行的一个动作是调用其超类的new()方法，并且会沿着继承树按这种方式一直向上调用。因此，所有的构造器都会按正确的顺序调用，它们都是起始于根基类并结束于当前的类。

如果超类的初始化方法需要参数，那么会有两种选择：一种选择是总是提供相同的参数，另外一种选择是使用super关键字。如果参数总是相同的，那么它们可以在被扩展的时候指定：
11.17 数据隐藏与封装
到目前为止，所有的类属性和方法都毫无限制地在类外可见。然而，我们有时希望通过隐藏类属性和类方法的名字来限制在类的外部访问类属性和类方法。这就使得其它程序员能够不依赖于一个特定的实现，而且它还防止仅对类内部有效的类属性被偶然地修改。当所有的数据都变成隐藏的（仅能被公共方法访问），代码的维护和测试都变得更加容易。

在SystemVerilog中，未被限定的类属性和方法是公共的，它们对访问对象名字的任何人都是有效的。

一个被标识成local的成员仅对类内的方法有效。而且这些本地成员在子类内是不可见得。当然，访问本地类属性或方法的非本地方法可以被继承，并且作为子类的方法它可以正确地工作。

除了可以被继承以及对子类可见外，一个被标识成protected的类属性或方法具有本地成员的所有特性。

注意：在类的内部，一个本地方法或类属性可以被引用，即使它处于一个不同的实例中。例如：
11.18 常量类属性
与任何其它SystemVerilog变量一样，类属性可以通过const声明成只读的。然而，由于类属性是动态的对象，类属性允许两种形式的只读变量：全局常量和实例常量。

全局常量类属性是那些在声明中包含了初始值得常量类属性。它们与其它的const变量类似，也就是它们不能在除声明之外的其它地方赋值。
11.19 抽象类与虚拟方法
我们可以产生一组类，它们可以看作是来源于一个共用的基类。例如，一个类型为BasePacket的公用基类设置了一个包的初始结构，但这个结构并不完整，因此它永远也不会被实例化。然而从这个基类开始，我们可以派生许多子类，例如以太网包、令牌环包、GPSS包、卫星包。这些包的每一个可能看上去很相似，它们都需要相同的方法集合，但它们在内部的实现细节上则存在明显的不同。

一个基类设置了其子类的原型。由于设置基类的目的就不是为了实例化，所以可以将类指定成virtual以便使其变得抽象：
11.20 多态性：动态方法查找
多态性使得超类中的一个变量能够保存子类对象，并且能够直接从超类变量中引用这些子类的方法。考虑一个例子，假设Packet对象的基类BasePacket通过虚拟函数定义了通常由它的子类使用的所有公开方法（例如send、receive、print等）。这时，尽管BasePacket是抽象的，它仍然可以用来声明一个变量：
11.21 类范围解析操作符 ::
类范围操作符 :: 被用来指定在一个类作用范围内定义的一个标识符。它具有下列形式：
11.22 块外声明
如果能够将方法定义放在类声明体的外部，那将是很方便的。这个功能可以通过两个步骤完成。首先，在类声明体内声明方法的原型（无论它是任务还是函数）、任何限定符（local、protected或virtual）、以及完整的参数说明加上extern限定符。extern限定符指示方法体（它的实现）在类声明的外部。接着，在类声明的外部声明完整的方法（与原型类似但没有限定符），并将这个方法绑定回它所属的类：使用一对冒号（::）将方法名限定为类名字。
11.23 参数化的类
如果定义一个基本类，它的对象在实例化的时候可以具有不同的数组尺寸或数据类型，那么这种功能通常很有用。我们可以不必为每一个尺寸或类型编写相同的代码，并且可以为本质上不同并且不可互换的对象使用同一个说明（这与C++的类模板类似）。

普通的Verilog参数机制可以用来参数化一个类：
11.24 typedef类
有时一个类变量需要在类本身被声明之前声明。例如，如果两个类中的每一个类都需要另外一个类的句柄。在编译器处理第一个类的声明期间，编译器遇到了第二个类的引用，而这个引用是未定义的，因此编译器会将它标记为一个错误。

通过使用typedef来为第二个类提供提前声明就可以解决这个问题：
11.25 类与结构体
SystemVerilog加入了面向对象的类结构。从表面上看，类与结构体似乎提供了等价的功能，似乎只需要其中的一个就足够了。然而，事实并非如此；类在下述四个基本方面与结构体是不同的：
  1. SystemVerilog结构体是严格的静态对象；它们或者在一个静态的存储位置（全局或模块的作用范围）或者在一个自动任务的堆栈中产生。相反，SystemVerilog对象（也就是类实例）则是动态的，它们的声明不会产生对象，产生对象是通过调用new实现的。
  2. SystemVerilog结构体是类型兼容的，只要它们的位尺寸是相同的，因此拷贝具有不同的构成但尺寸相等的结构体是合法的。相反，SystemVerilog对象具有严格强类型。将一种类型的对象拷贝到另外一个类型的对象是不被允许的。
  3. SystemVerilog对象使用句柄实现，因此它提供了类似于C语言指针的功能。但SystemVerilog不允许为其它类型产生句柄，因此，与C语言不同的是，能够保证SystemVerilog句柄是安全的。
  4. SystemVerilog对象构成了面向对象数据抽象的基础，它提供了真正的多态性。类实例、抽象类、以及动态强制类型转换提供了强大的机制，它远远超过了结构体仅能提供的封装机制。
11.26 内存管理
对象、字符串、动态数组、以及联合数组的内存是动态分配的。当创建对象的时候，SystemVerilog会分配更多的内存。当对象不再需要的时候，SystemVerilog自动地释放内存以便这些内存能够被重新使用。自动的内存管理系统是SystemVerilog的整体组成部分。如果没有自动的内存管理，SystemVerilog的多线程、重进入环境会增加许多导致用户出错的机会。一个手工的内存管理系统（就像C语言的malloc和free所提供的那样）是不够的。

例如，考虑下面的例子：


主题

主题
第十七章 断言
主题
主题
描述
17.1 简介（一般信息）
SystemVerilog加入了为一个系统指定断言的功能。断言说明了系统的一个行为。断言主要用来验证一个设计的行为。另外，断言可以被用来提供功能覆盖以及产生验证的输入激励。

SystemVerilog具有两种类型的断言：并发断言和即时断言。
  • 即时断言的执行遵从仿真事件语义并且像一个过程块中的一条语句一样执行。即时断言的主要目的是与仿真一起使用。
  • 并发断言基于时钟语义并使用变量的采样值。SystemVerilog断言的目标之一就是为断言提供一个公共的语义，这样它们可以被用来驱动不同的设计和验证工具。许多工具，例如形式验证工具，使用基于周期的语义来评估电路描述，典型情况下这种方法依赖于一个时钟信号或者信号组来驱动电路的评估。在时钟沿之间的任何时序或事件行为都会被忽略。并发断言结合了这些时钟语义。虽然这种方法通常简化了一个电路描述的评估，然而却存在一些情况，在这些情况下基于周期的评估提供了与标准的SystemVerilog基于事件的计算不同的行为。

本章表述了这两种类型的断言。
17.2 即时断言
即时断言语句是一个表达式的测试，当语句在程序代码中执行的时候完成。表达式是非时间的，并且按一个过程化if语句的条件中的表达式相同的方式解释。也就是说，如果表达式计算成X、Z或0，那么它被解释成假并且认为断言失败。否则，表达式被解释成真，并且认为断言通过。

即时断言语句是一个statement_item，并且可以在一个过程化语句被说明的任意地方说明。
17.3 并发断言概述
并发断言描述了贯穿时间的行为。与即时断言基于时钟的计算模型不同，并发断言仅在一个时钟标记出现的时候被计算。在计算中使用的变量值是采样的值。通过这种方式，我们可以获得一个可预测的结果，而不管仿真器内部的对事件进行排序和计算的机制如何。这种模型也对应于从RTL描述获得的硬件解释的综合模型。

断言中使用的变量值在一个时隙的Preponed区域被采样，并且断言在Observe区域被计算。这一点在第十四章 调度语义中解释。

一个并发断言规范采用的时序模型基于时钟标记并使用一个通用的时钟周期概念。一个时钟的定义由用户明确地说明并且在表达式之间可以存在不同。

一个时钟标记是时间上的一个原子瞬间，它本身并不具有在时间上的持续期。在任意仿真时间，一个时钟应该只标记一次，并且在这个仿真时间上采样的值被用于当前断言的计算。在一个断言中，采样值是一个时钟标记上变量唯一有效的值。图17-1显示了随着时钟的推进一个变量的值。在时钟标记1和2，req信号的值是低。在时钟标记3，采样的值为高并保持为高直到时钟标记6。变量req在时钟标记6处的采样值为低并保持为低直到时钟标记10。注意，仿真值跃变到高发生在时钟标记9。然而，时钟标记9处的采样值仍为低。

图17-1 — 在仿真标记上采样一个变量

在一个表达式中使用的表达式总是被绑定到一个时钟定义。采样值被用来计算值变化表达式或者用来确定一个序列匹配的布尔子表达式。

注意：

  • 一个重要的一点是要确保定义的时钟行为是没有毛刺的。否则会采样到错误的值。
  • 如果一个出现在时钟表达式中变量也出现在一个断言表达式中，那么这个变量的值在两个使用中可以是不同的。变量的当前值被用在时钟表达式中，而变量的采样值则用于断言。
控制序列计算的时钟表达式可以比仅仅是单一的信号名更加复杂。诸如(clk && gating_signal)和(clk iff gating_signal)之类的表达式可以被用来代表一个门时钟。其它更加复杂的表达式也是可能的。然而，为了确保正确的系统行为并尽可能真正地符合基于周期的语义，一个时钟表达式中的信号必须是无毛刺的，并且在任何仿真时间只能跃变一次。

并发断言的一个例子如下：
17.4 布尔表达式
在序列中使用的表达式针对表达式中出现的变量的采样值进行计算。一个表达式计算的结果是布尔值，并且与一个过程化if语句中条件表达式的解释方式相同。也就是说，如果表达式计算成X、Z、或0，那么它被解释成“假”。否则解释成“真”。

出现在并发断言中的表达式存在某些限制。对操作数类型、变量和操作符的限制在后续的章节中描述。

表达式可以包含函数调用，但存在某些语义限制。
  • 出现在表达式中的函数不能包含输出或ref参数（允许使用const ref）。
  • 函数应该是自动的（或者不保留状态信息）并且没有边带效应。
17.5 序列
17.6 声明序列
一个序列可以在下列单元中声明：
  • 一个模块
  • 一个接口
  • 一个程序
  • 一个时钟控制块
  • 一个包
  • 一个编译单元的作用范围
序列使用下列的语法进行声明：
17.7 序列操作
17.8 处理一个序列中的数据
使用一个SystemVerilog静态变量意味着仅存在它的一份拷贝。如果需要在流水线设计中检查数据值，那么对于每一个进入流水线的数据量值，我们可以使用一个单独的变量来存储预期的流水线输出，以便在真正退出管线的时候比较结果。这个存储空间可以通过使用一个变量数组来构建，并且为了最小化通过流水线的传播这个数组可以安排在一个移位寄存器中。然而，在一些更为复杂的情况下，例如管线的潜伏期是可变的并且是乱序的，那么这种结构可能就变得非常复杂并且容易出错。因此，我们需要一些局部变量，这些变量在一个特定的、能够跨越任意时间间隔的事务检查中使用，并且能够与其它事务检查重叠。所以，这样的一个变量必须能够在需要的时候在一个序列实例中动态地产生并能在序列结束的时候移除。

一个变量的动态产生极其赋值是通过在一个序列或特性声明中使用局部变量声明并在序列中赋值来实现的。
17.9 在一个序列匹配时调用子程序
任务、任务方法、void函数、void函数方法以及系统任务可以在一个序列成功匹配的结束处调用。子程序调用，例如局部变量赋值，出现在紧跟着序列的以逗号分割的列表中。子程序调用被称为附加到序列。序列以及之后的列表以括号包围。
17.10 系统函数
断言一般被用来计算一个设计实现的某些特定属性，例如一个特定的信号是否为“热点（one-hot）”。SystemVerilog中包含下列系统函数来促进这些基本的断言功能：
  • $onehot(<expression>) ：如果表达式中只有一位为高，那么返回“真”。
  • $onehot0(<expression>) ：如果表达式中至少有一位为高，那么返回“真”。
  • $isunknown(<expression>) ：如果表达式任何一位为X或Z，那么返回“真”，等价于：^<expression> === 'bx。
所有上述的系统函数都具有一个bit类型的返回值。1'b1的返回值指示“真”，1'b0的返回值指示“假”。

为布尔表达式提供的另外一个有用的函数是$countones，它可以计算一个位向量表达式中1的数目。
17.11 声明特性
一个特性定义了设计的一个行为。一个特性可以作为一个假设、一个检查器或者一个覆盖率规范被用于验证。为了将这种行为用于验证，必须使用一个断言、假设或者覆盖语句。一个特性声明本身不会产生任何结果。

一个特性可以在下列结构中声明：
  • 一个模块
  • 一个接口
  • 一个程序
  • 一个时钟控制块
  • 一个包
  • 一个编译单元作用域
为了声明一个特性，我们可以使用如下所示的property结构：
17.12 多时钟的支持
多时钟序列和特性可以使用下列的语法说明。
17.13 并发断言
A property on its own is never evaluated for checking an expression. It must be used within a verification statement for this to occur. A verification statement states the verification function to be performed on the property. The statement can be one of the following:
  • assert to specify the property as a checker to ensure that the property holds for the design
  • assume to specify the property as an assumption for the environment
  • cover to monitor the property evaluation for coverage
A concurrent assertion statement can be specified in:
  • an always block or initial block as a statement, wherever these... more
17.14 时钟解析
SystemVerilog具有多种方法为一个特性指定时钟。

— 具有一个时钟的序列实例，例如：
17.15 将特性绑定到作用域或实例
To facilitate verification separate from the design, it is possible to specify properties and bind them to specific modules or instances. The following are the goals of providing this feature:
  • It allows verification engineers to verify with minimum changes to the design code/files.
  • It allows a convenient mechanism to attach verification IP to a module or an instance.
  • No semantic changes to the assertions are introduced due to this feature. It is equivalent to writing properties external to a module, using hierarchical path names.
With this feature, a user can bind a module, interface, or program instance to a module... more
17.16 expect语句
The expect statement is a procedural blocking statement that allows waiting on a property evaluation. The syntax of the expect statement accepts a named property or a property declaration, and is given below.


主题

主题
第十三章 进程间的同步与通信
主题
主题
描述
13.1 简介（一般信息）
对于用来对一个复杂系统或高度灵活的测试平台进行建模的动态进程来说，高层次并且易于使用的同步和通信机制对于控制它们之间的通信是非常必要的。Verilog提供了基本的同步机制（也就是->和@），但它们仅限于静态对象，虽然这对于硬件级的同步来说是足够的，然而它们却不能满足高度动态、灵活的测试平台的需要。在系统级，Verilog的一个本质上的限制就是它缺乏创建动态事件和通信通道的能力，而这些对于创建动态进程却是必需的。

SystemVerilog加入了强大而又易于使用的同步和通信机制的集合，所有这些都可以动态地产生和回收。SystemVerilog加入了一个内建的semaphore类，这个内建类可以用来同步以及相互排斥地共享资源。一个mailbox内建类可以用作是进程间的通信通道。SystemVerilog还增强了Verilog的命名事件数据类型以便满足许多系统级的同步需求。

semaphore和mailboxe是内建类型，尽管如此，它们仍然是类，并且可以用作基类以便衍生额外的更高层次的类。这些内建的类驻留在内建的std包中（参见7.10.1节），因此它们可以在任何其它范围内被用户代码重新定义。
13.2 semaphore
从概念上讲，一个semaphore是一个桶。当为semaphore分配内存的时候，会产生一个包含固定数目键值的桶。使用semaphore的进程在继续执行之前必须首先从桶中获得一个键值。如果一个特定的进程要求一个键值，那么只能同时出现固定数目的进程。所有其它进程必须等待直到足够数目的键值返回到桶中。典型情况下semaphore被用来控制对共享资源的互斥访问，以及用来实现基本的同步。

产生一个semaphore的例子如下：
13.3 mailbox
maibox是一种通信机制，它使得消息能够在进程间通信。被一个进程发送到一个mailbox的数据可以被另外一个进程重新获得。

从概念上讲，mailbox的行为就像一个真实的邮箱一样。当一封信被分发并且放入到邮箱的时候，一个人可以重新获得这封信（以及存储在其中的任何数据）。然而，如果当这个人检查邮箱的时候这封信还没有被分发，那么这个人必须做出选择：它要么等待这封信被分发，要么在下一次检查邮箱的时候重新获得这封信。与此类似，SystemVerilog的mailbox以一个可控的方式来传输和接收数据。在产生mailbox的时候，它可以具有有界的队列尺寸也可以具有无边界的尺寸。当一个有界mailbox包含了其边界数目的消息的时候，mailbox会变满。一个试图向已经满了的mailbox放置消息的进程应该被挂起，直到在mailbox队列中具有足够的空间。在一个发送操作中，无边界mailbox永远也不会挂起一个线程。

产生一个mailbox的例子如下：
13.4 参数化的mailbox
缺省的mailbox是无类型的，也就是说，单个mailbox可以发送和接收任何类型的数据。这是一个非常强大的机制，然而不幸的是，它也会因为一个消息与用来重新获得消息的变量间的类型不匹配而导致运行时错误。一个mailbox经常被用来传输一个特定的消息类型，在这种情况下，如果能够在编译时发现类型不匹配，那会是很有用的。

参数化的mailbox与参数化类（参见11.23节）、模块和接口使用相同的机制。
13.5 事件
在Verilog中，命名的事件是静态对象，它可以通过->操作符触发，并且通过@操作符进程可以等待一个事件被触发。SystemVerilog事件支持相同的基本操作，但它从几个方面增强了Verilog事件。最为显著的增强是：Verilog命名事件的触发状态没有持续时间，而在SystemVerilog中，这个触发状态在事件被触发的整个时间步值内持续。而且，SystemVerilog事件作为同步队列的句柄使用，因此，它们可以作为参数传递给任务，并且它们可以赋值到另外一个事件或者与另外一个事件进行比较。

现存的Verilog事件操作（@和->）是后向兼容的，当使用在静态Verilog上下文中的时候可以继续以相同的方式工作。下面所描述的其它功能可以在静态上下文或动态上下文中作用于所有的事件。

SystemVerilog事件为一个底层的同步对象提供了一个句柄。当进程等待一个事件被触发的时候，进程被放入到一个在同步对象内部维护的队列当中。进程可以或者通过@操作符，或者通过使用wait()结构检查它们的触发状态来等待一个SystemVerilog事件被触发。事件通过使用->或->>操作符来触发。
13.6 事件排序：wait_order()
wait_order结构会挂起调用进程直到所有指定的事件以指定的顺序（从左到右）被触发，或者任何为触发的事件被乱序触发，并因此会导致操作失败。

wait_order结构的语法如下：
13.7 事件变量
一个事件是一个唯一具有几个重要特性的数据类型。与Verilog不同，SystemVerilog事件可以被赋值到另外一个事件。当一个事件赋值到另外一个事件的时候，源事件的同步队列被源事件和目标事件所共享。从这个意义上讲，事件是一个全功能的变量而不仅仅是标签。


主题

主题
第十九章 接口
主题
主题 | 描述
19.1 简介（一般信息） | The communication between blocks of a digital system is a critical area that can affect everything from ease of RTL coding, to hardware-software partitioning to performance analysis to bus implementation choices and protocol checking. The interface construct in SystemVerilog was specifically created to encapsulate the communication between blocks, allowing a smooth migration from abstract system-level design through successive refinement down to lower-level register-transfer and structural views of the design. By encapsulating the communication between blocks, the interface construct also facilitates design re-use. The inclusion of interface capabilities is one of the major advantages of SystemVerilog. At its lowest level, an... more
19.2 接口语法 |
19.3 接口中的端口 | One limitation of simple interfaces is that the nets and variables declared within the interface are only used to connect to a port with the same nets and variables. To share an external net or variable, one that makes a connection from outside of the interface as well as forming a common connection to all module ports that instantiate the interface, an interface port declaration is required. The difference between nets or variables in the interface port list and other nets or variables within the interface is that only those in the port list can be connected externally by name... more
19.4 modport | To restrict interface access within a module, there are modport lists with directions declared within the interface. The keyword modport indicates that the directions are declared as if inside the module.
19.5 接口与specify块 | The specify block is used to describe various paths across a module and perform timing checks to ensure that events occurring at the module inputs satisfy the timing constraints of the device described by the module. The module paths are from module input ports to output ports and the timing checks are relative to the module inputs. The specify block refers to these ports as terminal descriptor. Module inout ports can function as either an input or output terminal. When one of the port instances is an interface, each signal in the interface becomes an available terminal, with the default... more
19.6 接口中的任务与函数 | Tasks and functions can be defined within an interface, or they can be defined within one or more of the modules connected. This allows a more abstract level of modeling. For example “read” and “write” can be defined as tasks, without reference to any wires, and the master module can merely call these tasks. In a modport these tasks are declared as import tasks. If a module is connected to a modport containing an exported task or function, and the module does not define that task or function, then an elaboration error shall occur. Similarly if the modport contains an... more
19.7 参数化接口 | Interface definitions can take advantage of parameters and parameter redefinition, in the same manner as module definitions. This example shows how to use parameters in interface definitions.
19.8 虚拟接口 | Virtual interfaces provide a mechanism for separating abstract models and test programs from the actual signals that make up the design. A virtual interface allows the same subprogram to operate on different portions of a design, and to dynamically control the set of signals associated with the subprogram. Instead of referring to the actual set of signals directly, users are able to manipulate a set of virtual signals. Changes to the underlying design do not require the code using virtual interfaces to be re-written. By abstracting the connectivity and functionality of a set of blocks, virtual interfaces promote code-reuse. A... more
19.9 对接口对象的访问 | Access to all objects declared in an interface is always available by hierarchical reference, regardless of whether or not the interface is connected through a port. When an interface is connected with a modport in either the module header or port connection, access by port reference is limited to only those objects listed in the modport, for only those types of objects legal to be listed in modports (nets, variables, tasks, and functions) All objects are still visible by hierarchical reference. For example:


主题

主题
第十二章 随机约束
主题
主题
描述
12.1 简介（一般信息）
约束驱动的测试生成方法使得用户能够自动地为功能验证产生测试。随机测试比一个传统的、直接的测试方法更有效率。通过指定约束，我们可以很容易地为难于到达的边界条件产生测试。SystemVerilog允许用户以一种紧凑、明了的方式指定约束。约束接下来会被一个求解器处理，这个求解器用来产生满足约束的随机值。

典型情况下，随机约束在一个面向对象的数据抽象之上指定。它将需要被随机化的数据建模成包含随机变量和用户定义约束的对象。约束确定了可以被赋值给随机变量的有效值。对象很适合于表示复杂的集合数据类型以及诸如以太网包之类的协议。

第12.2节提供了基于对象的随机化和约束编程的概述。本章余下的部分提供了有关随机变量、约束块、以及处理它们的机制的详细信息。
12.2 概述
本章介绍了在对象内产生随机激励的基本概念和用法。SystemVerilog使用一个面向对象的方法来为对象的成员变量赋随机值，它以用户定义的约束为准。例如：
12.3 随机变量
类变量可以使用rand和randc类型修饰符关键字声明成随机的。

在一个类中声明随机变量的语法如下：
12.4 约束块
随机变量的值通过由约束块声明的约束表达式来确定。像任务、函数和变量一样，随机块是类的成员。在一个类中，约束块的名字必须是唯一的。

声明约束块的语法如下：
12.5 随机化方法
12.6 内联约束 — randomize() with
通过使用randomize()...with结构，用户可以在randomize()方法的调用点上声明内联约束。这些额外的约束与对象约束一起应用。

randomize()...with的语法如下：
12.7 使用rand_mode()关闭随机变量
rand_mode()可以用来控制激活或关闭一个随机变量。当一个随机变量处于未激活状态的时候，这个随机变量就好像没有使用rand或randc声明一样。未激活的随机变量不会被rand_mode()方法随机化，并且它们的值会被求解器当作状态变量。所有的随机变量最初都是激活的。

rand_mode()方法的语法如下：
12.8 使用constraint_mode()控制约束
constraint_mode()方法可以用来控制激活或关闭一个约束。当约束处于未激活（关闭）状态时，它不会被randomize()方法所考虑。所有的约束最初都是激活的。

constraint_mode()方法的语法如下：
12.9 动态的约束修改
SystemVerilog中提供了几种方法来动态地修改随机化方法：
  • 蕴涵以及if...else风格的约束允许声明具有判决条件的约束。
  • 可以使用contraint_mode()内建方法来激活或关闭约束块。初始情况下，所有的约束块均处于激活状态。未激活的约束会被randomize()函数忽略。
  • 可以使用rand_mode()内建方法来激活或关闭随机变量。初始情况下，所有的rand和randc变量都处于激活状态。未激活的随机变量会被randomize()函数忽略。
  • 在dist约束中的权重可以被改变，从而影响了被选定集合中特定值出现的概率。
12.10 内联随机变量控制
randomize()方法可以用来临时性地控制一个类实例或对象中的随机变量和状态变量的集合。当调用无参数的randomize方法的时候，它的行为就像前一节所描述的那样，也就是说，它会为对象中所有使用rand或randc声明的随机变量赋新的值，这样所有的约束都会被满足。当调用带有参数的randomize的时候，它的参数指定了该对象内随机变量的完整集合；对象中的所有其它变量都被认为是状态变量。例如，考虑下面的类以及对randomize方法的调用：
12.11 范围变量的随机化 — std::randomize()
内建的类随机化方法对类成员变量执行专有的操作。使用类来对需要随机化的数据建模是一种强大的机制，它使得我们能够产生通用、可复用的包含随机变量的对象，并能够产生可以在以后扩展、继承、约束、过载、使能、关闭、以及从其它对象合并或分离的约束。类及与其关联的随机变量和约束在处理上的方便性使得类非常适合描述和处理随机数据和约束。然而，某些要求较少的问题并不需要类的这些完整的灵活性，它可以使用一个较为简单的机制来随机化不属于一个类的数据。范围随机函数（std::randomize()）使得用户能够随机化当前范围内的数据，而无需定义一个类或实例化一个类对象。

范围随机化函数的语法如下：
12.12 随机数系统函数与方法
12.13 随机稳定性
随机数发生器（RNG）对于线程和对象是本地的。因为被一个线程或对象返回的随机值序列独立于其它线程或对象的RNG，所以这个特性被称为随机稳定性。随机稳定性应用于：
  • 系统随机化调用，$urandom()和$urandom_range()。
  • 对象和进程随机播种方法，srandom()。
  • 对象随机化方法，randomize()。
在面对用户代码小的改变的时候，具有这种特点的测试平台能够展示更加稳定的RNG行为。另外，对于通过手工设置种子的线程和对象，它能够更精确地控制随机值的产生。
12.14 为随机化手工设置种子
每一个对象维护了它自己的内部随机数发生器，这个随机数发生器它的randomize()方法所专用。这就使得对象能够各自独立地被随机化并能够相对于其它的随机化函数独立地调用。当产生一个对象的时候，它的随机数发生器（RNG）能够使用来自产生这个对象的线程的RNG的下一个值设置种子。这个过程被称为层次化的对象播种。

有时我们希望能够使用srandom()方法手工地设置种子。这种功能或者在一个类方法中，或者在类定义的外部完成。

作为一个类方法在内部为RNG设置种子的例子如下：
12.15 随机加权的条件 — randcase
12.16 随机序列产生 — randsequence
分析程序生成器，例如yacc，使用巴科斯-诺尔范式（BNF）或类似的符号来描述被分析语言的文法。因此文法被用来产生一个程序，它能够检查一个标记流是否代表了该语言中一个语法正确的表达方式。SystemVerilog的序列产生器反转了这个过程。它使用文法来随机地产生一个文法所描述的语言的正确的表达方式（也就是一个标记流）。随机序列发生器对于随机地产生结构化的激励序列（例如指令或网络流量模式）非常有用。

序列发生器使用个randsequence块内的一组规则和生成式。randsequence块的语法如下：


主题

主题
第十五章 时钟控制块
主题
主题
描述
15.1 简介（一般信息）
在Verilog中，块与块之间的通信通过模块端口来指定。SystemVerilog加入了接口（interface）这一概念，接口是一个关键的结构，它能够封装块与块之间的通信，因此，用户能够方便地改变模块间通信的建模抽象层次。

一个接口指定了一个测试平台用来与被测设计进行通信的信号或线网。然而，一个接口并没有任何显式的时序规程、同步要求、或时钟控制范例。

SystemVerilog加入了时钟控制块，它能够识别时钟信号，并能够捕获被建模块的时序和同步要求。一个时钟控制块集合了同步于一个特定时钟的信号，并且使得它们的时序成为显式的。在一个基于周期的方法中，时钟控制块是一个关键的元素，它使得用户能够在一个更高的抽象层次上编写测试平台。除了关注于信号以及时间上的转变外，测试还可以根据周期和事务定义。根据环境的不同，一个测试平台可以包含一个或多个时钟控制块，每一个都可以包含它自己的时钟加上任意数目的信号。

时钟控制块将时序和同步细节与一个测试平台中的结构、功能和过程元素分割开来。因此，采样和驱动时钟控制块信号的时序成为隐式的并且相对于时钟控制块的时钟。这使得我们能够以一个非常简洁的方式编写一组关键的操作，而无需显式地使用时钟或指定时序。这些操作是：
  • 同步的事件
  • 输入采样
  • 同步的驱动
15.2 时钟控制块声明
时钟控制块的声明语法如下：
15.3 输入时滞与输出时滞
输入或双向信号在指定的时钟事件上采样。如果指定了一个输入时滞，那么信号在时钟事件之前的时滞时间单位上采样。类似地，输出或双向信号在相应的时钟事件之后的时滞仿真时间单位上被驱动。图15-1为一个上升沿时钟显示了基本的采样/驱动时序。

图15-1 — 包含相对于时钟上升沿的时滞的采样和驱动时间

一个时滞必须是一个常量表达式，并且可以被说明成一个参数。如果没有指定时滞的时间单位，那么会使用当前的时间单位。如果使用了一个数字的话，那么时滞会使用当前作用范围的时间比例来解释。

15.4 层次化的表达式
一个时钟控制块中的任何信号都可以与一个任意的层次化表达式相关联。正像15.2节所描述的那样，层次化的表达式通过在层次化表达式前面附加一个等号（=）来引入：
15.5 多时钟控制块中的信号
相同的信号（时钟、输入、输入输出、或输出）可以在一个时钟控制块中出现多次。使用相同时钟（或时钟表达式）的时钟控制块应该共享相同的同步事件，这种方式就像几个锁存器可以被一个相同的时钟控制一样。输入语义在15.12节中描述，输出语义在15.14节中描述。
15.6 时钟控制块的作用范围和生命周期
一个时钟控制块既是一个声明也是这个声明的一个实例。单独的实例化步骤不是必要的。相反，会为包含声明的块的每一个实例产生一个拷贝（就像一个always块一样）。一旦声明了一个时钟控制块，定时信号就可以通过时钟控制块的名字和一个点（.）操作符来引用：
15.7 多时钟控制块的例子
在这个例子中，一个简单的测试程序包含了两个时钟控制块。在本例中使用的程序结构将在第十六章中讨论。
15.8 接口与时钟控制块
一个时钟控制块封装了一组共享一个基本时钟的信号，因此使用一个SystemVerilog接口说明一个时钟控制块能够显著地减少连接测试平台所需代码的数目。此外，由于测试平台内时钟控制块中信号方向是有关测试平台而不是被测设计的，一个modport声明可以恰当地描述这两个方向。一个测试平台程序可以包含在一个程序当中，并且它的端口可以是接口，这个接口对应于每个时钟控制块中声明的信号。从测试平台这一侧（也就是modport test）看接口中的连线应该与时钟控制块中声明的方向相同，而从被测设计来看则具有相反的方向（也就是modport dut）。

例如，前面的例子可以使用接口按如下的方式重新编写：
15.9 时钟控制块事件
一个时钟控制块的时钟控制事件可以直接使用时钟控制块的名字来引用，而不用理会用来声明时钟控制块的真实时钟控制事件。

例如：
15.10 周期延时：##
##操作符可以被用来将执行延时一个指定数目的时钟控制事件，或者时钟周期。

周期延时语句的语法如下：
15.11 缺省时钟控制
一个时钟控制可以被说明成缺省的，这样它可以作用于一个指定模块、接口、或程序内的所有周期延时操作。

缺省周期说明语句的语法如下：
15.12 输入采样
所有的时钟控制块输入（input或inout）都在对应的时钟控制事件上采样。如果输入时滞不是一个显式的#0，那么采样的值对应于先于时钟控制事件的时间布值时滞时间单位的Postponed区域中的信号值（参见15.3节中的图15-1）。如果输入时滞是一个显式的#0，那么采样的值对应于Observed区域的采样值。

采样会立即发生（调用进程不会阻塞）。当一个信号出现在一个表达式中的时候，它会被信号的采样值替代，也就是在最后一个采样点上采样的值。

当同一个信号是多个始终控制块输入的时候，它的语义是很直接的；每一个时钟控制块使用自己的时钟控制事件采样对应的信号。
15.13 同步的事件
显式的同步通过事件控制操作符@来实现，它允许一个进程来等待一个特定的信号值变化或者一个时钟控制事件（参见15.9节）。

同步操作符的语法在第8.10节给出。

与事件控制一起使用的表达式可以指示时钟控制块的输入（input或inout）或者一个分片。分片可以包含动态索引，它会在@表达式执行的时候进行一次计算。

下面是一些同步语句的例子：
  • 等待时钟控制块ram_bus中ack_1信号的下一次变化
15.14 同步的驱动
时钟控制块的输出（output或inout）被用来在一个指定的时间上将值驱动到它们对应的信号。换句话说，对应的信号在指定的时钟控制事件上通过输出时滞来修改它的值。

说明一个同步驱动的语法类似于一个赋值：


主题

主题
第十八章 层次
主题
主题
描述
18.1 简介（一般信息）
Verilog的组织结构较为简单。除系统任务和系统函数外，所有的数据、函数和任务都位于模块当中（系统任务和系统函数是全局的，并且可以在PLI中定义）。Verilog模块可以包含其它模块的实例。任何未被实例化的模块都位于顶层。这个规则不适用于库，因此库具有不同的状态和不同的过程来进行分析。一个层次名可以在实例层次的任何地方指定任何命名的对象。模块层次通常很随意，需要耗费很多精力来维护端口列表。

在Verilog中，只有线网、reg、integer和时间数据类型才可以通过模块端口传递。

为了表示设计层次，SystemVerilog加入了许多增强：
  • 包含诸如数据、类型、类、任务和函数声明的包
  • 支持分离的编译
  • 仅在编译单元内可见的编译单元范围
  • 使用嵌套的模块声明来帮助表示自包含的模块和库
  • 在端口声明中可以使用较宽松的规则
  • 使用“.name”来简化命名端口的连接
  • 使用“.”的隐式端口连接
  • 与模块绑定的时间单位和时间精度说明
  • 使用接口的概念来封装模块间的连接（在第十九章中提供）
SystemVerilog的一个重要增强就是加入了通过模块端口传递任何数据类型的能力，包括线网、以及包括实数、数组和结构体在内的所有变量类型。
18.2 包
SystemVerilog包提供了额外的机制在多个SystemVerilog模块、接口和程序间共享参数、数据、类型、任务、函数、序列以及特性的声明。包是显式命名的作用域，它出现在源文本的最外层（与顶层模块和原语处于同一层次）。类型、变量、任务、函数以及特性都可以在一个包中声明。这些声明可以在模块、宏模块、接口、程序和其它包中通过导入或完整解析的名字来引用。
18.3 编译单元的支持
通过使用编译单元，SystemVerilog支持分离的编译。SystemVerilog提供了下列的术语和定义：
  • 编译单元：a collection of one or more SystemVerilog source files compiled together
  • 编译单元作用域：a scope that is local to the compilation unit. It contains all declarations that lie outside of any other scope
  • $unit：用来显式地访问编译单元作用域中的标识符的名字
The exact mechanism for defining which files constitute a compilation unit is tool specific. Tools shall provide a mechanism to specify the files that make up a compilation unit. Two extreme cases are:
  1. All files make a single compilation unit (in which case the declarations in the compilation-unit scope are accessible anywhere within the design)
  2. Each file is a separate compilation unit (in which case the... more
18.4 顶层实例
The name $root is added to unambiguously refer to a top level instance, or to an instance path starting from the root of the instantiation tree. $root is the root of the instantiation tree.

For example:
18.5 模块声明
18.6 嵌套的模块
A module can be declared within another module. The outer name space is visible to the inner module, so that any name declared there can be used, unless hidden by a local name, provided the module is declared and instantiated in the same scope.

One purpose of nesting modules is to show the logical partitioning of a module without using ports. Names that are global are in the outermost scope, and names that are only used locally can be limited to local modules.
18.7 外部模块
To support separate compilation, extern declarations of a module can be used to declare the ports on a module without defining the module itself. An extern module declaration consists of the keyword extern followed by the module name and the list of ports for the module. Both list of ports syntax (possibly with parameters), and original Verilog style port declarations can be used. Note that the potential existence of defparams precludes the checking of the port connection information prior to elaboration time even for list of ports style declarations.

The following example demonstrates the usage of extern module declarations.
18.8 端口声明
18.9 端口表达式列表
Verilog 1364-2001 created a list_of_port_declarations alternate style which minimized the duplication of data used to specify the ports of a module. SystemVerilog adds an explicitly named port declaration to that style, allowing elements of arrays and structures, concatenations of elements, or aggregate expressions of elements declared in a module, interface or program to be specified on the port list.

Like explicitly named ports in a module port declaration, port identifiers exist in their own namespace for each port list. When port item is just a simple port identifier, that identifier is used as both a reference to an interface item... more
18.10 时间单位与精度
SystemVerilog has a time unit and precision declaration which has the equivalent functionality of the ‘timescale compiler directives in Verilog-2001. Use of these declarations removes the file order dependencies problems with compiler directives. The time unit and precision can be declared by the timeunit and timeprecision keywords, respectively, and set to a time literal which must be a power of 10 units. For example:
18.11 模块实例
18.12 端口连接规则
通过允许所有变量数据类型都能够通过端口传递，SystemVerilog扩展了Verilog的端口连接能力。通过允许端口连接的两侧具有相同的兼容类型，并且通过允许对变量的连续赋值，SystemVerilog做到了这一点。SystemVerilog还产生了一个新的端口限定符类型，ref，它允许共享的变量通过传递一个层次化的引用来跨越一个端口。
18.13 命名空间
SystemVerilog has eight name spaces for identifiers, two are global (definitions name space and package name space), two are global to the compilation unit (compilation unit name space and text macro name space) and four are local. The eight name spaces are described as follows:
  1. The definitions name space unifies all the non-nested module, macromodule, primitive, program, and interface identifiers defined outside of all other declarations. Once a name is used to define a module, macromodule, primitive, program, or interface within one compilation unit the name shall not be used again (in any compilation unit) to declare another non-nested module,... more
18.14 层次化的名字
Hierarchical names are also called nested identifiers. They consist of instance names separated by periods, where an instance name can be an array element. The instance name $root refers to the top of the instantiated design and is used to unambiguously gain access to the top of the design.


主题

主题
第十六章 程序块
主题
主题
描述
16.1 简介（一般信息）
模块是基本的Verilog构造块。模块可以包含其它模块的实例、线网、任务和函数声明、以及always块和initial块中的过程语句。这种结构非常适合于硬件的描述。然而，对测试平台来讲，其重点不是硬件级的细节（例如线网、结构化层次、以及互连），而是建模设计验证的完整环境。为了获得被正确初始化和同步的环境、避免设计与测试平台间的竞争、自动化输入激励的产生、以及复用现存的模型和其它构架，我们需要耗费很大的努力。

程序块能够实现三个基本的目标：
  1. 它提供了测试平台执行的入口点。
  2. 它产生了一个封装程序级数据的范围。
  3. 它提供了一个语境来说明Reactive区域中的调度。
程序结构在设计和测试平台间建立了一个清晰的分割，并且更为重要的是，它为程序中声明的所有元素在Reactive区域中说明了特定的执行语义。与时钟控制块一起，程序为设计和测试平台间提供了无竞争的交互，并形成了周期和事务级的抽象。

SystemVerilog的抽象和建模结构简化了测试平台的产生和维护。实例化以及单独连接每一个程序实例的能力使得它们能够作为通用模块使用。
16.2 程序结构
一个典型的程序包含类型和数据声明、子例程、设计的连接、以及一个或多个过程化的代码流。设计和测试平台间的连接使用与SystemVerilog说明端口连接（包括接口）相同的互连机制。程序块的语法如下：
16.3 多个程序
SystemVerilog允许具有任意数目的程序定义或实例。程序可以是完全独立（没有程序间的通信）的，也可以是协同操作的。通过使用嵌套的块、包、或层次化引用来共享数据，或者在对应的程序块内部声明数据（使其成为私有的），通信的程度是可以控制的。
16.4 消除测试平台的竞争
在Verilog中具有两个主要的不确定性源。第一个是激活的事件以一个任意的顺序处理。第二个是行为块中没有时间控制结构的语句不会作为一个事件执行。然而，从测试平台的角度看，这些影响都是并不重要的细节问题。测试平台的主要任务是为被测设计产生有效的输入激励，并验证被测设计是否能够正确地操作。此外，对于使用周期抽象的测试平台而言，无论是检查当前的输出还是为下一个周期计算激励，它仅与系统的稳态相关。形式工具也已这种方式工作。

在敏感于设计信号（在模块内声明而不是程序块）变化（例如更新事件）的程序块中的语句在Reactive区域被调度。考虑一个包含@(clk)语句的程序块，其中clk是某个模块中的一个设计信号。clk信号的每一个跃变都会引起语句S1被调度到Reactive区域。同样，程序块中的initial块也在Reactive区域被调度；相反，模块中的initial块则在Active区域被调度。另外，从程序内驱动的设计信号必须使用无阻塞赋值进行赋值并且在NBA区域被更新。因此，即使无延时驱动的信号也会作为一个事件被传递到设计。使用这个行为，正确的周期语义可以无竞争地被建模；因此使得基于程序的测试平台能够与周期控制的断言和形式工具相兼容。

由于程序在Reactive区域调度事件，因此时钟控制块结构对于自动地采样前一个时间步值或时钟周期的稳态值非常有用。专门通过具有#0输入时滞的时钟控制模块读取设计值的程序对于读-写竞争是不敏感的。值得注意的是：简单地采样输入信号（或者在时钟控制块输入上设置非零时滞）不会消除潜在的竞争。正确的输入采样仅仅解决了单个的时钟控制块。对于多个时钟，交叠或同时的时钟以任意顺序处理仍然是一个潜在的竞争源。通过在所有的设计事件被处理了之后（包括被无阻塞赋值驱动的时钟），在Reactive区域调度其执行，程序结构解决了这方面的问题。
16.5 阻塞周期/事件模式下的任务
在设计模块内部调用程序任务或函数是非法的并且会导致一个错误。这是因为设计不必敏感于测试平台。SystemVerilog允许程序调用位于其它程序或位于设计模块内部的任务和函数。设计模块内部的函数可以从一个程序中被调用，并且不要求特殊的处理。然而，从一个程序中调用的位于设计模块内部的阻塞任务（一个没有在0仿真时间执行的任务）在从任务返回时却要求显式的同步。也就是说，当阻塞任务返回到程序代码的时候，程序块的执行被自动挂起直到Reacive区域。参数的拷贝发生在任务返回的时候。

在从程序内部调用设计模块中的阻塞任务时需要特别小心。在第一个时序控制上阻塞之前被任务计算的表达式应该使用它们已经被无阻塞赋值更新后的值。相反，如果在时间步值的起始处（在无阻塞赋值被处理之前）从一个模块中调用任务的话，那么那些相同的表达式应该使用它们被无阻塞赋值更新之前的值。
16.6 程序控制任务
除了通常的仿真控制任务（$stop和$finish）外，一个程序可以使用$exit控制任务。


主题

主题
第十四章 调度语义
主题
主题
描述
14.1 硬件模型的执行及其验证环境
本参考手册各个章节的目标是描述各个语言元素的行为。本章给出了这些元素间相互作用的概述，特别是有关事件调度和执行的内容。尽管SystemVerilog并不仅仅限制在仿真中使用，然而语言的语义是为事件导向的仿真而定义，并且硬件描述语言的其它使用都是从这个基本的定义抽象而出。
14.2 事件仿真
SystemVerilog语言根据一个分布式事件执行模型定义。本章详细描述了分布式事件仿真以便提供一个语境来描述SystemVerilog结构的含义和有效解释。这些最终的定义为仿真提供了标准的SystemVerilog参考算法，所有遵从这个标准的仿真器都应该实现这些算法。注意，这些定义具有许多选择，并且不同的仿真器之间的某些执行细节也有些差别。另外，除了本章描述的算法外，SystemVerilog仿真器可以自由地使用不同的算法，只要用户可见的效果与这些参考算法保持一致。

一个SystemVerilog描述包含了连接的执行线程或进程。进程是可以计算的对象，它们可以具有状态，并且可以响应输入上的变化以产生输出。进程是并发调度的元素，例如initial块。进程的例子包括但不限于原语、initial、always、always_comb、always_latch以及always_ff过程块、连续赋值、异步任务、以及过程赋值语句。

在被仿真的系统描述中，一个线网或变量的每一个变化都被认为是一个更新事件。

进程敏感于更新事件。当一个更新事件被执行的时候，敏感于这个事件的所有进程都会以任意顺序计算。一个进程的计算也是一个事件，这个事件被称为计算事件。

计算事件还包含PLI回调，这些PLI回调是执行模型中的一些点，其中用户定义的外部例程能够从仿真核中被调用。

除了事件之外，仿真器的另外一个关键方面是时间。术语仿真时间被用来指代由仿真器维护的时间值，它用来建模正在仿真的系统描述所花费的时间。在本章中，术语时间可以与仿真时间互换使用。

为了支持清晰并且可预测的交互作用，单个时隙被划分成多个区域，在这些区域中规定了特定执行类型排序的事件被调度。这就使得当被测设计处于一个稳定状态的时候特性和检查器能够采样数据。特性表达式可以被安全地计算，并且测试平台能够与特性和检查器以零延时相互作用，而这些都是以一个可预测的方式进行。这种机制还允许设计、时钟传输具有非零的延时，和/或激励和响应被自由地混合并与周期精确的描述相一致。
14.3 分层的事件调度器
一个符合规定的SystemVerilog仿真器必须维护某种形式的数据结构，随着仿真时间的继续，这个数据结构允许事件被动态地调度、执行和删除。这个数据结构通常被实现成一组时间排序的链表，它们一个定义明确的方式被划分和细分。

第一个分割根据时间进行。每一个事件都具有唯一的一个执行时间，在仿真期间的人以给定时间点上它可以是当前时间或某个未来的时间。在一个特定时间上的所有被调度的事件定义了一个时隙。通过在移动到下一个非空时隙之前执行和删除当前仿真时隙中的所有事件，仿真能够按时间顺序执行。这个过程保证了仿真器在时间上永远不会回退。

一个时隙被划分成一组有序的区域：
  1. Preponed
  2. Pre-active
  3. Active
  4. Inactive
  5. Pre-NBA
  6. NBA
  7. Post-NBA
  8. Observed
  9. Post-observed
  10. Reactive
  11. Postponed
将一个时隙划分成这些有序区域的目的是提供设计和测试平台代码间的可预测的交互作用。

除了Observed和Reactive区域以及Post-observed PLI区域外，这些区域本质上包含了Verilog 1364-2001标准仿真参考模型，并具有完全相同的确定层次。这就意味着合法的Verilog代码能够在新的机制下无需修改就可以正确地运行。Postponed区域是监视信号和其它类似事件的区域。一旦到达Postponded区域后，在这个时隙中不允许有新的值变化。

在SystemVerilog 3.1标准中，Observed和Reactive区域是新的区域，并且只有来自新的语言结构的事件才能被调度进这些新的区域。

当特性表达式被触发的时候，Observed区域用来计算这些特性表达式。这个确定性的一个标准就是特性计算在任意时钟触发时隙中只能发生一次。在特性计算期间，通过/失败代码应该在当前时隙的Reactive区域被调度。

特性表达式被采样数据的采样时间在时钟控制块中控制。新的#1step采样延时提供了在进入当前时隙之前立即采样数据的能力，并且相对于其它等价结构来说它是一个首选的结构，因为它使得1step的时间延时能够被参数化。这个#1step结构是一个卓有成效的机制，它提供了一个方法来定义采样发生的时间，并且不要求一个事件在前一个时隙中被产生。从概念上讲，这个#1step采样与在当前时隙的Preponed区域发生的数据采样相同。

在程序块、以及来自特性表达式通过/失败代码中说明的代码在Reactive区域被调度。

Pre-active、Pre-NBA和Post-NBA在SystemVerilog 3.1中是新的区域，但它们支持现存的PLI回调。Post-observed区域在SystemVerilog 3.1中是新的区域并且已经为支持PLI而加入。

Pre-active区域专用于一个PLI回调控制点，它使得用户代码能够在Active区域中的事件被计算（参见14.4节）之前读取和写入值以及产生事件。

Pre-NBA区域专用于一个PLI回调控制点，它使得用户代码能够在NBA区域中的事件被计算（参见14.4节）之前读取和写入值以及产生事件。

Post-NBA区域专用于一个PLI回调控制点，它使得用户代码能够在NBA区域中的事件被计算（参见14.4节）后读取和写入值以及产生事件。

Post-observed区域专用于一个PLI回调控制点，它使得用户代码能够在特性被计算（在Observed或较早的区域）后读取值。

事件区域的执行流程在图14-1中描述。

图14-1 — 时隙和事件区域的SystemVerilog流程

Active、Inactive、Pre-NBA、NBA、Post-NBA、Observed、Postobserved和Reactive区域被称为迭代区域。

Preponed区域专用于一个PLI回调控制点上，它使得用户代码在任何线网或变量改变状态之前访问当前时隙上的数据。

Active区域保留当前被计算的事件并且可以以任意顺序处理。

Inactive区域保留将要在所有激活事件被处理后被计算的事件。

一个显式的#0延时要求进程被挂起并且将一个事件调度到当前时隙的Inactive... more

14.4 PLI回调控制点
SystemVerilog中具有两种类型的PLI回调，一种类型的PLI回调当某种特定的行为发生时立即被执行，另外一种PLI回调被显式地注册成一个单次的计算事件。

我们有可能在任何区域显式地调度一个PLI回调事件。因此，一个显式的PLI回调注册能够被一个tuple (time, region)所识别。

下面的列表提供了来自不同的当前PLI回调的映射。

表格14-3：PLI回调


主题

主题
第十章 任务与函数
主题
主题
描述
10.1 简介（一般信息）
Verilog-2001具有静态和自动的任务和函数。在一个模块实例中，会为一个任务或函数的所有调用分配相同的存储空间。自动的任务和函数则为每一个实例分配唯一的、栈式存储空间。

SystemVerilog加入了在静态任务和函数中声明自动变量以及在自动任务和函数中声明静态变量的能力。

SystemVerilog还加入了：
  • 为声明任务和函数端口提供了更多的能力
  • 函数和输出和双向端口
  • void函数
  • 无需一个begin...end块或fork...jion块就可以在一个任务或函数中使用多条语句的能力
  • 在到达任务或函数的结尾之前从任务或函数返回的能力
  • 通过引用而不是值来传递参数的能力
  • 根据名字而不是位置来传递参数值得能力
  • 缺省的参数值
  • 通过直接编程接口（DPI）导入和导出函数的能力
10.2 任务
10.3 函数
10.4 任务与函数的参数传递
SystemVerilog提供了两种方式来为函数和任务传递参数：通过值传递和通过应用传递。参数还可以通过名字以及位置来传递。任务和函数的参数还可以指定缺省值，这就使得调用任务或函数的时候不传递参数。
10.5 导入与导出函数
函数导入和导出的语法如下：


主题

主题
第四章 数组
主题
主题 | 描述
4.1 简介（一般信息） | 数组是变量的集合，这些变量具有相同的数据类型，并可以使用相同的名字加上一个或多个索引来访问。 在C语言中，数组从0开始并以整数的形式进行索引，或者将其转换成指针。尽管整个数组可以作为一个整体被初始化，但在过程语句中，它的每一个元素必须被分离地读或写。 在Verilog-2001中，数组使用从左边界到右边界的顺序进行索引。如果它们是向量，它们还可以作为一个整体赋值，而如果他们是数组则不允许这样做。在Verilog-2001中允许多维数组。 在Verilog-2001中，所有的数据类型都可以声明成数组。reg、wire以及所有其它线网类型还可以具有向量宽度。在对象名字之前声明的尺寸被称作是“向量宽度”尺寸。在对象名字之后声明的尺寸被称为“数组”尺寸。
4.2 压缩与非压缩数组 | 压缩数组提供了一种将向量细分成子域的机制，这些子域可以作为数组元素方便地访问。这就可以保证压缩数组能够被表示成一个连续的位组（FPGA技术网提示：是指可以在内存中连续分配存储空间）。一个非压缩数组既可以这样表示也可以不这样表示（FPGA技术网提示：是指仿真器可以选择如何安排存储空间）。压缩数组与非压缩数组的不同之处在于：当一个压缩数组作为一个整体出现的时候，它被当作是单一的向量。 如果一个压缩数组被声明成有符号的，那么作为单一向量看待的数组也是有符号的。数组的单个元素是无符号的，除非它们的类型是被声明成有符号的命名类型。一个压缩数组的部分选择也是无符号的。 压缩数组可以是任意长度的整数类型（关于整数类型参见3.3节），因此，尺寸为48的压缩数组可以由48位组成，然后这个压缩数组就可以使用在48位算术表达式中。一个压缩数组可以实现的最大尺寸可以是有限制的，但最少应该可以实现65536（216）的长度。 压缩数组可以仅由单位整数数据类型（bit、logic、reg、wire以及其他线网类型）组成，也可以由其它能够递归成单位整数类型的压缩数组和压缩结构体组成。 具有预定义宽度的整数类型不能声明成压缩数组。这些类型是：byte、shorting、int、longint、以及integer。一个具有预定义宽度的整数类型可以被看作是一个一维的压缩数组。这些整数类型的压缩尺寸应该以趋向0的方向编号，并且最右边的索引是0。
4.3 多维数组 | 于Verilog的存储器类型类似，在类型之后声明的尺寸设置压缩尺寸，在实例之后的尺寸设置非压缩尺寸。
4.4 数组的索引与分片 | 一个表达式可以选取压缩数组的一部分，或者选取任何整数类型，并假定具有趋向0的编号方式。 SystemVerilog使用术语“部分选择（part selet）”来表示从一个单维压缩数组中选取一个或多个连续的位。这与Verilog中对术语“部分选择”的使用是一致的。
4.5 数组查询函数 | SystemVerilog提供了新的系统函数来返回有关数组的信息。包括：$left、$right,、$low,、$high,、$increment、$size、以及$dimensions。这些函数将在23.7节中描述。
4.6 动态数组 | 动态数组是一维的非压缩数组，它的尺寸可以在运行时设置或改变。动态数组的存储空间只有当数组在运行时被显式产生之后才会存在。 动态数组的声明语法如下：
4.7 数组赋值 | 对固定尺寸的非压缩数组赋值要求源数组和目的数组都具有相同非压缩维数，并且每一维的长度都必须相同。赋值通过将源数组的每一个元素赋值给目的数组的对应元素来实现，它要求源数组与目的数组具有兼容的类型。兼容类型是指在赋值操作上能够兼容的类型。在尺寸不等的固定尺寸非压缩数组间赋值会导致类型检查错误。
4.8 将数组作为自变量 | 数组可以作为自变量传递给任务或函数。数组自变量通过值进行传递的规则与数组赋值的规则相同（参见10.4节）。当数组自变量通过值传递的时候，一个数组的拷贝被传递给调用任务或函数。这条规则适用于所有的数组类型：固定尺寸数组、动态数组、或联合数组。 注意：未定义尺寸的维数只能出现在动态数组中，或者出现在导入DPI函数的形式变量中。如果一个形式变量的一维是未定义尺寸的，那么真实变量中对应维数具有任意尺寸也是可以接受的。 例如：
4.9 联合数组 | 对于处理成员数目会动态改变的连续变量集合而言，动态数组非常有用。然而，当集合的尺寸是未知的或者数据空间紧缺的时候，联合数组则是更好的选择。联合数组在使用之前不会分配任何存储空间，并且索引表达式不再被限制成integral表达式，而是可以具有任何数据类型。 联合数组实现了一个所声明类型的元素的查找表。用作索引的数据类型作为查找表的查找键值，并强制了一种顺序。 联合数组的声明语法如下：
4.10 联合数组方法 | 除了索引操作符之外，SystemVerilog提供了几个内建方法来允许用户分析和处理联合数组，同时提供了对联合数组的索引或键值的迭代处理。
4.11 联合数组赋值 | 联合数组只能被赋值为另外一个具有兼容类型并且具有相同索引类型的联合数组。其它的数组类型不能赋值给一个联合数组，而联合数组也不能赋值给其它类型的数组，无论是固定尺寸数组还是动态动态数组。 将联合数组赋值给另外一个联合数组会先将目的数组中所有现存条目清除，然后再将源数组中的每一个条目拷贝到目的数组。
4.12 联合数组自变量 | 作为自变量的联合数组只能传递给具有兼容类型并具有相同索引类型的联合数组。其它类型的数组，无论是固定尺寸数组还是动态数组，都不能传递给使用联合数组作为自变量的子程序。同样，联合数组也不能传递给使用其它类型的数组作为自变量的子程序。 通过值传递一个联合数组会产生联合数组的本地拷贝。
4.13 联合数组文本 | 联合数组文本值使用{index:value}这样的语法并带有可选的缺省索引。与所有其它数组一样，联合数组可以一次只写一个条目，或者使用数组文本替代整个数组内容。
4.14 队列 | 队列是一个相同元素的可变尺寸的有序集合。队列能够以常量时间访问它的所有元素，也能够以常量时间在队列的尾部和头部插入和删除元素。队列中的每一个元素都通过一个序号来标识，这个序号代表了元素在队列内的位置，0代表第一个元素，$代表最后一个元素。队列类似于一个一维的非压缩数组，它可以自动地增长和缩减。因此，与数组一样，队列可以使用索引、串联、分片、相等操作符进行处理。 队列使用与非压缩数组相同的语法声明，但可以使用$作为数组尺寸。队列的尺寸可以通过指定可选的右边界（最后一个索引）进行限制。
4.15 数组处理方法 | SystemVerilog提供了几个内建的方法来方便数组的搜索、排序和缩减。 调用这些数组方法的基本语法如下：


主题

主题
附录A 形式语法
主题
主题
描述
A.1 源文本
A.2 声明
A.3 Primitive instances
A.4 Module, interface and generated instantiation
A.5 UDP declaration and instantiation
A.6 Behavioral statements
A.7 Specify section
A.8 Expressions
A.9 General
A.10 Footnotes (normative)
  1. Embedded spaces are illegal.
  2. A simple_identifier, c_identifier, and arrayed_reference shall start with an alpha or underscore ( _ ) character, shall have at least one character, and shall not have any spaces.
  3. The $ character in a system_tf_identifier shall not be followed by white_space. A system_tf_identifier shall not be escaped.
  4. End of file.
  5. The unsigned number or fixed point number in time_literal shall not be followed by a white_space.
  6. implicit_class_handle shall only appear within the scope of a class_declaration or out-of-block method declaration.
  7. In any one declaration, only one of protected or local is allowed, only one of rand or... more


主题

主题
附录C 标准包
主题
主题 | 描述
C.1 semaphore | semaphore类在13.2节中描述，它的原型如下：
C.2 mailbox | mailbox类在13.3节中描述，它的原型如下：
C.3 randomize | 随机化函数在12.11节中描述，它的原形如下：
C.4 进程 | 进程类在9.9节中描述，它的原型如下：


主题

主题
附录D 链表
主题
主题 | 描述
D.1 List definitions | list—A list is a doubly linked list, where every element has a predecessor and successor. A list is a sequence that supports both forward and backward traversal, as well as amortized constant time insertion and removal of elements at the beginning, end, or middle. container—A container is a collection of data of the same type. Containers are objects that contain and manage other data. Containers provide an associated iterator that allows access to the contained data. iterator—Iterators are objects that represent positions of elements in a container. They play a role similar to that of an array subscript, and allow... more
D.2 List declaration | The List package supports lists of any arbitrary predefined type, such as integer, string, or class object. Any iterator that refers to the position of an element that is removed from a list becomes invalid, thus, unable to iterate over the list. To declare a specific list, users must first include the generic List class declaration from the standard include area and then declare the specialized list type: ‘include <List.vh> ... List#(type) dl; // dl is a List of 'type' elements
D.3 Linked list class prototypes | The following class prototypes describe the generic List and List_Iterator classes. Only the public interface is included here.
D.4 List_Iterator methods | The List_Iterator class provides methods to iterate over the elements of lists. These methods are described below.
D.5 List methods | The List class provides methods to query the size of the list, obtain iterators to the head or tail of the list,retrieve the data stored in the list, and methods to add, remove, and reorder the elements of the list.


主题

主题
附录E DPI C-layer
主题
主题
描述
E.1 概述
The SystemVerilog Direct Programming Interface (DPI) allows direct inter-language function calls between SystemVerilog and any foreign programming language with a C function call protocol and linking model:
  • Functions implemented in C and given import declarations in SystemVerilog can be called from System- Verilog; such functions are referred to as imported functions.
  • Functions implemented in SystemVerilog and specified in export declarations can be called from C; such functions are referred to as exported functions.
  • Tasks implemented in SystemVerilog and specified in export declarations can be called from C; such functions are referred to as exported tasks.
  • Functions implemented in C which... more
E.2 Naming conventions
All names introduced by this interface shall conform to the following conventions.
  • All names defined in this interface are prefixed with sv or SV_.
  • Function and type names start with sv, followed by initially capitalized words with no separators, e.g., svBitPackedArrRef.
  • Names of symbolic constants start with sv_, e.g., sv_x.
  • Names of macro definitions start with SV_, followed by all upper-case words separated by a underscore (_), e.g., SV_CANONICAL_SIZE.
E.3 Portability
Depending on the data types used for imported or exported tasks or functions, the C code can be binary-level or source-level compatible. Applications that do not use SystemVerilog packed types are always binary compatible. Applications that don’t mix SystemVerilog packed and unpacked types in the same data type can be written to guarantee binary compatibility. Open arrays with both packed and unpacked parts are also binary compatible.

The values of SystemVerilog packed types can be accessed via interface tasks or functions using the canonical representation of 2-state and 4-state packed arrays, or directly through pointers using the implementation representation. The... more
E.4 Include files
The C-layer of the Direct Programming Interface defines two include files corresponding to these two levels of compatibility: svdpi.h and svdpi_src.h.

Binary compatibility of an application depends on the data types of the values passed through the interface. If all corresponding type definitions can be written in C without the need to include the svdpi_src.h file, then an application is binary compatible. If the svdpi_src.h file is required, then the application is not binary compatible and needs to be recompiled for each simulator of choice.

Applications that pass solely C-compatible data types or standalone packed arrays (both 2-state and 4-state)... more
E.5 Semantic constraints
Formal and actual arguments of both imported tasks or functions and exported tasks or functions are bound by the principle “What You Specify Is What You Get.” This principle is binding both for the caller and for the callee, in C code and in SystemVerilog code. For the callee, it guarantees the actual arguments are as specified for the formal ones. For the caller, it means the function call arguments shall conform with the types of the formal arguments, which might require type-coercion on the caller side.

Another way to state this is that no compiler (either C or SystemVerilog)... more
E.6 Data types
This section defines the data types of the C-layer of the Direct Programming Interface.
E.7 Argument passing modes
This section defines the ways to pass arguments in the C-layer of the Direct Programming Interface.
E.8 Context tasks and functions
Some DPI imported tasks and functions require that the context of their call is known. For example, those calls can be associated with instances of C models that have a one-to-one correspondence with instances of SystemVerilog modules that are making the calls. Alternatively, a DPI imported task or function might need to access or modify simulator data structures using PLI or VPI calls, or by making a call back into SystemVerilog via an export task or function. Context knowledge is required for such calls to function properly. It can take special instrumentation of their call to provide such context.

To... more
E.9 Include files
The C-layer of the Direct Programming Interface defines two include files. The main include file, svdpi.h, is implementation-independent and defines the canonical representation, all basic types, and all interface functions. The second include file, svdpi_src.h, defines only the actual representation of packed arrays and, hence, is implementation-dependent. Both files are shown in Annex B.

Applications which do not need to include svdpi_src.h are binary-level compatible.
E.10 Arrays
Normalized ranges are used for accessing SystemVerilog arrays, with the exception of formal arguments specified as open arrays.
E.11 Open arrays
Formal arguments specified as open arrays allows passing actual arguments of different sizes (i.e., different range and/or different number of elements), which facilitates writing more general C code that can handle SystemVerilog arrays of different sizes. The elements of an open array can be accessed in C by using the same range of indices and the same indexing as in SystemVerilog. Plus, inquiries about the dimensions and the original boundaries of SystemVerilog actual arguments are supported for open arrays.

NOTE—Both packed and unpacked array dimensions can be unsized.

All formal arguments declared in SystemVerilog as open arrays are passed by... more


主题

主题
附录F 包含文件
主题
主题 | 描述
F.1 Binary-level compatibility include file svdpi.h |
F.2 源级兼容性包含文件svdpi_src.h |


主题

主题
附录G 包含外部语言代码
主题
主题
描述
G.1 Location independence
All pathnames specified within this annex are intended to be location-independent, which is accomplished by using the switch -sv_root. It can receive a single directory pathname as the value, which is then prepended to any relative pathname that has been specified. In absence of this switch, or when processing relative filenames before any -sv_root specification, the current working directory of the user shall be used as the default value.
G.2 Object code inclusion
Compiled object code is required for cases where the compilation and linking of source code is fully handled by the user; thus, the created object code only need be loaded to integrate the Foreign Language Code into a SystemVerilog application. All SystemVerilog applications shall support the integration of Foreign Language Code in object code form. Figure 7-1depicts the inclusion of object code and its relations to the various steps involved in this integration process.

Figure 7-1 — Inclusion of object code into a SystemVerilog application

Compiled object code can be specified by one of the following two methods:

  1. by an... more


主题

主题
附录H 并发断言的形式语义
主题
主题 | 描述
H.1 简介 | This appendix presents a formal semantics for SystemVerilog concurrent assertions. Immediate assertions and coverage statements are not discussed here. Throughout this appendix, “assertion” is used to mean “concurrent assertion”. The semantics is defined by a relation that determines when a finite or infinite word (i.e., trace) satisfies an assertion. Intuitively, such a word represents a sequence of valuations of SystemVerilog variables sampled at the finest relevant granularity of time (e.g., at the granularity of simulator cycles). The process by which such words are produced is closely related to the SystemVerilog scheduling semantics and is not defined here. In this appendix,... more
H.2 抽象语法 |
H.3 语义 | Let P be the set of atomic propositions. The semantics of assertions and properties is defined via a relation of satisfaction by empty, finite, and infinite words over the alphabet Σ = 2P U {T, ⊥}. Such a word is an empty, finite, or infinite sequence of elements of Σ. The number of elements in the sequence is called the length of the word, and the length of word w is denoted |w|. Note that |w| is either a non-negative integer or infinity. The sequence elements of a word are called its letters and are assumed to be indexed consecutively... more
H.4 Extended Expressions | This section describes the semantics of several constructs that are used like expressions, but whose meaning at a point in a word can depend both on the letter at that point and on previous letters in the word. By abuse of notation, the meanings of these extended expressions are defined for letters denoted “w j” even” though they depend also on letters w i for i < j. The reason for this abuse is to make clear the way these definitions should be used in combination with those in preceding sections.
H.5 Recursive Properties | This section defines the neutral semantics of instances of recursive properties in terms of the neutral semantics of instances of non-recursive properties. The latter can be expanded to properties in the abstract syntax by appropriate substitutions, and so their semantics is assumed to be understood. According to Restriction 1 in Section 17.11.3, it is understood below that the negation operator not cannot be applied to any property expression that instantiates a recursive property. Restriction 2 in Section 17.11.3 is not represented here because disable iff is treated as a general property-building operator in this appendix. A precise version of Restriction... more


主题

主题
附录J 术语表
主题
主题 | 描述
集合 | 一个集合表达式、变量或类型代表了一组单一值。集合类型是任意非压缩结构体、非压缩联合体、或非压缩数组数据类型。集合可以作为一个整体拷贝或比较，但典型情况下不能作为一个整体使用在表达式中。
断言 | 断言是一条某个特性必须为“真”的语句。例如，一个read_request信号必须总是在两个时钟内跟着一个read_grant信号。断言能够自动检查一个指定的特性是否为“真”，并且，如果特性不为“真”，它能够自动产生一条错误信息。SystemVerilog提供了特殊的断言结构。断言结构在第17章中讨论。
Bit-stream | A bit-stream type or variables is any type that can be represented as a serial stream of bits. To qualify as a bit-stream type, each and every bit of the type must be individually addressable. This means that a bit-stream type can be any type that does not include a handle, chandle, real, shortreal, or event.
Canonical representation | A data representation format established by convention into which and from which translations can be made with specialized representations.
Constant | There are two types of constants in SystemVerilog. Parameters and local parameters are elaboration constants. Their values are calculated before elaboration is complete. Elaboration constants can be used to set the range of array types. The other form of constant is a run-time constant. These are variables that can only be set in an initialization expression using the const qualifier.
Context imported task | A DPI imported task declared with the 'context' property that is capable of calling exported tasks or functions and capable of accessing System Verilog objects via VPI or PLI calls.
Disable protocol | A set of conventions for setting, checking and handling disable status.
DPI | Direct Programming Interface. This is an interface between SystemVerilog and foreign programming languages permitting direct function calls from SystemVerilog to foreign code and from foreign code to SystemVerilog. It has been designed to have low inherent overhead and permit direct exchange of data between SystemVerilog and foreign code.
Dynamic | A dynamic type or variable is one that can be resized or re-allocated at runtime. Dynamic types include those that contain dynamic arrays, associative arrays, queues, or class handles.
Elaboration | Elaboration is the process of binding together the components that make up a design. These components can include module instances, primitive instances, interfaces, and the top-level of the design hierarchy.
枚举类型 | 枚举数据类型提供了一种能力来声明可以由一组命名值表示的变量。我们可以指定这些值等价的数值。枚举类型可以使用枚举名字而不是枚举值方便地引用或显示。3.10节讨论了枚举类型。
Exported task | A System Verilog task that is declared in an export declaration and can be enabled from an imported task.
Imported task | A DPI foreign code subprogram that can call exported tasks and can directly or indirectly consume simulation time.
Interface | An interface encapsulates the communication between blocks of a design, allowing a smooth migration from abstract system-level design through successive refinement down to lower-level register-transfer and structural views of the design. By encapsulating the communication between blocks, the interface construct also facilitates design re-use. The inclusion of interface capabilities is one of the major advantages of SystemVerilog. Interfaces are covered in Section 19.
Integral | An integral expression, variable or type is used to represent integral, or integer value They may also be called vectored values. .Integrals may be signed or unsigned, sliced into smaller integral values, or concatenated into larger values.
LRM | LRM是Language Reference Manual的缩写。“SystemVerilog LRM”指的是本文档。“Verilog LRM”指的是IEEE手册“1364-2001 IEEE Standard for Verilog Hardware Description Language 2001”。参见附录K中有关这个手册的信息。
Open array | A DPI array formal argument for which the packed or unpacked dimension size (or both) is not specified and for which interface routines describe the size of corresponding actual arguments at runtime.
Packed array | Packed array refers to an array where the dimensions are declared before an object name. Packed arrays can have any number of dimensions. A one-dimensional packed array is the same as a vector width declaration in Verilog. Packed arrays provide a mechanism for subdividing a vector into subfields, which can be conveniently accessed as array elements. A packed array differs from an unpacked array, in that the whole array is treated as a single vector for arithmetic operations. Packed arrays are discussed in detail in Section 4.
进程 | 进程是一个或多个编程语句的线程，这些编程语句可以独立于其它编程语句执行。Verilog中的每一个initial过程、always过程以及连续赋值语句都是一个独立的进程。这些都是静态的进程。也就是说，每次进程启动运行后，都会有一个进程的结束。SystemVerilog加入了特殊的always过程，它们既可以是静态进程也可以是动态进程。当启动动态进程的时候，它们可以无中止地运行。有关进程的内容在第九章提供。
信号 | 信号是一个非正式的术语，通常指的是一个变量或线网。它所处的上下文可能会在允许的类型上作进一步的限制。
单一类型（Singular） | 一个单一（singular）表达式、变量或类型代表一个单一的值、符号或句柄。一个单一类型可以是除非压缩结构体、非压缩联合体、或非压缩数组数据类型外的任何类型。
SystemVerilog | SystemVerilog指的是Accellera为在抽象建模和验证方面扩展IEEE 1364-2001 Verilog标准的能力所建立的标准。SystemVerilog标准的许多特性均在本文档中提供。
非压缩数组（Unpacked array） | 非压缩数组是一种类型的数组，它的数组维数在对象名之后声明。非压缩数组与Verilog中的数组相同，并且可以拥有任意数目的维数。非压缩数组与压缩数组的不同之处在于：非压缩数组作为一个整体不能使用在算术运算中。它的每一个元素必须单独处理。非压缩数组在第四章中讨论。
Verilog | Verilog指的是IEEE 1364-2001 Verilog硬件描述语言（HDL），一般称为Verilog-2001。这个语言在IEEE手册“1364-2001 IEEE Standard for Verilog Hardware Description Language 2001”中描述。参见附录K中有关这个手册的相关信息。
VPI | Verilog Procedural Interface的缩写，意为“Verilog程序接口”。它是第三代Verilog编程语言接口（PLI），提供了以面向对象的方式访问Verilog行为对象、结构对象、断言和覆盖对象的能力。


目录

目录
第一章 SystemVerilog导论
第二章 文本值
2.1 简介（一般信息）
2.2 文本值语法
2.3 整数和逻辑文本
2.4 实数文本
2.5 时间文本
2.6 字符串文本
2.7 数组文本
2.8 结构体文本
第三章 数据类型
3.1 简介（一般信息）
3.2 数据类型语法
3.3 整数数据类型
3.3.1 integral类型
3.3.2 两态（两值）与四态（四值）数据类型
3.3.3 有符号与无符号数据类型
3.4 real与shortreal数据类型
3.5 void数据类型
3.6 chandle数据类型
3.7 string数据类型
3.7.1 len()
3.7.2 putc()
3.7.3 getc()
3.7.4 toupper()
3.7.5 tolower()
3.7.6 compare()
3.7.7 icompare()
3.7.8 substr(int i, int j)
3.7.9 atoi(), atohex(), atooct(), atobin()
3.7.10 atoreal()
3.7.11 itoa()
3.7.12 hextoa()
3.7.13 octtoa()
3.7.14 bintoa()
3.7.15 realtoa()
3.8 event数据类型
3.9 用户定义的类型
3.10 枚举
3.10.1 将新的数据类型定义成枚举类型
3.10.2 枚举类型的排列
3.10.3 类型检查
3.10.4 数值表达式中的枚举类型
3.10.4.1 first()
3.10.4.2 last()
3.10.4.3 next()
3.10.4.4 prev()
3.10.4.5 num()
3.10.4.6 name()
3.10.4.7 使用枚举类型的方法
3.11 结构体与联合体
3.12 类
3.13 单一类型与集合类型
3.14 强制类型转换
3.15 $cast动态强制类型转换
3.16 位流强制类型转换
第四章 数组
4.1 简介（一般信息）
4.2 压缩与非压缩数组
4.3 多维数组
4.4 数组的索引与分片
4.5 数组查询函数
4.6 动态数组
4.6.1 new[]
4.6.2 size()
4.6.3 delete()
4.7 数组赋值
4.8 将数组作为自变量
4.9 联合数组
4.9.1 通配符索引类型
4.9.2 字符串索引
4.9.3 类索引
4.9.4 integer（或int）索引
4.9.5 有符号的压缩数组
4.9.6 无符号压缩数组或压缩结构体
4.9.7 其它用户定义类型
4.10 联合数组方法
4.10.1 num()
4.10.2 delete()
4.10.3 exists()
4.10.4 first()
4.10.5 last()
4.10.6 next()
4.10.7 prev()
4.11 联合数组赋值
4.12 联合数组自变量
4.13 联合数组文本
4.14 队列
4.14.1 队列操作符
4.14.2 队列方法
4.14.2.1 size()
4.14.2.2 insert()
4.14.2.3 delete()
4.14.2.4 pop_front()
4.14.2.5 pop_back()
4.14.2.6 push_front()
4.14.2.7 push_back()
4.15 数组处理方法
4.15.1 数组定位符方法
4.15.2 数组排序方法
4.15.3 数组缩减方法
4.15.4 迭代器索引查询
第五章 数据声明
5.1 简介（一般信息）
5.2 数据声明语法
5.3 常量
5.4 变量
5.5 作用范围与生命周期
5.6 线网、reg、与logic
5.7 信号别名
5.8 类型兼容性
5.8.1 等价类型
5.8.2 赋值兼容
5.8.3 强制转换兼容
5.8.4 类型非兼容性
第六章 属性
6.1 简介（一般信息）
6.2 缺省属性类型
第七章 操作符与表达式
7.1 简介（一般信息）
7.2 操作符语法
7.3 赋值操作符
7.4 对logic和bit类型的操作
7.5 通配等式与通配不等式
7.6 实操作符
7.7 尺寸
7.8 符号
7.9 操作符优先级与关联性
7.10 内建方法
7.10.1 内建包
7.11 静态前缀
7.12 串联
7.13 非压缩数组表达式
7.14 结构体表达式
7.15 标签联合体表达式与成员访问
7.16 集合表达式
7.17 操作符过载
7.18 流操作符（压缩/非压缩）
7.18.1 将动态尺寸的数据位流化
7.19 条件操作符
7.20 集合成员资格
第八章 过程语句和控制流
8.1 简介（一般信息）
8.2 语句
8.3 阻塞赋值与无阻塞赋值
8.4 选择语句
8.4.1 模式匹配
8.4.1.1 case语句中的模式匹配
8.4.1.2 if语句中的模式匹配
8.4.1.3 条件表达式中的模式匹配
8.5 循环语句
8.5.1 do...while循环
8.5.2 循环的增强
8.5.3 foreach循环
8.6 跳转语句
8.7 final块
8.8 命名块与语句标签
8.9 disable
8.10 事件控制
8.10.1 序列事件
8.11 电平敏感的序列控制
8.12 过程赋值与解赋值的移除
第九章 进程
9.1 简介（一般信息）
9.2 组合逻辑
9.2.1 隐含的always_comb敏感性
9.3 锁存逻辑
9.4 时序逻辑
9.5 连续赋值
9.6 fork...join
9.7 进程执行线程
9.8 进程控制
9.8.1 wait fork
9.8.2 disable fork
9.9 精细的进程控制
第十章 任务与函数
10.1 简介（一般信息）
10.2 任务
10.3 函数
10.3.1 返回值与void函数
10.3.2 丢弃函数返回值
10.4 任务与函数的参数传递
10.4.1 通过值传递
10.4.2 通过引用传递
10.4.3 缺省参数值
10.4.4 通过名字传递参数
10.4.5 可选的参数列表
10.5 导入与导出函数
第十一章 类
11.1 简介
11.2 语法
11.3 概述
11.4 对象（类实例）
11.5 对象属性
11.6 对象方法
11.7 构造器
11.8 静态类属性
11.9 静态方法
11.10 this
11.11 赋值、重命名与拷贝
11.12 继承与子类
11.13 过载成员
11.14 super
11.15 强制类型转换
11.16 串接构造器
11.17 数据隐藏与封装
11.18 常量类属性
11.19 抽象类与虚拟方法
11.20 多态性：动态方法查找
11.21 类范围解析操作符 ::
11.22 块外声明
11.23 参数化的类
11.24 typedef类
11.25 类与结构体
11.26 内存管理
第十二章 随机约束
12.1 简介（一般信息）
12.2 概述
12.3 随机变量
12.3.1 rand修饰符
12.3.2 randc修饰符
12.4 约束块
12.4.1 外部约束块
12.4.2 继承
12.4.3 集合成员资格
12.4.4 分布
12.4.5 蕴含
12.4.6 if...else约束
12.4.7 迭代约束
12.4.8 全局约束
12.4.9 变量排序
12.4.10 静态约束块
12.4.11 约束中的函数
12.4.12 约束守卫者
12.5 随机化方法
12.5.1 randomize()
12.5.2 pre_randomize()与post_randomize()
12.5.3 随机化方法注意事项
12.6 内联约束 — randomize() with
12.7 使用rand_mode()关闭随机变量
12.8 使用constraint_mode()控制约束
12.9 动态的约束修改
12.10 内联随机变量控制
12.10.1 内联约束检查器
12.11 范围变量的随机化 — std::randomize()
12.11.1 为范围变量添加约束 — std::randomize() with
12.12 随机数系统函数与方法
12.12.1 $urandom
12.12.2 $urandom_range()
12.12.3 srandom()
12.12.4 get_randstate()
12.12.5 set_randstate()
12.13 随机稳定性
12.13.1 随机稳定性的特性
12.13.2 线程稳定性
12.13.3 对象稳定性
12.14 为随机化手工设置种子
12.15 随机加权的条件 — randcase
12.16 随机序列产生 — randsequence
12.16.1 随机生成式权重
12.16.2 If...else生成式语句
12.16.3 case生成式语句
12.16.4 repeat生成式语句
12.16.5 交叉生成式 — rand join
12.16.6 中止生成式 — break和return
12.16.7 生成式间的值传递
第十三章 进程间的同步与通信
13.1 简介（一般信息）
13.2 semaphore
13.2.1 new()
13.2.2 put()
13.2.3 get()
13.2.4 try_get()
13.3 mailbox
13.3.1 new()
13.3.2 num()
13.3.3 put()
13.3.4 try_put()
13.3.5 get()
13.3.6 try_get()
13.3.7 peek()
13.3.8 try_peek()
13.4 参数化的mailbox
13.5 事件
13.5.1 触发一个事件
13.5.2 无阻塞的事件触发
13.5.3 等待一个事件
13.5.4 稳固的触发：触发特性
13.6 事件排序：wait_order()
13.7 事件变量
13.7.1 合并事件
13.7.2 回收事件
13.7.3 事件比较
第十四章 调度语义
14.1 硬件模型的执行及其验证环境
14.2 事件仿真
14.3 分层的事件调度器
14.3.1 SystemVerilog仿真参考算法
14.4 PLI回调控制点
第十五章 时钟控制块
15.1 简介（一般信息）
15.2 时钟控制块声明
15.3 输入时滞与输出时滞
15.4 层次化的表达式
15.5 多时钟控制块中的信号
15.6 时钟控制块的作用范围和生命周期
15.7 多时钟控制块的例子
15.8 接口与时钟控制块
15.9 时钟控制块事件
15.10 周期延时：##
15.11 缺省时钟控制
15.12 输入采样
15.13 同步的事件
15.14 同步的驱动
15.14.1 驱动和无阻塞赋值
15.14.2 驱动值解析
第十六章 程序块
16.1 简介（一般信息）
16.2 程序结构
16.3 多个程序
16.4 消除测试平台的竞争
16.4.1 零时滞时钟控制块竞争
16.5 阻塞周期/事件模式下的任务
16.6 程序控制任务
16.6.1 $exit()
第十七章 断言
17.1 简介（一般信息）
17.2 即时断言
17.3 并发断言概述
17.4 布尔表达式
17.4.1 操作数类型
17.4.2 变量
17.4.3 操作符
17.5 序列
17.6 声明序列
17.7 序列操作
17.7.1 操作符优先级
17.7.2 序列中的复制
17.7.3 采样值函数
17.7.4 与操作
17.7.5 交集（具有长度限制的与操作）
17.7.6 或操作
17.7.7 first_match操作
17.7.8 序列上的条件
17.7.9 包含在另外一个序列中的序列
17.7.10 一个序列结束点的检测和使用
17.8 处理一个序列中的数据
17.9 在一个序列匹配时调用子程序
17.10 系统函数
17.11 声明特性
17.11.1 蕴含
17.11.2 特性的例子
17.11.3 递归特性
17.11.4 有限长度与无限长度行为
17.11.5 Non-degeneracy
17.12 多时钟的支持
17.12.1 多时钟控制序列
17.12.2 多时钟控制特性
17.12.3 时钟流
17.12.4 例子
17.12.5 在多时钟语境中检测和使用一个序列的结束点
17.13 并发断言
17.13.1 断言语句
17.13.2 假设语句
17.13.3 覆盖语句
17.13.4 在过程化代码外部使用并发断言语句
17.13.5 在过程化代码中嵌入并发断言
17.14 时钟解析
17.14.1 在多时钟控制特性中的时钟解析
17.15 将特性绑定到作用域或实例
17.16 expect语句
第十八章 层次
18.1 简介（一般信息）
18.2 包
18.2.1 引用包中的数据
18.2.2 搜索顺序规则
18.3 编译单元的支持
18.4 顶层实例
18.5 模块声明
18.6 嵌套的模块
18.7 外部模块
18.8 端口声明
18.9 端口表达式列表
18.10 时间单位与精度
18.11 模块实例
18.11.1 Instantiation using positional port connections
18.11.2 Instantiation using named port connections
18.11.3 Instantiation using implicit .name port connections
18.11.4 Instantiation using implicit .* port connections
18.12 端口连接规则
18.12.1 变量的端口连接规则
18.12.2 线网的端口连接规则
18.12.3 接口的端口连接规则
18.12.4 兼容的端口类型
18.12.5 非压缩数组端口与实例数组
18.13 命名空间
18.14 层次化的名字
第十九章 接口
19.1 简介（一般信息）
19.2 接口语法
19.2.1 Example without using interfaces
19.2.2 Interface example using a named bundle
19.2.3 Interface example using a generic bundle
19.3 接口中的端口
19.4 modport
19.4.1 An example of a named port bundle
19.4.2 An example of connecting a port bundle
19.4.3 An example of connecting a port bundle to a generic interface
19.4.4 Modport expressions
19.4.5 Clocking blocks and modports
19.5 接口与specify块
19.6 接口中的任务与函数
19.6.1 An example of using tasks in an interface
19.6.2 An example of using tasks in modports
19.6.3 An example of exporting tasks and functions
19.6.4 An example of multiple task exports
19.7 参数化接口
19.8 虚拟接口
19.8.1 Virtual interfaces and clocking blocks
19.8.2 Virtual interfaces modports and clocking blocks
19.9 对接口对象的访问
第二十章 覆盖
20.1 简介（一般信息）
20.2 定义覆盖模型：covergroup
20.3 在类中使用covergroup
20.4 定义覆盖点
20.4.1 Specifying bins for transitions
20.4.2 Automatic bin creation for coverage points
20.4.3 Wildcard specification of coverage point bins
20.4.4 Excluding coverage point values or transitions
20.4.5 Specifying Illegal coverage point values or transitions
20.5 Defining cross coverage
20.5.1 Example of user-defined cross coverage and select expressions
20.5.2 Excluding cross products
20.5.3 Specifying Illegal cross products
20.6 Specifying coverage options
20.6.1 Covergroup Type Options
20.7 Predefined coverage methods
20.8 Predefined coverage system tasks and functions
20.9 Organization of option and type_option members
第二十一章 参数
21.1 简介（一般信息）
21.1.1 defparam语句的删除
21.2 参数声明语法
第二十二章 配置库
22.1 简介（一般信息）
22.2 库
第二十三章 系统任务与系统函数
23.1 简介（一般信息）
23.2 确立时的typeof函数
23.3 typename函数
23.4 表达式尺寸系统函数
23.5 范围系统函数
23.6 Shortreal转换
23.7 数组查询系统函数
23.8 断言严重性系统任务
23.9 断言控制系统任务
23.10 断言系统函数
23.11 随机数系统函数
23.12 程序控制
23.13 覆盖系统函数
23.14 对Verilog-2001系统任务的增强
23.15 $readmemb与$readmemh
23.15.1 读取压缩的数据
23.15.2 读取两态类型
23.16 $writememb and $writememh
23.16.1 Writing packed data
23.16.2 Writing 2-state types
23.16.3 Writing addresses to output file
23.17 File format considerations for multi-dimensional unpacked arrays
23.18 System task arguments for multi-dimensional unpacked arrays
第二十四章 VCD数据
第二十五章 编译器指令
25.1 简介（一般信息）
25.2 `define宏
25.3 `include
第二十六章 考虑从SystemVerilog中删除的功能
26.1 简介（一般信息）
26.2 defparam语句
26.3 过程赋值与解赋值语句
第二十七章 直接编程接口（DPI）
27.1 概述
27.1.1 Tasks and functions
27.1.2 Data types
27.1.2.1 Data representation
27.2 Two layers of the DPI
27.2.1 DPI SystemVerilog layer
27.2.2 DPI foreign language layer
27.3 Global name space of imported and exported functions
27.4 导入的任务和函数
27.4.1 Required properties of imported tasks and functions — semantic constraints
27.4.1.1 Instant completion of imported functions
27.4.1.2 input, output and inout arguments
27.4.1.3 Special properties pure and context
27.4.1.4 Memory management
27.4.1.5 Reentrancy of imported tasks
27.4.1.6 C++ exceptions
27.4.2 Pure functions
27.4.3 Context tasks and functions
27.4.4 Import declarations
27.4.5 Function result
27.4.6 形式参数的类型
27.4.6.1 开放数组
27.5 Calling imported functions
27.5.1 Argument passing
27.5.1.1 “What You Specify Is What You Get” principle
27.5.2 Value changes for output and inout arguments
27.6 Exported functions
27.7 Exported tasks
27.8 Disabling DPI tasks and functions
第二十八章 SystemVerilog断言API
28.1 需求
28.1.1 命名约定
28.2 Extensions to VPI enumerations
28.2.1 Object types
28.2.2 Object properties
28.2.3 Callbacks
28.2.4 Control constants
28.3 Static information
28.3.1 Obtaining assertion handles
28.3.2 Obtaining static assertion information
28.3.2.1 Using vpi_get_assertion_info
28.3.2.2 Extending vpi_get() and vpi_get_str()
28.4 Dynamic information
28.4.1 Placing assertion system callbacks
28.4.2 Placing assertions callbacks
28.5 Control functions
28.5.1 Assertion system control
28.5.2 Assertion control
第二十九章 SystemVerilog覆盖API
29.1 需求
29.1.1 SystemVerilog API
29.1.2 Naming conventions
29.1.3 Nomenclature
29.2 SystemVerilog real-time coverage access
29.2.1 Predefined coverage constants in SystemVerilog
29.2.2 Built-in coverage access system functions
29.2.2.1 $coverage_control
29.2.2.2 $coverage_get_max
29.2.2.3 $coverage_get
29.2.2.4 $coverage_merge
29.2.2.5 $coverage_save
29.3 FSM recognition
29.3.1 Specifying the signal that holds the current state
29.3.2 Specifying the part-select that holds the current state
29.3.3 Specifying the concatenation that holds the current state
29.3.4 Specifying the signal that holds the next state
29.3.5 Specifying the current and next state signals in the same declaration
29.3.6 Specifying the possible states of the FSM
29.3.7 Pragmas in one-line comments
29.3.8 Example
29.4 VPI coverage extensions
29.4.1 VPI entity/relation diagrams related to coverage
29.4.2 Extensions to VPI enumerations
29.4.3 Obtaining coverage information
29.4.4 Controlling coverage
第三十章 SystemVerilog数据读API
30.1 简介（一般信息）
30.2 需求
30.3 Extensions to VPI enumerations
30.3.1 Object types
30.3.2 Object properties
30.3.2.1 Static info
30.3.2.2 Dynamic info
30.3.2.2.1 Control constants
30.3.3 System callbacks
30.4 VPI object type additions
30.4.1 Traverse object
30.4.2 VPI collection
30.4.2.1 Operations on collections
30.5 Object model diagrams
30.6 Usage extensions to VPI routines
30.7 VPI routines added in SystemVerilog
30.8 Reading data
30.8.1 VPI read initialization and load access initialization
30.8.2 Object selection for traverse access
30.8.3 Optionally loading objects
30.8.3.1 Iterating the design for the loaded objects
30.8.3.2 Iterating the object collection for its member objects
30.8.4 Reading an object
30.8.4.1 Traversing value changes of objects
30.8.4.2 Jump Behavior
30.8.4.3 Dump off regions
30.8.5 Sample code using object (and traverse) collections
30.8.6 Object-based traversal
30.8.7 Time-ordered traversal
30.9 Optionally unloading the data
30.10 Reading data from multiple databases and/or different read library providers
30.11 VPI routines extended in SystemVerilog
30.12 VPI routines added in SystemVerilog
30.12.1 VPI reader routines
第三十一章 SystemVerilog VPI Object Model
31.1 简介（一般信息）
31.2 Instance
31.3 Interface
31.4 Program
31.5 Module (supersedes IEEE 1364-2001 26.6.1)
31.6 Modport
31.7 Interface tf decl
31.8 Ports (supersedes IEEE 1364-2001 26.6.5)
31.9 Ref Obj
31.9.1 Examples
31.10 Variables (supersedes IEEE 1364-2001 section 26.6.8)
31.11 Var Select (supersedes IEEE 1364-2001 26.6.8)
31.12 Typespec
31.13 Variable Drivers and Loads (supersedes IEEE 1364-2001 26.6.23)
31.14 Instance Arrays (supersedes IEEE 1364-2001 26.6.2)
31.15 Scope (supersedes IEEE 1364-2001 26.6.3)
31.16 IO Declaration (supersedes IEEE 1364-2001 26.6.4)
31.17 Clocking Block
31.18 Class Object Definition
31.19 Constraint, constraint ordering, distribution,
31.20 Constraint expression
31.21 Class Variables
31.22 Structure/Union
31.23 Named Events (supersedes IEEE 1364-2001 26.6.11)
31.24 Task, Function Declaration (supersedes IEEE 1364-2001 26.6.18)
31.25 Alias Statement
31.25.1 Examples
31.26 Frames (supersedes IEEE 1364-2001 26.6.20)
31.27 Threads
31.28 tf call (supersedes IEEE 1364-2001 26.6.19)
31.29 Module path, path term (supersedes IEEE 1364-2001 26.6.15)
31.30 Concurrent assertions
31.31 Property Decl
31.32 Property Specification
31.33 Multiclock Sequence Expression
31.34 Sequence Declaration
31.35 Sequence Expression
31.36 Attribute (supersedes IEEE 1364-2001 26.6.42)
31.37 Atomic Statement (supersedes IEEE 1364-2001 26.6.27)
31.38 If, if else, return, case, do while (supersedes IEEE 1364-2001 26.6.35, 26.6.36)
31.39 waits, disables, expect, foreach (supersedes IEEE 1364 26.6.38)
31.40 Simple expressions (supersedes IEEE 1364-2001 26.6.25)
31.41 Expressions (supersedes IEEE 1364-2001 26.6.26)
31.42 Event control (supersedes IEEE 1364-2001 26.6.30)
31.43 Event stmt (supersedes IEEE 1364-2001 26.6.27)
31.44 Process (supersedes IEEE 1364-2001 26.6.27)
31.45 Assignment (supersedes IEEE 1364-2001 26.6.28)
附录A 形式语法
A.1 源文本
A.1.1 库源文本
A.1.2 配置源文本
A.1.3 模块和原语源文本
A.1.4 模块参数和端口
A.1.5 模块条目
A.1.6 接口条目
A.1.7 程序条目
A.1.8 类条目
A.1.9 Constraints
A.1.10 Package items
A.2 声明
A.2.1 声明类型
A.2.1.1 模块参数声明
A.2.1.2 Port declarations
A.2.1.3 Type declarations
A.2.2 Declaration data types
A.2.2.1 Net and variable types
A.2.2.2 Strengths
A.2.2.3 Delays
A.2.3 Declaration lists
A.2.4 Declaration assignments
A.2.5 Declaration ranges
A.2.6 Function declarations
A.2.7 Task declarations
A.2.8 Block item declarations
A.2.9 Interface declarations
A.2.10 Assertion declarations
A.2.11 Covergroup declarations
A.3 Primitive instances
A.3.1 Primitive instantiation and instances
A.3.2 Primitive strengths
A.3.3 Primitive terminals
A.3.4 Primitive gate and switch types
A.4 Module, interface and generated instantiation
A.4.1 Instantiation
A.4.1.1 Module instantiation
A.4.1.2 Interface instantiation
A.4.1.3 Program instantiation
A.4.2 Generated instantiation
A.4.2.1 Generated module instantiation
A.4.2.2 Generated interface instantiation
A.5 UDP declaration and instantiation
A.5.1 UDP declaration
A.5.2 UDP ports
A.5.3 UDP body
A.5.4 UDP instantiation
A.6 Behavioral statements
A.6.1 Continuous assignment and net alias statements
A.6.2 Procedural blocks and assignments
A.6.3 Parallel and sequential blocks
A.6.4 Statements
A.6.5 Timing control statements
A.6.6 Conditional statements
A.6.7 Case statements
A.6.7.1 Patterns
A.6.8 Looping statements
A.6.9 Subroutine call statements
A.6.10 Assertion statements
A.6.11 Clocking block
A.6.12 Randsequence
A.7 Specify section
A.7.1 Specify block declaration
A.7.2 Specify path declarations
A.7.3 Specify block terminals
A.7.4 Specify path delays
A.7.5 System timing checks
A.7.5.1 System timing check commands
A.7.5.2 System timing check command arguments
A.7.5.3 System timing check event definitions
A.8 Expressions
A.8.1 Concatenations
A.8.2 Subroutine calls
A.8.3 Expressions
A.8.4 Primaries
A.8.5 Expression left-side values
A.8.6 Operators
A.8.7 Numbers
A.8.8 Strings
A.9 General
A.9.1 Attributes
A.9.2 Comments
A.9.3 Identifiers
A.9.4 White space
A.10 Footnotes (normative)
附录B 关键字
附录C 标准包
C.1 semaphore
C.2 mailbox
C.3 randomize
C.4 进程
附录D 链表
D.1 List definitions
D.2 List declaration
D.2.1 Declaring list variables
D.2.2 Declaring list iterators
D.3 Linked list class prototypes
D.3.1 List_Iterator class prototype
D.3.2 List class prototype
D.4 List_Iterator methods
D.4.1 next()
D.4.2 prev()
D.4.3 eq()
D.4.4 neq()
D.4.5 data()
D.5 List methods
D.5.1 size()
D.5.2 empty()
D.5.3 push_front()
D.5.4 push_back()
D.5.5 front()
D.5.6 back()
D.5.7 pop_front()
D.5.8 pop_back()
D.5.9 start()
D.5.10 finish()
D.5.11 insert()
D.5.12 insert_range()
D.5.13 erase()
D.5.14 erase_range()
D.5.15 set()
D.5.16 swap()
D.5.17 clear()
D.5.18 purge()
附录E DPI C-layer
E.1 概述
E.2 Naming conventions
E.3 Portability
E.3.1 Binary compatibility
E.3.2 Source-level compatibility
E.4 Include files
E.4.1 svdpi.h include file
E.4.2 svdpi_src.h include file
E.5 Semantic constraints
E.5.1 Types of formal arguments
E.5.2 input arguments
E.5.3 output arguments
E.5.4 Value changes for output and inout arguments
E.5.5 context and non-context tasks and functions
E.5.6 pure functions
E.5.7 Memory management
E.6 Data types
E.6.1 Limitations
E.6.2 Duality of types: SystemVerilog types vs. C types
E.6.3 Data representation
E.6.4 Basic types
E.6.5 Normalized ranges
E.6.6 Mapping between SystemVerilog ranges and normalized ranges
E.6.7 Canonical representation of packed arrays
E.7 Argument passing modes
E.7.1 Overview
E.7.2 Calling SystemVerilog tasks and functions from C
E.7.3 Argument passing by value
E.7.4 Argument passing by reference
E.7.5 Allocating actual arguments for SystemVerilog-specific types
E.7.6 Argument passing by handle—open arrays
E.7.7 input arguments
E.7.8 inout and output arguments
E.7.9 Function result
E.8 Context tasks and functions
E.8.1 Overview of DPI and VPI context
E.8.2 Context of imported and export tasks and functions
E.8.3 Working with DPI context tasks and functions in C code
E.8.4 Example 1 — Using DPI context functions
E.8.5 Relationship between DPI and VPI/PLI interfaces
E.9 Include files
E.9.1 Binary compatibility include file svdpi.h
E.9.1.1 Scalars of type bit and logic
E.9.1.2 Canonical representation of packed arrays
E.9.1.3 Implementation-dependent representation
E.9.1.4 Translation between the actual representation and the canonical representation
E.9.2 Source-level compatibility include file svdpi_src.h
E.9.3 Example 2 — binary compatible application
E.9.4 Example 3— source-level compatible application
E.10 Arrays
E.10.1 Multidimensional arrays
E.10.2 Direct access to unpacked arrays
E.10.3 Access to packed arrays via canonical representation
E.10.3.1 Bit selects
E.10.3.2 Part selects
E.11 Open arrays
E.11.1 Actual ranges
E.11.2 Array querying functions
E.11.3 Access functions
E.11.4 Access to the actual representation
E.11.5 Access to elements via canonical representation
E.11.6 Access to scalar elements (bit and logic)
E.11.7 Access to array elements of other types
E.11.8 Example 4— two-dimensional open array
E.11.9 Example 5 — open array
E.11.10 Example 6 — access to packed arrays
E.11.11 Example 7 — binary compatible calls of exported functions
附录F 包含文件
F.1 Binary-level compatibility include file svdpi.h
F.2 源级兼容性包含文件svdpi_src.h
附录G 包含外部语言代码
G.1 Location independence
G.2 Object code inclusion
G.2.1 Bootstrap file
G.2.2 Examples
附录H 并发断言的形式语义
H.1 简介
H.2 抽象语法
H.2.1 Abstract grammars
H.2.2 Notations
H.2.3 Derived forms
H.2.3.1 Derived non-overlapping implication operator
H.2.3.2 Derived consecutive repetition operators
H.2.3.3 Derived delay and concatenation operators
H.2.3.4 Derived non-consecutive repetition operators
H.2.3.5 Other derived operators
H.3 语义
H.3.1 Rewrite rules for clocks
H.3.2 Tight satisfaction without local variables
H.3.3 Satisfaction without local variables
H.3.3.1 Neutral satisfaction
H.3.3.2 Weak and strong satisfaction by finite words
H.3.4 Local variable flow
H.3.5 Tight satisfaction with local variables
H.3.6 Satisfaction with local variables
H.3.6.1 Neutral satisfaction
H.3.6.2 Weak and strong satisfaction by finite words
H.4 Extended Expressions
H.4.1 Extended booleans
H.4.2 Past
H.5 Recursive Properties
附录I sv_vpi_user.h
附录J 术语表
集合
断言
Bit-stream
Canonical representation
Constant
Context imported task
Disable protocol
DPI
Dynamic
Elaboration
枚举类型
Exported task
Imported task
Interface
Integral
LRM
Open array
Packed array
进程
信号
单一类型（Singular）
SystemVerilog
非压缩数组（Unpacked array）
Verilog
VPI
附录K 参考书目


Index

Index
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | G | H | I | L | O | P | S | V | 单 | 第 | 断 | 非 | 附 | 集 | 进 | 枚 | 信
1
10.1 简介（一般信息）
10.2 任务
10.3 函数
10.3.1 返回值与void函数
10.3.2 丢弃函数返回值
10.4 任务与函数的参数传递
10.4.1 通过值传递
10.4.2 通过引用传递
10.4.3 缺省参数值
10.4.4 通过名字传递参数
10.4.5 可选的参数列表
10.5 导入与导出函数
11.1 简介
11.10 this
11.11 赋值、重命名与拷贝
11.12 继承与子类
11.13 过载成员
11.14 super
11.15 强制类型转换
11.16 串接构造器
11.17 数据隐藏与封装
11.18 常量类属性
11.19 抽象类与虚拟方法
11.2 语法
11.20 多态性：动态方法查找
11.21 类范围解析操作符 ::
11.22 块外声明
11.23 参数化的类
11.24 typedef类
11.25 类与结构体
11.26 内存管理
11.3 概述
11.4 对象（类实例）
11.5 对象属性
11.6 对象方法
11.7 构造器
11.8 静态类属性
11.9 静态方法
12.1 简介（一般信息）
12.10 内联随机变量控制
12.10.1 内联约束检查器
12.11 范围变量的随机化 — std::randomize()
12.11.1 为范围变量添加约束 — std::randomize() with
12.12 随机数系统函数与方法
12.12.1 $urandom
12.12.2 $urandom_range()
12.12.3 srandom()
12.12.4 get_randstate()
12.12.5 set_randstate()
12.13 随机稳定性
12.13.1 随机稳定性的特性
12.13.2 线程稳定性
12.13.3 对象稳定性
12.14 为随机化手工设置种子
12.15 随机加权的条件 — randcase
12.16 随机序列产生 — randsequence
12.16.1 随机生成式权重
12.16.2 If...else生成式语句
12.16.3 case生成式语句
12.16.4 repeat生成式语句
12.16.5 交叉生成式 — rand join
12.16.6 中止生成式 — break和return
12.16.7 生成式间的值传递
12.2 概述
12.3 随机变量
12.3.1 rand修饰符
12.3.2 randc修饰符
12.4 约束块
12.4.1 外部约束块
12.4.10 静态约束块
12.4.11 约束中的函数
12.4.12 约束守卫者
12.4.2 继承
12.4.3 集合成员资格
12.4.4 分布
12.4.5 蕴含
12.4.6 if...else约束
12.4.7 迭代约束
12.4.8 全局约束
12.4.9 变量排序
12.5 随机化方法
12.5.1 randomize()
12.5.2 pre_randomize()与post_randomize()
12.5.3 随机化方法注意事项
12.6 内联约束 — randomize() with
12.7 使用rand_mode()关闭随机变量
12.8 使用constraint_mode()控制约束
12.9 动态的约束修改
13.1 简介（一般信息）
13.2 semaphore
13.2.1 new()
13.2.2 put()
13.2.3 get()
13.2.4 try_get()
13.3 mailbox
13.3.1 new()
13.3.2 num()
13.3.3 put()
13.3.4 try_put()
13.3.5 get()
13.3.6 try_get()
13.3.7 peek()
13.3.8 try_peek()
13.4 参数化的mailbox
13.5 事件
13.5.1 触发一个事件
13.5.2 无阻塞的事件触发
13.5.3 等待一个事件
13.5.4 稳固的触发：触发特性
13.6 事件排序：wait_order()
13.7 事件变量
13.7.1 合并事件
13.7.2 回收事件
13.7.3 事件比较
14.1 硬件模型的执行及其验证环境
14.2 事件仿真
14.3 分层的事件调度器
14.3.1 SystemVerilog仿真参考算法
14.4 PLI回调控制点
15.1 简介（一般信息）
15.10 周期延时：##
15.11 缺省时钟控制
15.12 输入采样
15.13 同步的事件
15.14 同步的驱动
15.14.1 驱动和无阻塞赋值
15.14.2 驱动值解析
15.2 时钟控制块声明
15.3 输入时滞与输出时滞
15.4 层次化的表达式
15.5 多时钟控制块中的信号
15.6 时钟控制块的作用范围和生命周期
15.7 多时钟控制块的例子
15.8 接口与时钟控制块
15.9 时钟控制块事件
16.1 简介（一般信息）
16.2 程序结构
16.3 多个程序
16.4 消除测试平台的竞争
16.4.1 零时滞时钟控制块竞争
16.5 阻塞周期/事件模式下的任务
16.6 程序控制任务
16.6.1 $exit()
17.1 简介（一般信息）
17.10 系统函数
17.11 声明特性
17.11.1 蕴含
17.11.2 特性的例子
17.11.3 递归特性
17.11.4 有限长度与无限长度行为
17.11.5 Non-degeneracy
17.12 多时钟的支持
17.12.1 多时钟控制序列
17.12.2 多时钟控制特性
17.12.3 时钟流
17.12.4 例子
17.12.5 在多时钟语境中检测和使用一个序列的结束点
17.13 并发断言
17.13.1 断言语句
17.13.2 假设语句
17.13.3 覆盖语句
17.13.4 在过程化代码外部使用并发断言语句
17.13.5 在过程化代码中嵌入并发断言
17.14 时钟解析
17.14.1 在多时钟控制特性中的时钟解析
17.15 将特性绑定到作用域或实例
17.16 expect语句
17.2 即时断言
17.3 并发断言概述
17.4 布尔表达式
17.4.1 操作数类型
17.4.2 变量
17.4.3 操作符
17.5 序列
17.6 声明序列
17.7 序列操作
17.7.1 操作符优先级
17.7.10 一个序列结束点的检测和使用
17.7.2 序列中的复制
17.7.3 采样值函数
17.7.4 与操作
17.7.5 交集（具有长度限制的与操作）
17.7.6 或操作
17.7.7 first_match操作
17.7.8 序列上的条件
17.7.9 包含在另外一个序列中的序列
17.8 处理一个序列中的数据
17.9 在一个序列匹配时调用子程序
18.1 简介（一般信息）
18.10 时间单位与精度
18.11 模块实例
18.11.1 Instantiation using positional port connections
18.11.2 Instantiation using named port connections
18.11.3 Instantiation using implicit .name port connections
18.11.4 Instantiation using implicit .* port connections
18.12 端口连接规则
18.12.1 变量的端口连接规则
18.12.2 线网的端口连接规则
18.12.3 接口的端口连接规则
18.12.4 兼容的端口类型
18.12.5 非压缩数组端口与实例数组
18.13 命名空间
18.14 层次化的名字
18.2 包
18.2.1 引用包中的数据
18.2.2 搜索顺序规则
18.3 编译单元的支持
18.4 顶层实例
18.5 模块声明
18.6 嵌套的模块
18.7 外部模块
18.8 端口声明
18.9 端口表达式列表
19.1 简介（一般信息）
19.2 接口语法
19.2.1 Example without using interfaces
19.2.2 Interface example using a named bundle
19.2.3 Interface example using a generic bundle
19.3 接口中的端口
19.4 modport
19.4.1 An example of a named port bundle
19.4.2 An example of connecting a port bundle
19.4.3 An example of connecting a port bundle to a generic interface
19.4.4 Modport expressions
19.4.5 Clocking blocks and modports
19.5 接口与specify块
19.6 接口中的任务与函数
19.6.1 An example of using tasks in an interface
19.6.2 An example of using tasks in modports
19.6.3 An example of exporting tasks and functions
19.6.4 An example of multiple task exports
19.7 参数化接口
19.8 虚拟接口
19.8.1 Virtual interfaces and clocking blocks
19.8.2 Virtual interfaces modports and clocking blocks
19.9 对接口对象的访问
2
2.1 简介（一般信息）
2.2 文本值语法
2.3 整数和逻辑文本
2.4 实数文本
2.5 时间文本
2.6 字符串文本
2.7 数组文本
2.8 结构体文本
20.1 简介（一般信息）
20.2 定义覆盖模型：covergroup
20.3 在类中使用covergroup
20.4 定义覆盖点
20.4.1 Specifying bins for transitions
20.4.2 Automatic bin creation for coverage points
20.4.3 Wildcard specification of coverage point bins
20.4.4 Excluding coverage point values or transitions
20.4.5 Specifying Illegal coverage point values or transitions
20.5 Defining cross coverage
20.5.1 Example of user-defined cross coverage and select expressions
20.5.2 Excluding cross products
20.5.3 Specifying Illegal cross products
20.6 Specifying coverage options
20.6.1 Covergroup Type Options
20.7 Predefined coverage methods
20.8 Predefined coverage system tasks and functions
20.9 Organization of option and type_option members
21.1 简介（一般信息）
21.1.1 defparam语句的删除
21.2 参数声明语法
22.1 简介（一般信息）
22.2 库
23.1 简介（一般信息）
23.10 断言系统函数
23.11 随机数系统函数
23.12 程序控制
23.13 覆盖系统函数
23.14 对Verilog-2001系统任务的增强
23.15 $readmemb与$readmemh
23.15.1 读取压缩的数据
23.15.2 读取两态类型
23.16 $writememb and $writememh
23.16.1 Writing packed data
23.16.2 Writing 2-state types
23.16.3 Writing addresses to output file
23.17 File format considerations for multi-dimensional unpacked arrays
23.18 System task arguments for multi-dimensional unpacked arrays
23.2 确立时的typeof函数
23.3 typename函数
23.4 表达式尺寸系统函数
23.5 范围系统函数
23.6 Shortreal转换
23.7 数组查询系统函数
23.8 断言严重性系统任务
23.9 断言控制系统任务
25.1 简介（一般信息）
25.2 `define宏
25.3 `include
26.1 简介（一般信息）
26.2 defparam语句
26.3 过程赋值与解赋值语句
27.1 概述
27.1.1 Tasks and functions
27.1.2 Data types
27.1.2.1 Data representation
27.2 Two layers of the DPI
27.2.1 DPI SystemVerilog layer
27.2.2 DPI foreign language layer
27.3 Global name space of imported and exported functions
27.4 导入的任务和函数
27.4.1 Required properties of imported tasks and functions — semantic constraints
27.4.1.1 Instant completion of imported functions
27.4.1.2 input, output and inout arguments
27.4.1.3 Special properties pure and context
27.4.1.4 Memory management
27.4.1.5 Reentrancy of imported tasks
27.4.1.6 C++ exceptions
27.4.2 Pure functions
27.4.3 Context tasks and functions
27.4.4 Import declarations
27.4.5 Function result
27.4.6 形式参数的类型
27.4.6.1 开放数组
27.5 Calling imported functions
27.5.1 Argument passing
27.5.1.1 “What You Specify Is What You Get” principle
27.5.2 Value changes for output and inout arguments
27.6 Exported functions
27.7 Exported tasks
27.8 Disabling DPI tasks and functions
28.1 需求
28.1.1 命名约定
28.2 Extensions to VPI enumerations
28.2.1 Object types
28.2.2 Object properties
28.2.3 Callbacks
28.2.4 Control constants
28.3 Static information
28.3.1 Obtaining assertion handles
28.3.2 Obtaining static assertion information
28.3.2.1 Using vpi_get_assertion_info
28.3.2.2 Extending vpi_get() and vpi_get_str()
28.4 Dynamic information
28.4.1 Placing assertion system callbacks
28.4.2 Placing assertions callbacks
28.5 Control functions
28.5.1 Assertion system control
28.5.2 Assertion control
29.1 需求
29.1.1 SystemVerilog API
29.1.2 Naming conventions
29.1.3 Nomenclature
29.2 SystemVerilog real-time coverage access
29.2.1 Predefined coverage constants in SystemVerilog
29.2.2 Built-in coverage access system functions
29.2.2.1 $coverage_control
29.2.2.2 $coverage_get_max
29.2.2.3 $coverage_get
29.2.2.4 $coverage_merge
29.2.2.5 $coverage_save
29.3 FSM recognition
29.3.1 Specifying the signal that holds the current state
29.3.2 Specifying the part-select that holds the current state
29.3.3 Specifying the concatenation that holds the current state
29.3.4 Specifying the signal that holds the next state
29.3.5 Specifying the current and next state signals in the same declaration
29.3.6 Specifying the possible states of the FSM
29.3.7 Pragmas in one-line comments
29.3.8 Example
29.4 VPI coverage extensions
29.4.1 VPI entity/relation diagrams related to coverage
29.4.2 Extensions to VPI enumerations
29.4.3 Obtaining coverage information
29.4.4 Controlling coverage
3
3.1 简介（一般信息）
3.10 枚举
3.10.1 将新的数据类型定义成枚举类型
3.10.2 枚举类型的排列
3.10.3 类型检查
3.10.4 数值表达式中的枚举类型
3.10.4.1 first()
3.10.4.2 last()
3.10.4.3 next()
3.10.4.4 prev()
3.10.4.5 num()
3.10.4.6 name()
3.10.4.7 使用枚举类型的方法
3.11 结构体与联合体
3.12 类
3.13 单一类型与集合类型
3.14 强制类型转换
3.15 $cast动态强制类型转换
3.16 位流强制类型转换
3.2 数据类型语法
3.3 整数数据类型
3.3.1 integral类型
3.3.2 两态（两值）与四态（四值）数据类型
3.3.3 有符号与无符号数据类型
3.4 real与shortreal数据类型
3.5 void数据类型
3.6 chandle数据类型
3.7 string数据类型
3.7.1 len()
3.7.10 atoreal()
3.7.11 itoa()
3.7.12 hextoa()
3.7.13 octtoa()
3.7.14 bintoa()
3.7.15 realtoa()
3.7.2 putc()
3.7.3 getc()
3.7.4 toupper()
3.7.5 tolower()
3.7.6 compare()
3.7.7 icompare()
3.7.8 substr(int i, int j)
3.7.9 atoi(), atohex(), atooct(), atobin()
3.8 event数据类型
3.9 用户定义的类型
30.1 简介（一般信息）
30.10 Reading data from multiple databases and/or different read library providers
30.11 VPI routines extended in SystemVerilog
30.12 VPI routines added in SystemVerilog
30.12.1 VPI reader routines
30.2 需求
30.3 Extensions to VPI enumerations
30.3.1 Object types
30.3.2 Object properties
30.3.2.1 Static info
30.3.2.2 Dynamic info
30.3.2.2.1 Control constants
30.3.3 System callbacks
30.4 VPI object type additions
30.4.1 Traverse object
30.4.2 VPI collection
30.4.2.1 Operations on collections
30.5 Object model diagrams
30.6 Usage extensions to VPI routines
30.7 VPI routines added in SystemVerilog
30.8 Reading data
30.8.1 VPI read initialization and load access initialization
30.8.2 Object selection for traverse access
30.8.3 Optionally loading objects
30.8.3.1 Iterating the design for the loaded objects
30.8.3.2 Iterating the object collection for its member objects
30.8.4 Reading an object
30.8.4.1 Traversing value changes of objects
30.8.4.2 Jump Behavior
30.8.4.3 Dump off regions
30.8.5 Sample code using object (and traverse) collections
30.8.6 Object-based traversal
30.8.7 Time-ordered traversal
30.9 Optionally unloading the data
31.1 简介（一般信息）
31.10 Variables (supersedes IEEE 1364-2001 section 26.6.8)
31.11 Var Select (supersedes IEEE 1364-2001 26.6.8)
31.12 Typespec
31.13 Variable Drivers and Loads (supersedes IEEE 1364-2001 26.6.23)
31.14 Instance Arrays (supersedes IEEE 1364-2001 26.6.2)
31.15 Scope (supersedes IEEE 1364-2001 26.6.3)
31.16 IO Declaration (supersedes IEEE 1364-2001 26.6.4)
31.17 Clocking Block
31.18 Class Object Definition
31.19 Constraint, constraint ordering, distribution,
31.2 Instance
31.20 Constraint expression
31.21 Class Variables
31.22 Structure/Union
31.23 Named Events (supersedes IEEE 1364-2001 26.6.11)
31.24 Task, Function Declaration (supersedes IEEE 1364-2001 26.6.18)
31.25 Alias Statement
31.25.1 Examples
31.26 Frames (supersedes IEEE 1364-2001 26.6.20)
31.27 Threads
31.28 tf call (supersedes IEEE 1364-2001 26.6.19)
31.29 Module path, path term (supersedes IEEE 1364-2001 26.6.15)
31.3 Interface
31.30 Concurrent assertions
31.31 Property Decl
31.32 Property Specification
31.33 Multiclock Sequence Expression
31.34 Sequence Declaration
31.35 Sequence Expression
31.36 Attribute (supersedes IEEE 1364-2001 26.6.42)
31.37 Atomic Statement (supersedes IEEE 1364-2001 26.6.27)
31.38 If, if else, return, case, do while (supersedes IEEE 1364-2001 26.6.35, 26.6.36)
31.39 waits, disables, expect, foreach (supersedes IEEE 1364 26.6.38)
31.4 Program
31.40 Simple expressions (supersedes IEEE 1364-2001 26.6.25)
31.41 Expressions (supersedes IEEE 1364-2001 26.6.26)
31.42 Event control (supersedes IEEE 1364-2001 26.6.30)
31.43 Event stmt (supersedes IEEE 1364-2001 26.6.27)
31.44 Process (supersedes IEEE 1364-2001 26.6.27)
31.45 Assignment (supersedes IEEE 1364-2001 26.6.28)
31.5 Module (supersedes IEEE 1364-2001 26.6.1)
31.6 Modport
31.7 Interface tf decl
31.8 Ports (supersedes IEEE 1364-2001 26.6.5)
31.9 Ref Obj
31.9.1 Examples
4
4.1 简介（一般信息）
4.10 联合数组方法
4.10.1 num()
4.10.2 delete()
4.10.3 exists()
4.10.4 first()
4.10.5 last()
4.10.6 next()
4.10.7 prev()
4.11 联合数组赋值
4.12 联合数组自变量
4.13 联合数组文本
4.14 队列
4.14.1 队列操作符
4.14.2 队列方法
4.14.2.1 size()
4.14.2.2 insert()
4.14.2.3 delete()
4.14.2.4 pop_front()
4.14.2.5 pop_back()
4.14.2.6 push_front()
4.14.2.7 push_back()
4.15 数组处理方法
4.15.1 数组定位符方法
4.15.2 数组排序方法
4.15.3 数组缩减方法
4.15.4 迭代器索引查询
4.2 压缩与非压缩数组
4.3 多维数组
4.4 数组的索引与分片
4.5 数组查询函数
4.6 动态数组
4.6.1 new[]
4.6.2 size()
4.6.3 delete()
4.7 数组赋值
4.8 将数组作为自变量
4.9 联合数组
4.9.1 通配符索引类型
4.9.2 字符串索引
4.9.3 类索引
4.9.4 integer（或int）索引
4.9.5 有符号的压缩数组
4.9.6 无符号压缩数组或压缩结构体
4.9.7 其它用户定义类型
5
5.1 简介（一般信息）
5.2 数据声明语法
5.3 常量
5.4 变量
5.5 作用范围与生命周期
5.6 线网、reg、与logic
5.7 信号别名
5.8 类型兼容性
5.8.1 等价类型
5.8.2 赋值兼容
5.8.3 强制转换兼容
5.8.4 类型非兼容性
6
6.1 简介（一般信息）
6.2 缺省属性类型
7
7.1 简介（一般信息）
7.10 内建方法
7.10.1 内建包
7.11 静态前缀
7.12 串联
7.13 非压缩数组表达式
7.14 结构体表达式
7.15 标签联合体表达式与成员访问
7.16 集合表达式
7.17 操作符过载
7.18 流操作符（压缩/非压缩）
7.18.1 将动态尺寸的数据位流化
7.19 条件操作符
7.2 操作符语法
7.20 集合成员资格
7.3 赋值操作符
7.4 对logic和bit类型的操作
7.5 通配等式与通配不等式
7.6 实操作符
7.7 尺寸
7.8 符号
7.9 操作符优先级与关联性
8
8.1 简介（一般信息）
8.10 事件控制
8.10.1 序列事件
8.11 电平敏感的序列控制
8.12 过程赋值与解赋值的移除
8.2 语句
8.3 阻塞赋值与无阻塞赋值
8.4 选择语句
8.4.1 模式匹配
8.4.1.1 case语句中的模式匹配
8.4.1.2 if语句中的模式匹配
8.4.1.3 条件表达式中的模式匹配
8.5 循环语句
8.5.1 do...while循环
8.5.2 循环的增强
8.5.3 foreach循环
8.6 跳转语句
8.7 final块
8.8 命名块与语句标签
8.9 disable
9
9.1 简介（一般信息）
9.2 组合逻辑
9.2.1 隐含的always_comb敏感性
9.3 锁存逻辑
9.4 时序逻辑
9.5 连续赋值
9.6 fork...join
9.7 进程执行线程
9.8 进程控制
9.8.1 wait fork
9.8.2 disable fork
9.9 精细的进程控制
A
A.1 源文本
A.1.1 库源文本
A.1.10 Package items
A.1.2 配置源文本
A.1.3 模块和原语源文本
A.1.4 模块参数和端口
A.1.5 模块条目
A.1.6 接口条目
A.1.7 程序条目
A.1.8 类条目
A.1.9 Constraints
A.10 Footnotes (normative)
A.2 声明
A.2.1 声明类型
A.2.1.1 模块参数声明
A.2.1.2 Port declarations
A.2.1.3 Type declarations
A.2.10 Assertion declarations
A.2.11 Covergroup declarations
A.2.2 Declaration data types
A.2.2.1 Net and variable types
A.2.2.2 Strengths
A.2.2.3 Delays
A.2.3 Declaration lists
A.2.4 Declaration assignments
A.2.5 Declaration ranges
A.2.6 Function declarations
A.2.7 Task declarations
A.2.8 Block item declarations
A.2.9 Interface declarations
A.3 Primitive instances
A.3.1 Primitive instantiation and instances
A.3.2 Primitive strengths
A.3.3 Primitive terminals
A.3.4 Primitive gate and switch types
A.4 Module, interface and generated instantiation
A.4.1 Instantiation
A.4.1.1 Module instantiation
A.4.1.2 Interface instantiation
A.4.1.3 Program instantiation
A.4.2 Generated instantiation
A.4.2.1 Generated module instantiation
A.4.2.2 Generated interface instantiation
A.5 UDP declaration and instantiation
A.5.1 UDP declaration
A.5.2 UDP ports
A.5.3 UDP body
A.5.4 UDP instantiation
A.6 Behavioral statements
A.6.1 Continuous assignment and net alias statements
A.6.10 Assertion statements
A.6.11 Clocking block
A.6.12 Randsequence
A.6.2 Procedural blocks and assignments
A.6.3 Parallel and sequential blocks
A.6.4 Statements
A.6.5 Timing control statements
A.6.6 Conditional statements
A.6.7 Case statements
A.6.7.1 Patterns
A.6.8 Looping statements
A.6.9 Subroutine call statements
A.7 Specify section
A.7.1 Specify block declaration
A.7.2 Specify path declarations
A.7.3 Specify block terminals
A.7.4 Specify path delays
A.7.5 System timing checks
A.7.5.1 System timing check commands
A.7.5.2 System timing check command arguments
A.7.5.3 System timing check event definitions
A.8 Expressions
A.8.1 Concatenations
A.8.2 Subroutine calls
A.8.3 Expressions
A.8.4 Primaries
A.8.5 Expression left-side values
A.8.6 Operators
A.8.7 Numbers
A.8.8 Strings
A.9 General
A.9.1 Attributes
A.9.2 Comments
A.9.3 Identifiers
A.9.4 White space
B
Bit-stream
C
C.1 semaphore
C.2 mailbox
C.3 randomize
C.4 进程
Canonical representation
Constant
Context imported task
D
D.1 List definitions
D.2 List declaration
D.2.1 Declaring list variables
D.2.2 Declaring list iterators
D.3 Linked list class prototypes
D.3.1 List_Iterator class prototype
D.3.2 List class prototype
D.4 List_Iterator methods
D.4.1 next()
D.4.2 prev()
D.4.3 eq()
D.4.4 neq()
D.4.5 data()
D.5 List methods
D.5.1 size()
D.5.10 finish()
D.5.11 insert()
D.5.12 insert_range()
D.5.13 erase()
D.5.14 erase_range()
D.5.15 set()
D.5.16 swap()
D.5.17 clear()
D.5.18 purge()
D.5.2 empty()
D.5.3 push_front()
D.5.4 push_back()
D.5.5 front()
D.5.6 back()
D.5.7 pop_front()
D.5.8 pop_back()
D.5.9 start()
Disable protocol
DPI
Dynamic
E
E.1 概述
E.10 Arrays
E.10.1 Multidimensional arrays
E.10.2 Direct access to unpacked arrays
E.10.3 Access to packed arrays via canonical representation
E.10.3.1 Bit selects
E.10.3.2 Part selects
E.11 Open arrays
E.11.1 Actual ranges
E.11.10 Example 6 — access to packed arrays
E.11.11 Example 7 — binary compatible calls of exported functions
E.11.2 Array querying functions
E.11.3 Access functions
E.11.4 Access to the actual representation
E.11.5 Access to elements via canonical representation
E.11.6 Access to scalar elements (bit and logic)
E.11.7 Access to array elements of other types
E.11.8 Example 4— two-dimensional open array
E.11.9 Example 5 — open array
E.2 Naming conventions
E.3 Portability
E.3.1 Binary compatibility
E.3.2 Source-level compatibility
E.4 Include files
E.4.1 svdpi.h include file
E.4.2 svdpi_src.h include file
E.5 Semantic constraints
E.5.1 Types of formal arguments
E.5.2 input arguments
E.5.3 output arguments
E.5.4 Value changes for output and inout arguments
E.5.5 context and non-context tasks and functions
E.5.6 pure functions
E.5.7 Memory management
E.6 Data types
E.6.1 Limitations
E.6.2 Duality of types: SystemVerilog types vs. C types
E.6.3 Data representation
E.6.4 Basic types
E.6.5 Normalized ranges
E.6.6 Mapping between SystemVerilog ranges and normalized ranges
E.6.7 Canonical representation of packed arrays
E.7 Argument passing modes
E.7.1 Overview
E.7.2 Calling SystemVerilog tasks and functions from C
E.7.3 Argument passing by value
E.7.4 Argument passing by reference
E.7.5 Allocating actual arguments for SystemVerilog-specific types
E.7.6 Argument passing by handle—open arrays
E.7.7 input arguments
E.7.8 inout and output arguments
E.7.9 Function result
E.8 Context tasks and functions
E.8.1 Overview of DPI and VPI context
E.8.2 Context of imported and export tasks and functions
E.8.3 Working with DPI context tasks and functions in C code
E.8.4 Example 1 — Using DPI context functions
E.8.5 Relationship between DPI and VPI/PLI interfaces
E.9 Include files
E.9.1 Binary compatibility include file svdpi.h
E.9.1.1 Scalars of type bit and logic
E.9.1.2 Canonical representation of packed arrays
E.9.1.3 Implementation-dependent representation
E.9.1.4 Translation between the actual representation and the canonical representation
E.9.2 Source-level compatibility include file svdpi_src.h
E.9.3 Example 2 — binary compatible application
E.9.4 Example 3— source-level compatible application
Elaboration
Exported task
F
F.1 Binary-level compatibility include file svdpi.h
F.2 源级兼容性包含文件svdpi_src.h
G
G.1 Location independence
G.2 Object code inclusion
G.2.1 Bootstrap file
G.2.2 Examples
H
H.1 简介
H.2 抽象语法
H.2.1 Abstract grammars
H.2.2 Notations
H.2.3 Derived forms
H.2.3.1 Derived non-overlapping implication operator
H.2.3.2 Derived consecutive repetition operators
H.2.3.3 Derived delay and concatenation operators
H.2.3.4 Derived non-consecutive repetition operators
H.2.3.5 Other derived operators
H.3 语义
H.3.1 Rewrite rules for clocks
H.3.2 Tight satisfaction without local variables
H.3.3 Satisfaction without local variables
H.3.3.1 Neutral satisfaction
H.3.3.2 Weak and strong satisfaction by finite words
H.3.4 Local variable flow
H.3.5 Tight satisfaction with local variables
H.3.6 Satisfaction with local variables
H.3.6.1 Neutral satisfaction
H.3.6.2 Weak and strong satisfaction by finite words
H.4 Extended Expressions
H.4.1 Extended booleans
H.4.2 Past
H.5 Recursive Properties
I
Imported task
Integral
Interface
L
LRM
O
Open array
P
Packed array
S
SystemVerilog
V
Verilog
VPI
单
单一类型（Singular）
第
第八章 过程语句和控制流
第二十八章 SystemVerilog断言API
第二十二章 配置库
第二十九章 SystemVerilog覆盖API
第二十六章 考虑从SystemVerilog中删除的功能
第二十七章 直接编程接口（DPI）
第二十三章 系统任务与系统函数
第二十四章 VCD数据
第二十五章 编译器指令
第二十一章 参数
第二十章 覆盖
第二章 文本值
第九章 进程
第六章 属性
第七章 操作符与表达式
第三十一章 SystemVerilog VPI Object Model
第三十章 SystemVerilog数据读API
第三章 数据类型
第十八章 层次
第十二章 随机约束
第十九章 接口
第十六章 程序块
第十七章 断言
第十三章 进程间的同步与通信
第十四章 调度语义
第十五章 时钟控制块
第十一章 类
第十章 任务与函数
第四章 数组
第五章 数据声明
第一章 SystemVerilog导论
断
断言
非
非压缩数组（Unpacked array）
附
附录A 形式语法
附录B 关键字
附录C 标准包
附录D 链表
附录E DPI C-layer
附录F 包含文件
附录G 包含外部语言代码
附录H 并发断言的形式语义
附录I sv_vpi_user.h
附录J 术语表
附录K 参考书目
集
集合
进
进程
枚
枚举类型
信
信号


Welcome