基础

class sv_class;
//class properties
int x;
static byte no_pkts_created;

//method-1
task set(int i);
x = i;
endtask

//method-2
function int get();
return x;
endfunction

static function get_pkt_ctr();
$display("ctr=%d", no_pkts_created);
endfunction

function new();
this.x = x;
$display("pkt_id: %d", no_pkts_created);
no_pkts_created++;
endfunction

function sv_class copy(); // 深复制
copy = new();
copy.x = this.x;
return copy;
endfunction
endclass

// 实例化
module class_tb;

sv_class cls, cls2;


initial begin
cls = new(1); // 利用关键字new初始化
cls2 = new cls; // 浅复制,只会复制x的值
sv_class::get_pkt_ctr(); // static函数直接调用
end
endmodule

浅复制不会复制类中的类(内部类),而是共享同一片存储空间

和interface类似,class也可以使用参数化设计

//---- class ----
class packet #(parameter int ADDR_WIDTH = 32,DATA_WIDTH = 32);
bit [ADDR_WIDTH-1:0] address;
bit [DATA_WIDTH-1:0] data ;

function new();
address = 10;
data = 20;
endfunction
endclass

继承与多态

在sv的class中,可以使用extends继承父类

class parent_class;
bit [31:0] addr;

virtual function void display();
$display("parent");
endfunction
endclass

class child_class extends parent_class;
bit [31:0] data;

function void display();
$display("child");
endfunction
endclass

module inheritence;
initial begin
child_class c = new();
c.addr = 10;
c.data = 20;
$display("Value of addr = %0d data = %0d",c.addr,c.data);

parent_class p = c;
p.display(); // 输出child
end
endmodule

权限控制:

  • public: 默认值,不需要写public,使用super关键字可以访问父类成员
  • local:只有自己可以访问,子类无法访问
  • protected: 只有自己和子类可以访问

抽象类

  • 抽象类无法实例化,只能被继承
  • 抽象类可以包含只有一个原型的函数(纯虚函数)
virtual class BasePackt;
int id;
pure virtual function int send(bit[31:0] data);
endclass

constraints

constraints对成员变量的随机化进行一些约束,确保他们的随机值在这个范围之内

语法:

rand byte data;  
// 限制随机值在(0,5)之间
constraint data_cons{
data > 0
  data <5;
}
------------------------
constraint data_cons{
data inside {[0:3],[8:10]};
}
------------------------
int array = '{1,2,2,3,3,3,4,4,4,4}
constrain data_c {
data inside array;
}
--------------------------
constraint data_cons {
data dist {0, 2, [5: 10]};
}
---------------------------
constraint data_cons{
// 取得0的概率为 10 / (10 + 3 * 45)
data dist {0:=10,[1:3]:=45};
}
----------------------------
// 取得0的概率为10 / (10 + 45), 取得1的概率为(45 / 3) / (10 + 45)
constraint data_cons{
data dist {0:/10,[1:3]:/45};
}
-----------------------------
// 当data_flag > 2时,在[1: 3]之间取值
constraint data_cons{
(data_flag > 2) -> data inside {[1:3]};
  (data_flag <= 2) -> data inside {[4:6]};
}
等同于
constraint data_cons{
if(data_flag>2
data inside {[1:3]};
else
data inside {[4:6]};
}
----------------------------------
数组的约束
rand byte pload[];

constraint pload_cons {
foreach(pload[i]) {
pload[i] inside {[1:255]};
}
pload.sum < 1024;
pload.size() inside {[1:8]};
}

约束的开关:

  • 关闭某一个约束: module_name.constraint_name.constraint_mode(0)
  • 关闭一个模块内所有约束: module_name.constraint_mode(0)

约束的重载:

class my_transaction extends uvm_sequence_item;

rand bit crc_err;
rand bit sfd_err;

constraint crc_err_cons{
crc_err == 1'b0;
}
constraint sfd_err_cons{
sfd_err == 1'b0;
}

`uvm_object_utils_begin(my_transaction)
`uvm_field_int(sfd_err, UVM_ALL_ON | UVM_NOPACK)
`uvm_field_int(pre_err, UVM_ALL_ON | UVM_NOPACK)
`uvm_object_utils_end

function new(string name = "my_transaction");
super.new();
endfunction

endclass

class new_transaction extends my_transaction;
`uvm_object_utils(new_transaction)
function new(string name= "new_transaction");
super.new(name);
endfunction

// 重载约束
constraint crc_err_cons{
crc_err dist {0 := 2, 1 := 1};
}
endclass