Agenda
- System Verilog 数据类型-字符串
- System Verilog 数据类型-枚举类型
- System Verilog 数据类型-常量
- System Verilog 数据类型-定宽数组
- System Verilog 数据类型- 动态数组
- System Verilog 数据类型- 队列
- System Verilog 数据类型-关联数组
- System Verilog 数据类型-链表
System Verilog数据类型-字符串
- 字符串
- 可以用来保存长度可变的字符串
- 单个字符是byte类型
- 元素编号是0~N-1
The syntax declare a string is :
string variable_name [= initial_value];
where variable_name is a valid identifier and the optional initial_value can be a string literal or the value ""
for an empty string.For example:
string myName = “John Smith”;
If an initial value is not specified in the declaration, the variable is initialized to “br”,the empty string
- 字符串操作
Operator | 说明 |
---|---|
Str1 == Str2 | 判断两个字符串是否相等 如果它们相等,则结果为 1,如果它们不相等,则为 0 |
Str1 != Str2 | Inequality,==的逻辑非运算 |
Str1<Str2 Str1<= Str2 Str1> Str2 Str1>=Str2 | 比较。如果相应的条件为真,则关系运算符返回 1 使用两个字符串 Str1 和 Str2 的字典顺序。 |
{Str1,Str2,…,Strn} | 按先后顺序拼成一个新的字符串 |
{multiple{Str}} | 相当于把字符串乘以多少倍 |
Str[index] | 标号索引 |
Str.method(…) | Str的内嵌函数 |
- 字符串的内嵌函数
- len()
- function int len();
- str.len()
- 字符串长度
- 空字符串返回0
- putc()
- Task putc(int l, string s)
- Task putc(int l, byte c)
- str.putc(j,x)等价于str[j]=x;
- getc();
- function int getc(int i)
- x = str.getc(j) 等价于x = str[j]
- toupper()
- function string toupper()
- 返回一个所有字符大写的字符串
- tolower()
- function string tolower()
- 返回一个小写的字符串;
- compare() 【比较是区分大小写】
- function int compare(string s)
- embedded null bytes are included
- 常用
- icompare();【不区分大小写】
- function int compare (string s)
- embedded null bytes are included
- 比较是不区分大小写的
- substr()
- function string substr(int i ,int j) // 从i位置开始拷贝j长度的字符串(i:起始位;j:长度)
- 参数i的默认值为0,j的默认值是s.size()
- 举例:
- string s = “123abc”;
- string s = s.substr(2,2); // 从下标为2的位置开始,拷贝两个字符返回,即“3a”
- string a = s.substr(); // 不加参数会拷贝整个s,即“123abc”
- string a = s.substr(3); // 从下标为3的位置开始,拷贝剩余全部字符返回,即“abc”
- **如果 i < 0, i > j, or j >= str.len(), substr() returns " " **(the empty string)
- len()
- 内嵌函数字符串转换(了解即可)
- atoi()和itoa() //可以转化为integer()类型(四态)
- atoi() : 字符串转换为整数
- itoa():整数转换为字符串
- atohex() 和hextoa()
- atooct() 和octtoa()
- atobin() 和 bintoa()
- atoreal() 和 realtoa() // 转化为real类型(浮点数)
- atoi()和itoa() //可以转化为integer()类型(四态)
- 优点:
- 使用动态的存储方式(没有赋初值,它的长度就是0),不用担心存储空间会全部用完
- 打印
- 函数$psprintf()可返回一个格式化的临时字符串,并且可以直接传递给其他子程序
- 可用$formatf()形成字符串句子;
- 若只需打印输出,使用$display()即可
Task Name | |
---|---|
$sscanf(str,foramt,args) | $sscanf将字符串按照某个模板格式进行扫描,其字符串格式和C语言中的printf()函数类似 |
$sformat(str,format,args); | $sformat 是$sscanf 的反函数。将字符串按照给定的格式填入相应的参数args中 |
$display(format,args) | $display就是Verilog的printf语句,在stdout上显示格式化的字符串 |
$sformatf(format,args) ;UVM常用 | $sformatf 任务和$sformat 相似,除了其返回字符串结果。字符串作为$sformatf 的返回值,而不是像$sformat 一样放在第一个参数上 |
$psprintf() | 可返回一个格式化的临时字符串,并且可以直接传递给其他子程序 |
验证工程师要习惯看log;因为集成验证跑一个波形会很慢很慢
debug时多加打印,减少对仿真波形的依赖
System Verilog数据类型-枚举类型
- 枚举数据类型提供了一种方式来声明一个具有特定允许值列表的抽象变量,每一个值都有一个确定的用户自定义名字,即便签(label)
- 最简单的枚举类型包含了一个变量名称列表以及一个或多个变量
- 能够自动为列表中的每个名称分配不同的数值;
- 使用后缀“_e”来表示枚举类型
//枚举类型(验证RTL的典型场景,即状态机)
typedef enum{INIT,DECODE,IDLE} fsmstate_e;
fsmstate_e pstate,nstate;// 声明自定义
initial begin
case(pstate)
IDLE: nstate = INIT; // 数据赋值
INIT: nstate = DECODE;
default: nstate = IDLE;
endcase
$display("Next state is %s",
nstate.name()); // 显示状态
end
验证状态机:所有的分支都要遍历。状态机没有线网,都是寄存器。
容易卡入一个死循环。
定义枚举值
- 缺省是从0开始递增的整数
- 可以定义自己的枚举值
- 如果没有特别指出,枚举类型会被当成int类型存储
- enum{red,yellow,green} light1,light2; // anonymous int type
- enum{a=0,b=7,c,d=8} alphabet;
- //Syntax error: c and d are both assigned 8
- enum bit[3:0] {bronze=5'h3,silver,gold=3'h5} medal4;
- // Error in the bronze and gold member declarations (位宽需要保持一致)
- enum bit[0:0] {a,b,c} alphabet;
- // Error in c declaration,requires at least 2 bits (位宽不够)
枚举类型的子程序
- first() 返回第一个枚举常量
- last() 返回最后一个枚举常量
- next() 返回下一个枚举常量
- next(N) 返回以后第N个枚举常量
- prev() 返回前一个枚举常量
- prev(N): 返回以前第N个枚举常量
- num() returns the number of elements in the given enumeration.
- name()
- function string name();
// 遍历所有枚举成员
typedef enum{RED, BULE,GREEN} color_e;
color_e color;
color = color.first;
do
begin
$display("Color = %0d/%s",color,color.name);
color = color.next;
end
while(color != color.first); // 环形绕回即完成
枚举类型的转换
- 缺省类型为双状态int,可以使用简单的赋值表达式把变量的值直接赋给枚举类型;
- SV要求显示类型转换 (enum = $cast(int))
枚举类型的应用
-在UVM中,常见的应用是打印等级
SV数据类型 - 常量
- 文本宏
- 全局
- 不推荐,用时加模块名(大的项目时就不推荐这样使用,用的时候,一定要加上模块名,使其有独有标签)
- parameter
- 作用范围有限
- 普遍用于RTL code
- const修饰符(声明为常量)
const uvm_root uvm_top = uvm_root::get();
[因为一个环境里就只有一个top]
压缩数组和非压缩数组
-
压缩数组(packed arrays)
- can only be made of the single bit types(bit,logic,wire,and the other net types)
- can only be made of the single bit types(bit,logic,wire,and the other net types)
-
unpacked arrays
- Integer types with predefined widths cannot have packed array dimensions declared.These types are:byte,shortint,int,longint,and integer.
- 压缩数组存储:无间隙存储,与编译器、OS及硬件平台无关
- 压缩数组初始化:
- 与向量一样,可以在声明时用简单的赋值进行初始化,赋值可以是常数,常数的拼接或常数的复制
- logic [3:0][7:0] a = 32’h0;
- logic [3:0][7:0] b = {16’hz,16’h0}; // 拼接操作符
- logic [3:0][7:0] c = {16{2’b01}} ; // 复制操作符 (左边的是高维[3:0],右边的是低维)
-
非压缩数组初始化
- 在声明时用
'{}
内的值序列进行初始化,'{
作为左定界符表明里面是表达式列表,而不是verilog表达式的拼接,括号的套数与数组的维数一致 - int d2[2][4] = '{2{7,3,0,5}} ; // 复制,复制操作符前无
’
- int d1 [2][4] = ‘{’{7,3,0,5},'{2,0,1,6}};
- 在声明时用
-
压缩数组的赋值: 压缩数组是向量,可以像verilog向量一样赋值
- 数组的一个元素
- 整个数组(向量)
- 整组的一部分
- 整数的一段(多个相邻的子域)
logic[1:0][1:0][7:0] a; a[1][1][0] = 1'b0; a = 32'hf1a3c5e7; a[1][0][3:0] = 4'hf; a[0] = 16'hface; a={16'hz,16'b0};// 拼接赋值
- 非压缩数组赋值
- 给一个元素赋值
- 给一个元素的1位或部分位赋值
- 用一个值序列给整个数组赋值
- 用一个值序列给数组的一段赋值
byte a[0:3][0:3]; a[1][0] = 8'h5; a = '{'{0,1,2,3},'{4,5,6,7},'{7,6,5,4}}; a[3] = '{'hf,'ha,'hc,'he}; a = '{default:'0} ; // 整个数组赋值 a[0] = '{default:4}; // 整租一段赋值
定宽数组的声明
- 只给出数据位宽即可;
- 可以通过在变量名后面指定维度的方式来创建多维定宽数组
- bit[63:0] d_array[128]; // 向量数组
- shortreal cosines [90]; //浮点数组
- typedef enum{Mo,Tu,We,Th,Fr,Sa,Su} Week_t;
- Week_t year[52]; // 自定义数组
// 定宽数组的声明: int lo_hi[0:15]; int c_style[16];
// 声明并使用多维数组 int array2 [0:7][0:3]; int arrays[8][4]; // 紧凑的声明 array2[7][3] =1;
-
定宽数组的初始化
- 初始化
- 无初始化的缺省值
- 四态缺省值:x
- 二态缺省值:0
-
常量数组
- 即一个单引号加大括号来初始化数组
int ascend[4] = '{0,1,2,3};
int descend[5];
descend='{4,3,2,1,0};
descend[0:2] = '{5,6,7};
-
数组操作- for和foreach
- for循环:需要$size() 返回数据位宽
- foreach循环
-
数组操作-复制和比较
- 复制
- SV可以引用整个数组或其中的一段元素,因此允许将整个数组或者数组特定维的内容复制到另一个数组,其限制是等号两边的数组必须有相同的维数、位数和类型
- 比较
- 仅限于等于或不等于
- 复制
-
同时使用位下标和数组下标(先是数组下标,后是位下标)
// 同时使用数组下标和位下标
initial begin
bit[31:0] src[5](数组下标) = '{5{5}};
$display (src[0], // 'b101或’d5
src[0][0], // 'b1
src[0][2:1] // 'b10
);
end
动态数组
- 在声明时使用空的下标
[]
- 这意味着数组的宽度不在编译时给出,而在程序运行时再指定;
- 最开始是空的,所以必须调用new[]操作符分配空间,同时在方括号中传递数组宽度
- 内嵌函数
- new()
- used to set or change the size of the array
- size()
- function int size()
- Note: The size method is equivalent to $length(addr.I)
- delete() // 用完给delete掉
- function void delete()
- empties the array,resulting in a zero-sized array
- 随机化(基本上用的是动态数组)
- 声明,加rand修饰符
- 带约束的随机
- new()
UVM支持的数组
- sarray 是静态数组
- array是动态数组 (典型场景用于transaction里,还有用在monitor,一般用于比对。)