前言
在我的上一篇博客中,你已经学习了如何创建具有静态属性的类。这类变量的作用类似于全局变量,因为无论你创建多少个对象,都仅存在一个副本。这篇展示了如何创建访问那些静态属性的方法。
方法
任何类方法都可以读取和写入这些静态属性,就像动态属性一样。但是,如果将方法声明为静态方法,则可以调用该方法而无需构造对象。以下示例是带有静态方法的Thing类,用于打印Thing对象的数量。即使没有构造Thing对象,也可以调用Thing :: print_count()。
class Thing;
int id; // Dynamic, unique to each object
static int count; // Static, associated with the class
static function void print_count();
$display(“Thing::count = %0d.”, count);
endfunction
// The rest of the class
endclass
静态方法只能访问静态属性。请记住,静态属性的作用就像全局变量,因为它始终存在。动态属性存储在对象中。 id属性仅存在于单个对象中,因此print_count()无法看到它。
这是一个简单的错误处理类,该类跟踪已打印的错误消息数,并在达到最大值时退出。请注意,没有创建ErrorH句柄或对象。复制这段代码,然后在模拟器上尝试一下。
class ErrorH;
static int count=0, max_count=10;
static function void print(input string s);
$error(s);
if (++count >= max_count) begin
$display("*** Error max %0d exceeded", max_count);
$finish(0);
end
endfunction
static function void set_max_count(input int m);
max_count = m;
endfunction
endclass
initial begin
ErrorH::set_max_count(2); // Limit the number of errors
ErrorH::print("one");
ErrorH::print("two - should end sim");
ErrorH::print("three - should not print");
end
更多小技巧
uvm_config_db类是基于静态方法构建的,因此你需要使用以下语法进行调用。
uvm_config_db::set(...)
uvm_config_db::get(...)
如果没有静态方法,则必须构造一个数据库(DB)对象,并将其句柄传递到测试平台的每个角落。这违反了简化配置信息共享的整个目标。
这部分没有特意展示。期待在即将发布的博文中发现更多详细信息。
前言
与传统的面向过程的编程相反,使用面向对象(Object Oriented Programming,OOP)的编程来创建测试平台的优点之一是,你的数据和代码包含在一个类中,从而减少了对全局变量的需求。这些很有用,但是你需要谨慎使用它们以限制访问它们的方式,从而避免数据损坏。另外,你需要为全局变量创建唯一的名称,以避免冲突。是否有一种OOP方法可以使一个变量可以跨多个类访问并解决命名问题?
对象计数
当你调试带有多个对象的代码时,为每个对象使用唯一的名称或ID十分方便,因此你可以轻松地在系统中跟踪它们。那该如何自动设置ID呢?你可以用一个全局变量来计这种类型的对象的数量,但是你试图避免使用全局变量。 OOP解决方案是一个静态变量,其中的存储与类声明相关联,而不是与动态构造的多个对象相关联。
class Thing;
int id; // Dynamic, unique to each object
static int count; // Static, associated with the class
function new();
id = count++; // Initialize ID, update count
endfunction
// The rest of the class
endclass
每次构造新对象时,其ID都会获取当前计数,然后计数增加。 count属性保存创建的对象数。由于此属性是静态的,因此即使没有创建任何对象,该属性也存在。下面显示的冒号-语法称为作用域解析运算符,它表示要在名称空间Thing中查找名称计数。
Thing t0, t1, t2;
initial begin
// Print the count, before any objects constructed
$display("count=%0d. before", Thing::count);
t0 = new();
// Print count after the first object constructed
$display("count=%0d. after", Thing::count);
t1 = new();
t2 = new();
end
下图展示了刚才创建对象的过程。静态计数属性与该类相关联,并且仅存在一个副本。句柄t0,t1和t2指向单独的对象,每个对象都有单独的存储空间和唯一的id值。
局部全局变量
啊哈-你刚刚创建了一个“全局”变量count,该变量保存到目前为止创建的Thing对象的数量,但对于Thing类而言是“本地”的。用OOP的术语,你可以说该属性在Thing类的名称空间中。
每个类都有其自己的名称空间,因此Thing类中称为“ count”的属性不会与另一个类中的“count”冲突。每个类都可以有自己的计数变量,如果用全局变量来完成,则不会造成任何混乱。
SystemVerilog允许你创建参数化的模块和类。这使它们更加灵活,并且能够处理多种数据类型,而不仅仅是一种。此概念已在UVM中广泛使用,尤其是利用uvm_config_db来配置数据库。你可以自己动手尝试下面这些示例。
按值参数化
让我们从一个简单类——比特位向量开始。该类具有向量宽度的参数。 (良好的编程习惯是始终为你的参数设置默认值。)
class Vector #(parameter WIDTH=1);
bit [WIDTH-1:0] data;
endclass
现在,你可以为具有各种宽度的向量的类声明句柄。
Vector v1; // Default: data width=1
Vector #(8) v8; // 8-bit data
Vector #(.WIDTH(16)) v16; // 16-bit data
initial begin
v1 = new();
$display("v1 ", $typename(v1.data)); // v1 bit[0:0]
v8 = new();
$display("v8 ", $typename(v8.data)); // v8 bit[7:0]
end
每次你指定一个值时,实际上就是在创建一个新类。因此,你可以想象上面包含v8的那行实际上创建了以下类声明。
class Vector__8;
bit [8-1:0] data;
endclass
v1,v8和v16句柄类型不兼容,因为它们分别用于单独的类Vector_1,Vector_8和Vector_16。即使使用$ cast(),也无法在这些句柄之间进行赋值。
按类型参数化
假设你的老板要求你在SystemVerilog中为堆栈编写公用类。你可能会想到这样的事情。
class Stack;
int items[64], idx=0;
function void push(input int val);
items[idx++] = val;
endfunction
function int pop();
return items[idx--];
endfunction
endclass
你写的类如此受欢迎,以至于你项目中的其他人要求你提供字节堆栈,实数值堆栈等等。无需编写几十个新类,只需修改你的旧类即可。 push()和pop()的代码保持不变,只需适用于其他类型。
class Stack #(parameter type T=int);
T items[64], idx=0;
function void push(input T val); …
function T pop(); …
endclass
Stack int_stack; // Default: Stack of ints
Stack #(bit[7:0]) byte_stack; // Stack of 8-bit values
Stack #(real) real_stack; // Stack of real values
再者,这三个声明实际上创建了三个新类。因此,这些句柄类型不兼容。
当然,你本可以告诉老板使用System Verilog的队列数据类型,但是这样做的还有什么乐趣呢?
更多小技巧
类标题中的关键字“parameter”是可选的。
参数名称采用大写以表示它不是变量。
当我第一次学习UVM时,有很多事情让我感到困惑。在修完UVM课程之后,还有什么模糊的地方?
这里有一个图表,展示不同测试平台层次,其中橘色表示事务从测试级序列流入代理项。
想查看更多SystemVerilog和UVM提示吗?报名参加我即将举行的网络研讨会"UVM编码指南:你可能不知道的提示和技巧。"
享受你的验证旅程!
原文链接:https://blogs.mentor.com/verificationhorizons/blog/author/cspear/
点击【阅读原文】可直达课程页面,马上试听
往期精彩:
V2Pro春季班普遍学撑了,秋季班7月报名你还敢来么
30w+还送股送房?60+IC企业2019薪资全面攀升!
UVM RAL模型:用法和应用
我们准备做第二期线下培训,依旧认真且严肃
如果你突然被裁员了,你的Plan B是什么?
[彩虹糖带你入门UVM]
理解UVM-1.2到IEEE1800.2的变化,掌握这3点就够