SV中的OOP
OOP:Object-Oriented Programming,有两点个人认为适合验证环境的搭建:1)Property(变量)和Method(function/task)的封装,其实是BFM模型更方便的应
用。2)继承(Inheritance)与合成(Composition)非常适合一个架构的搭建。
在SV中,类可以定义在program, module, package中,但是一般一个类或几个相关的类会单独写在一个文件中。最终在program中调用。而且在SV中,所有成员
默认都是public类型的,除非显示的用local/protected来声明。实际上,SV class中的变量应该尽可能的用public并且rand,来增加可控性。
local/protected都可以针对property和method来说明,local表示member只对该class的对象可见,extend出的subclass也是不可见的。
但是该class中non-local的method调用了local的method或者property,
inherit之后的method也是可以正常执行的。
protected表示member对该class和它的subclass都是可以见的。 对外部的大环境不可见。
基类的指针可以直接指向扩展类的对象,但是只能调用扩展类中基类的那一部分,
基类的指针也可以直接转换为扩展类的指针,通过$cast函数,此时的基类指针指向的已经是扩展类对象,通过cast,转变为扩展类指针,可以调用扩展类中自有的元素。
SV默认会为每个类创建一个new函数,并初始化对象(二值变量为0,四值变量为X)。用户一般自定义new函数赋初值,分配空间可以交给SV来做。
显式的释放一个句柄指向的对象的空间 tr=null。
在SV中可以用关键字(Static)创建静态变量,可以让类有一个类级别的全局变量。一般子初始化时即赋值,还可以建一个静态的方法,来单独的操作静态变量。静态变
量可以通过类名::变量名的方式来引用。类中的其他变量都默认是automatic的修饰符,而且可以通过this.变量名,来直接调用类一级别的变量。在类的外
部定义方法时,可以用关键字extern来在类中声明,后在类外通过类名::方法名的方式来定义。
当类作为一个function的传递参数时,此时不加ref传递的是一个句柄的复制量。在下边的例子中,tr只有一个t的句柄的复制量,所以是Null,之后tr的改变和t没有直
接关系。
Transaction t; function void create(Transaction tr);
initial begin tr = new ();
creat(t); tr.addr = 42;
$display(t.addr); endfunction
end
一个对象的复制,可以通过简单的new函数来实现,也可以通过一种自定义的copy函数来实现,这种实现方式在类包含中,很适用。
new函数,当要复制的对象中还包含另一个类的对象时,会直接复制另一个对象的所有东西,包括id,句柄。
Transaction src, dst; function Transaction copy
initial begin copy = new();
src = new; copy.addr = addr;
dst = new src; copy.stats = stats.copy();
end endfunction
copy函数,在每一个类中都定义,在使用时,递归调用。这是id号都会刷新,而且因为对象都是new来构造出来的,所以更符合设计意图。
在一个类中例化另一个类(Composition),这时对方法的调用:ststs.startT.function,为了确保在编译时,不会因为编译顺序而造成某个类还不能被识别,可以在文
件开头加 typedef class Statistics, 来先声明类Statistics。而且此时外层类的new函数中,必须包含内层类的new函数。这种composition的结构非常适合
去构建一个大的验证框架,因为它可以将各个部分联系起来。
类的继承(Inheritance),扩展类拥有基类的一切变量与方法,在扩展类中调用基类的变量与函数,可以通过super.+变量/方法来调用。在扩展类的构造函数中,应该
先对基类先进行new函数。在扩展类的对象中调用对象时,SV比较句柄的类型来决定调用的是基类function还是扩展类function。但是当function是virtual
类型时,SV会根据对象的类型来决定调用基类function还是扩展类function。推荐在需要扩展的基类中使用virtual function的形式,这样符合OOP的多
态概念,也有利于向下转换。
class Transaction; class extends Transaction;
rand bit [31:0]src,dst,data[8]; rand bit bad_crc;
bit [31:0]crc; virtual function void calc_crc();
virual function void cal_crc(); super.calc_crc();
crc = src^dst^data.xor; if(bad_crc) crc = ~crc;
endfunction endfunction
endclass: Transaction endclass:Badtr
Transaction tr;
Badtr bad;
initial begin
tr = new ();
tr.calc_crc (); //调用基类类型
bad = new();
bad.calc_crc (); //调用扩展类类型
tr = bad; //基类句柄可以直接指向扩展类对象
tr.calc_crc (); //由对象类型来决定,所以调用BadTr.calc_crc
$cast(bad , tr); //将指向扩展类对象的基类句柄指向扩展类句柄。只有这种情况下,可以成功,$cast非零
bad.calc_crc (); //由对象类型决定,所以调用BadTr.cac_crc
end
BluePrint pattern:其实是类的继承在可重用验证环境中的一种典型用法。以Transaction为例,定义一个Transaction的基类,然后再定义一个Transaction的扩展
类,然后在顶层Test中,指定Generator需要哪一个Transaction。其实和UVM中的sequencer调用sequence如出一辙。
class Generator; class Environment;
mailbox gen2drv; Generator gen;
Transaction tr; Driver drv;
function new (input mailbox gen2drv) mailbox gen2drv;
this.gen2drv = gen2drv; function void build; //new函数的构建,mailbox, drv, gen
tr = new(); task run();
endfunction task wrap_up() ;
task run; endclass
Transaction tr1;
forever begin
assert(tr.randomize() );
tr1 = tr.copy(); //copy一份到driver
gen2drv.put (tr1);
end
endtask
endclass
program automatic test;
Environment env;
initial begin
env = new();
env.build(); //new函数
begin
BadTr bad = new();
env.gen.tr = bad; //通过类的顶层关系来调用,Transaction的替换。
end
env.run();
env.wrap_up();
end
endprogram
CallBack:在顶层中定义一个Task,在Driver中调用。便于直接添加task,并且因为是在顶层,所以更好针对项目来定制。
class Driver;
Driver_cbs cbs[$]; //用于存放扩展类的句柄,这个扩展类可以使driver也可以是scoreboard,只要是需要回调的。
task run();
bit drop;
Transaction tr;
forever begin
drop = 0;
agt2drvget(tr);
foreach (cbs[i]) cbs[i].pre_tx(tr, drop); //前回调
if(!drop) continue;
transmit (tr); //最基本的driver就负责一种发送transaction
foreach (cbs[i]) cbs[i].post_tx(tr); //后回调
end
endtask
class Driver_cbs_drop extends Driver_cbs;
scoreboard scb;
virtual task pre_tx (ref Transaction tr, ref bit drop) //从一个纯虚类继承而来,之所以使用纯虚类,为了能够重载
scb.save_expected (tr); //与scoreboard连接起来,
drop = ($urandom_range (0,99) == 0); //随机丢掉一个transaction
endclass
program autmatic test; class Scoreboard;
Environment env; Transaction scb[$];
initial begin function void save_expect (input Transaction tr)
env= new(); function void compare_actual( input Trans.. tr)
env.build(); enclass //一个简单的scoreboard模型
begin
Driver_cbs_drop dcd = new();
env.drv.cbs.push_back(dcd); //在顶层加入一个task
end
end
endprogram
纯虚类和纯虚方法:只为继承的基类和方法。纯虚方法+pure声明,只需要定义一个prototype,并且只能在纯虚类中定义,必须继承才能使用。同样纯虚类,可以定
义非纯虚方法,但是还是必须继承才能例化。
virtual class BaseTr;
static int count;
int id;
function new();
id = count ++;
endfunction
pure virtual function bit compare(input BaseTr to);
pure virtual function BaseTr copy(input BaseTr to = null)
endclass
还有一个问题:在基类中定义虚方法时,copy函数可以进一步优化。因为虚函数在基类和扩展类中,必须参数一致,返回类型一样,所以建议将copy_data单独分出
来。copy_data中传入指向扩展对象的指针,copy函数内进行new。copy的返回类型可以是基类指针,所以也可以是扩展类对象。
class BadTr extends Transaction
rand bit bad_crc;
virtual function void copy_data(input Transaction tr);
BadTr bad;
super.copy_data(tr); //这样返回的还是基类句柄,因为copy_data是virtual function
$cast(bad,tr)
bad.bad_crc = bad_crc; //此处返回的应该是基类指针,也可以是扩展类对象
endfunction
。。。。。。。
virtual function void copy(input Transaction1 to == null); //新的copy函数,更加健壮
BadTr bad;
if(to == null)
bad = new();
else bad = to;
copy_data(bad); //扩展类对象。
return bad;
endfunction
基类句柄可以直接指向扩展类对象,此时基类的句柄可以赋值给扩展类的句柄$cast(base,extends),来访问扩展类中的变量。
如果基类句柄没有指向扩展类对象,那这个复制会报错。
SV中的OOP的更多相关文章
- 不会JS中的OOP,你也太菜了吧!(第二篇)
一.你必须知道的 1> 原型及原型链在继承中起到了关键的作用.所以你一定要理解他们.2> 不会JS中的OOP,你也太菜了吧!(第一篇) 二.继承的6种方法 1> 原型链继承 原型链继 ...
- oc中的oop基础及类的基本介绍
面向对象的(OOP)的基础知识 类(class):表示一组对象数据的结构体,对象通类来得到自身.类名首字母大写. 对象(objcet):是一种包含值和指向其类的隐藏指针的结构体.运行中的程序中通常会有 ...
- SV中的随机化
SV搭建testbench的关键概念:CRT(constraint random test),测试集的随机化. 由于对象class由数据和操作组成,所以对数据的随机化一般放在一个class内.(对环境 ...
- SV中的线程
SV中线程之间的通信可以让验证组件之间更好的传递transaction. SV对verilog建模方式的扩展:1) fork.....join 必须等到块内的所有线程都执行结束后,才能继续执行块后的语 ...
- SV中的Interface和Program
Interface:SV中新定义的接口方式,用来简化接口连接,使用时注意在module或program之外定义interface,然后通过'include来添加进工程. interface arb_ ...
- SV中的task和function
SV中class的properties和methods默认都是public的,但是可以声明为local和protected. 一个properties声明为local类型的,则只在该class中的me ...
- SV中的数据类型
Verilog-1995中规定的数据类型有:变量(reg), 线网(wire), 32位有符号数(integer), 64位无符号数(time), 浮点数(real). SV扩展了reg类型为logi ...
- Python3中面向对象 OOP
Python3中面向对象 OOP 定义: python中通过关键字 class 实现类的定义: class ClassName(object): pass 获取成员变量:ClassName.变量名 修 ...
- 小结JS中的OOP(下)
关于JS中OOP的具体实现,许多大神级的JS专家都给出了自己的方案. 一:Douglas Crockford 1.1 Douglas Crockford实现的类继承 /** * 原文地址:http:/ ...
随机推荐
- java.lang.NoClassDefFoundError: Could not initialize class xxx 原因
一.问题及原因 程序里有个工具类,主要是调用它的静态方法来发送mq. 调用场景如下: 结果这两天报了个错: java.lang.NoClassDefFoundError: Could not init ...
- rc.sysinit 解析
$# :它可抓出 positional parameter 的數量,即脚本后面的参数有几个 $@和$*表示全部参数,但不包含脚本名,即$0,如果在command line上跑 my.sh p1 “p2 ...
- 跟bWAPP学WEB安全(PHP代码)--PHP代码注入
---恢复内容开始--- 背景 今天我们换一个方式来分析这个漏洞,从渗透的角度去搞. 渗透过程 测试漏洞 先来看看,观察URL是:http://192.168.195.195/bWAPP/phpi.p ...
- 【BZOJ2310】ParkII 插头DP
[BZOJ2310]ParkII Description Hnoi2007-Day1有一道题目 Park:给你一个 m * n 的矩阵,每个矩阵内有个权值V(i,j) (可能为负数),要求找一条回路, ...
- [APP] Android 开发笔记 006-使用短信验证SDK进行短信验证
1. 下载SDK (http://www.mob.com/#/download) SMS For Android Studio: http://www.mob.com/download/sms/and ...
- Android aapt使用小结
Android打包成Apk后,其实是一个压缩文件,我们用winrar打开也能看到里面的文件结构.还能看到AndroidManifest.但是里面的内容有点问题. 不知道是因为加密还是Android就是 ...
- css如何设置label的字间距
css.html如何设置label的字间距 .myClass label{ letter-spacing: 10px; } 如果label需要居中,需加上 text-indent: 10px; 首行 ...
- pandas category数据类型
实际应用pandas过程中,经常会用到category数据类型,通常以string的形式显示,包括颜色(红,绿,蓝),尺寸的大小(大,中,小),还有地理信息等(国家,省份),这些数据的处理经常会有各种 ...
- poj3304 Segments【计算几何】
C - Segments POJ - 3304 最近开始刷计算几何了 公式好多完全不会 数学不行 几何不行 记忆力不行 当机 查的题解 就当复习吧 这套专题拿来熟悉一下计算几何模板 #include ...
- MapReduce计算之——hadoop中的Hello World
1. 启动集群 2. 创建input路径(有关hadoop 的命令用 "hadoop fs"),input路径并不能在系统中查找到,可以使用 “hadoop fs -ls /” ...