【SV课程学习Day6】


面向对象编程基础

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、面向对象(OOP)

  • 使用户能够创建复杂的数据类型,并且将它们跟这些使用这些数据类型的程序紧密结合在一起。
  • 在更加抽象的层次建立测试平台和系统级模型,通过调用函数来执行一个动作而不改变信号的电平
  • 测试平台跟设计细节分开,变得更加可靠,更加易于维护,更有利于重复使用

验证人员的主要都是集中在模块级别的验证,ST(SoC验证)和IT的人员相对较少。block的环境原则上是要复用的。

二、OOP术语

  • 类(class)包含变量和子程序(begin…end/always/task)的基本构建模块
  • 对象(object)类的一个实例
  • 句柄(handle):指向对象的指针
  • 属性(property):存储数据的变量(类里面的数据变量
  • 方法(method):任务(task)或者函数(function)中操作变量的程序代码
  • 原型(prototype)程序的头,包括程序名,返回类型和参数列表(实质就是程序的源代码)

插入一条重点知识:(面试常考点
1.对象应用上面关于深拷贝和浅拷贝;
2.UVM的callback,config_db

class(类)

  • 变量
  • 子程序
  • 定义在program,module,package中,或者在这些块之外的任何地方。

示例代码如下:

class Packet;
	//data or class properties 
	bit [3:0] command; 
	bit [40:0] address;
	bit [4:0] master_id;
	integer time_requested;
	integer time_issued;
	integer status;
	
	// initialization 
	function new();
		command = IDLE;
		address = 41’b0;
		master_id = 5’bx; 
	endfunction
	
	// methods 
	// public access entry points 
	task clean(); 
		command = 0; address = 0; master_id = 5’bx; 
	endtask
	task issue_request( int delay );
		// send request to bus 
	endtask
	function integer current_status();
		current_status = status; 
	endfunction
endclass

在这里插入图片描述
上图可以看出环境的基类是uvm_void类;并且可以在UVM中的定义可以看出uvm_void是空的,没有任何数据变量和方法的抽象类
在这里插入图片描述


对象(object)——类的一个实例

  • 数据包,是在运行中测试平台需要的时候才被创建
  • 激励对象不断地被创建并且用来驱动DUT,检查结果,最后这些对象所占用的内存可以被释放,以供新的对象使用
  • SV类在使用前必须先实例化
  • An object is used by first declaring a variable of that class type (that holds an object handle) and then creating an object of that class (using the new function)
    and assigning it to the variable
    使用对象首先声明该类类型的变量(包含对象句柄),然后创建该类的对象(使用new函数)并将其分配给变量

创建对象实例

  • Pack p;// declare a variable of class Packet(类先例化一个句柄)
  • p = new();// initialize variable to a new allocated object of the class Packet(句柄实例化之后创建对象,初始化给变量赋初值同时给它开辟空间,四态的默认初值为x,二态的初始值为0)

在这里插入图片描述
SV的句柄没有被实例化的话,它的值默认是空指针(null),SV编译器会对任何null的数据都会报空指针,这将会导致仿真中断。
SV中唯一支持的就是$cast.【子类$cast父类】

  • 空指针需要new的地方有两个
    1. 动态数组
    2. 对象

1. 对象new()

  • 分配内存
  • 初始化变量
    UVM中调用create,它的原型就是new
    在这里插入图片描述
    在这里插入图片描述
  • 声明和new分开(推荐)
    应该避免在声明一个句柄时调用构造函数,即new函数。虽然语法上是合法的。但会引起顺序问题,因为此时构造函数在第一条过程语句前就被调用了。希望按照一定顺序初始化对象,但如果在声明时调用了new函数,你就不能控制这个顺序了。
    此外,如果忘记了使用automatic存储空间,构造函数将在仿真开始时,而非进入块的时候被调用。
  • 对象new() 和new[]
    • new() : ** 创建一个对象**
    • new[]创建一个含有一个或多个变量的数组

2.句柄

  • 一次只能指向一个
  • 通过声明一个句柄来创建一个对象

3.属性(property):存储数据的变量

  • No net types(线网类型不允许放在类里面,因为线网类型没有办法编译)

net_type ::= supply 0 | supply 1|tri|triand|trior|tri0|tri1| wire| wand|wor

4.方法(method)任务或者函数中操作变量的程序代码

Packet p = new; // 这里是声明和创建放一起了
status = p.current_status();
实际代码推荐如下:在这里插入图片描述

【补充说明】

  • function里可以调用function,task里也可以调用function,但是function里调用task验证环境会报warning ,编译不会报错。对于验证工程师而言,所有的warning也是要消除的。

5.原型(prototype)程序的头,包括程序名、返回类型和参数列表

6.对象的解除分配(deallocation)

  • 一旦事物已经成功完成并得到统计结果,不需要再保留,回收内存,长时间的仿真会将内存耗尽
// 创建多个对象
Transaction t;// 创建一个句柄
t = new();// 分配一个新的Transaction
t = new(); // 分配第二个,并且释放第一个t (覆盖)
t = null;// 解除分配第二个  (清除句柄)

上面的代码通常放在monitor里,monitor的用法是从端口get到一个包(一般是一个类,transaction),driver把transaction发送转化为时序,通过bus 模型把这些信息发送给DUT,DUT把这些数据包处理完之后,这个transaction会在monitor里去采,采到的也是transaction,采到transaction以后去进行后续处理,处理之前要把它new一下,去给它做一些数据的转换,然后发到scoreboard进行数据比对。
第二个来了就是同样的句柄再new()一遍,它用的还是一块地址。这样的话,内存就是在不断地创建回收,创建回收。这样就不会内存耗尽。

静态变量和全局变量

  • 静态变量(staticc)
    - 被这个类地所有实例所共享,并且它的使用范围仅限于这个类
  • 全局变量(定义在类以外,谨慎使用全局变量,用的时候打上logo,带上你验证模块的名字)
    • 整个测试平台都可以访问
    • “污染”全局名字空间(name space)

    静态变量

    • 被这个类的所有实例所共享,并且它的使用范围仅限这个类
    • 可以使用句柄引用静态变量,可以使用类名加上::(类作用域操作符)
    • 通常在声明时初始化
    • SV不允许静态方法读写非静态变量

    实例

在这里插入图片描述
uvm_reporter是静态的,而且是protected的,所有的子环境都共享同一个uvm_reporter;不管你是在case里,monitor里也好,或者是在top里,所有的地方只要你用uvm_report的写法,它都会统计同一个count里去。这就是静态变量的意义所在。无论是IT,还是BT,如果你的环境是统一的,你在case也好,在组件也好,所有的report都会summary在一起。他们所有都会共享同一个uvm_report_server.

类之外定义方法
  • 声明在开始处添加关键词extern
  • 整个方法在类定义后面,并加上类名和::(作用域操作符)
    在这里插入图片描述
作用域(指的是哪些)
- module(harness是module)
- program
- task
- function
- begin...end
![在这里插入图片描述](https://img-blog.csdnimg.cn/1340d14d34e148c887f233484c93770d.png)
作用域解析运算符::
  • 用于显示的对标识符的命名空间做出解析:
  • class_scope::=class_type ::
  • 常见归类如下:
    • 包的使用,如import packets::*
    • 内建类调用函数,std::randomize()
    • class内部声明,外部定义
    • 对静态变量static variable静态方法static method的调用(用类::直接调用)
    • 对静态成员static member的调用
    • 调用randomize with{} 时使用local::identifier 重名的标识符做出区分 // 对特殊的case打上标签;做一个异常的case,强制修改crc的值,这个值通常是随机的,会挑一个位置强制修改,要把这个错误的位置告知我的scoreboard.通常告知就使用这个logo方法。在transaction里面做一些内容,这个内容是不确定的,需要相互传,但不推荐使用config_db的。一两个变量的话就使用sequence里的变量赋值到我的case里面的Logo,再用logo再去传给其他的。还有可能就是有多个sequence,多个端口给包打标签。
    • 派生类内部访问父类的Public 变量和方法
    • covergroup coverpoint cross的使用
    this
    • The this keyword is used to unambiguously refer to class properties or or methods of the current instance(对象访问类的原型)
    • 代表当前变量
    • The this keyword shall only be used within non-static class methods (this 关键字只能在非静态类方法中使用)
      在这里插入图片描述
super()
  • used from within a derived class to refer to members of the parent class(子类访问父类)
  • 必须放在子类第一行,否则会编译报错
    在这里插入图片描述
  • this 和 super
    • 一般对应,用来区分子类与父类的同名变量
class trans;
	string name;
	function display(output string name);
		name = this.name;
	endfunction
endclass
class trans_ex extends trans;
	string name;
	function display(output string name);
		name = super.name;
	endfunction
endclass
local
  • 和this 对应,protected
class mac_driver extends uvm driver#(mac_transaction);
	...
	int pre_num;
	local int pre_num_min;
	local int pre_num_max;
	function void build phase(uvm_phase phase)
		super.build(phase);
		pre_uvm_min = 3;
		pre_uvm_max = 7;
	endfunction
endclass

编译顺序问题

有时候你需要编译一个类,而这个类包含一个尚未定义的类,声明这个被包含的类的句柄将会引起错误,因为编译器还不认识这个新的数据类型,这时你需要使用typedef语句声明一个类名,如下例所示:

// use typedef
typedef class Statistics; // 定义低级别类
class Transaction;
	Statistics stats; // 使用Statistics类
	...
endclass

class Statistics; // 定义Statistics类
...
endclass

但是上述这个方法不推荐大家使用。

  • 编译顺序问题
    在这里插入图片描述

验证工程师招聘时重要的一条是会使用脚本,一般是makefile 或者perl脚本。

  • 编译顺序一般在makefile脚本里去定义。把脚本从前往后列一遍,这也就是编译顺序。
  • UVM的验证结构是从低到高去构建的,从下到上,写完sequence,driver,monitor,再写agent ,写完agent,再写scoreboard,reference model,从下到上。按这个顺序去写,如果反了,会出现类未定义。用typedef去解决类未定义的问题。编译顺序一般放在filelist,即编译顺序。
对象的应用
  • 修改句柄
    在这里插入图片描述
  • 修改对象
    在这里插入图片描述
    验证环境期望的是定向随机,是要随机化的,每次随机化产生不同对象。
    在这里插入图片描述
    随机一般是在uvm_do里面 ,先new再随机。
    先声明,告诉发送多少个(n),先new,再随机化。发送之前打一个标签,告诉你我要发数据了。
  • 句柄数组(UVM没有
    在这里插入图片描述

句柄复制

  • = (句柄赋值)

对象复制

  • 深拷贝
  • 浅拷贝
    • new(创建了一个新的对象,并且复制了现有对象的所有变量)
If,however,the example above is re-written as shown below ,a  copy of p1 shall be made:
	Packet p1;
	Packet p2;
	p1 = new;
	p2 = new p1;
深复制
  • 不仅仅会拷贝当前b的对象的成员变量,还会拷贝b实例中a句柄的对象内容,即进行深层次的复制。
  • 浅拷贝
    • 只会拷贝b对象中的成员变量A1,B1的句柄a,而不会拷贝句柄a所指向的对象中的内容;
      如果类里面没有其他句柄,深拷贝浅拷贝没有区别。
      没有类里面有别的类的句柄(类的嵌套),
      这两者才会有差别。
    • 对象深拷贝
      在这里插入图片描述

数据pack和unpack

在这里插入图片描述

在这里插入图片描述

Class and structures(类与结构体的差别)

  1. SystemVerilog struct are strictly static objects; they are created either in a static memory location
    (global or module scope) or on the stack of an automatic task. Conversely, SystemVerilog objects (i.e.,
    class instances) are exclusively dynamic, their declaration doesn’t create the object; that is done by calling
    new.
  2. SystemVerilog structs are type compatible so long as their bit sizes are the same, thus copying structs of
    different composition but equal sizes is allowed. In contrast, SystemVerilog objects are strictly stronglytyped. Copying an object of one type onto an object of another is not allowed.
  3. SystemVerilog objects are implemented using handles, thereby providing C-like pointer functionality. But,
    SystemVerilog disallows casting handles onto other data types, thus, unlike C, SystemVerilog handles are
    guaranteed to be safe.
  4. SystemVerilog objects form the basis of an Object-Oriented data abstraction that provides true
    polymorphism. Class inheritance, abstract classes, and dynamic casting are powerful mechanisms that go
    way beyond the mere encapsulation mechanism provided by structs.
  • 结构体是静态的,里面是纯数据类型,没有task,没有function。
  • 类是可以支持task和function的
  • 结构体声明的时候空间就给他创建好了,我们对象是要动态创建,来一个创建一个,用完就是释放。
  • 类可以封装,继承,多态,扩展了很多功能。
  • 结构体可以用于DPI接口;SoC里面的核都是用C语言。UVM跟C语言是无法通讯的,需要用到DPI接口,DPI的核心就是将类转换成数据结构;
  • 对于纯数字芯片验证,就只是UVM和SV。目前芯片越做越大,SoC越来越明显,SoC必定会接触C语言的,存在SoC与C语言的转换。SoC验证并不是验证主体。DV验证更多都是模块级验证。
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值