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的更多相关文章

  1. 不会JS中的OOP,你也太菜了吧!(第二篇)

    一.你必须知道的 1> 原型及原型链在继承中起到了关键的作用.所以你一定要理解他们.2> 不会JS中的OOP,你也太菜了吧!(第一篇) 二.继承的6种方法 1> 原型链继承 原型链继 ...

  2. oc中的oop基础及类的基本介绍

    面向对象的(OOP)的基础知识 类(class):表示一组对象数据的结构体,对象通类来得到自身.类名首字母大写. 对象(objcet):是一种包含值和指向其类的隐藏指针的结构体.运行中的程序中通常会有 ...

  3. SV中的随机化

    SV搭建testbench的关键概念:CRT(constraint random test),测试集的随机化. 由于对象class由数据和操作组成,所以对数据的随机化一般放在一个class内.(对环境 ...

  4. SV中的线程

    SV中线程之间的通信可以让验证组件之间更好的传递transaction. SV对verilog建模方式的扩展:1) fork.....join 必须等到块内的所有线程都执行结束后,才能继续执行块后的语 ...

  5. SV中的Interface和Program

    Interface:SV中新定义的接口方式,用来简化接口连接,使用时注意在module或program之外定义interface,然后通过'include来添加进工程. interface  arb_ ...

  6. SV中的task和function

    SV中class的properties和methods默认都是public的,但是可以声明为local和protected. 一个properties声明为local类型的,则只在该class中的me ...

  7. SV中的数据类型

    Verilog-1995中规定的数据类型有:变量(reg), 线网(wire), 32位有符号数(integer), 64位无符号数(time), 浮点数(real). SV扩展了reg类型为logi ...

  8. Python3中面向对象 OOP

    Python3中面向对象 OOP 定义: python中通过关键字 class 实现类的定义: class ClassName(object): pass 获取成员变量:ClassName.变量名 修 ...

  9. 小结JS中的OOP(下)

    关于JS中OOP的具体实现,许多大神级的JS专家都给出了自己的方案. 一:Douglas Crockford 1.1 Douglas Crockford实现的类继承 /** * 原文地址:http:/ ...

随机推荐

  1. 禁用ngen版本的.NET Framework dll加载

    在调试时会发现出于性能考虑.NET Framework dll加载的都是ngen版本,比如:System.dll,实际加载System.ni.dll. 如果希望加载非ngen版本,可以设置系统环境变量 ...

  2. Spring Boot 利用插件构造QueryDSL语句时报错:You need to run build with JDK or have tools.jar on the classpath.If this occur....

    You need to run build with JDK or have tools.jar on the classpath.If this occures during eclipse bui ...

  3. 9.7 Django

    2018-9-7 14:37:35 这次是 图书  出版社  作者 的连表 2018-9-7 16:56:36

  4. 8.31前端 jQuery

    2018-8-31 19:52:09 周末吧这几天课看完 结束前端!然后进行Django!!! 越努力,越幸运! day56 2018-03-16 1. 内容回顾 1. 样式操作 1. 操作class ...

  5. 使用pidstat监控资源使用

    linux可以使用pidstat命令监控系统资源,比如监控cup使用如下: pidstat -u 还可以使用 -r(内存) -d(硬盘)

  6. 关于keyGenerator,KeyPairGenerator,SecretKeyFactory的解析

    Java加密的常用的加密算法类型有三种 1单向加密:也就是不可逆的加密,例如MD5,SHA,HMAC 2对称加密:也就是加密方和解密方利用同一个秘钥对数据进行加密和解密,例如DES,PBE等等 3非对 ...

  7. hdu1166 敌兵布阵【线段树】

    C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于 ...

  8. hue安装及基本测试-笔记

    #################################################################################################### ...

  9. 通过微信服务号推送Zabbix告警

    近期看到一篇通过微信实现Zabbix告警的文章,但实践时发现,无法成功发送消息. 分析原因,应该是微信公众平台加强了登录验证,在登录时会需要管理员进行扫描二维码操作才能成功登陆后台: 而之前文章中的A ...

  10. TensorFlow基础1:reduce_sum()函数和reduce_mean()函数

    https://blog.csdn.net/chengshuhao1991/article/details/78545723 在计算损失时,通常会用到reduce_sum()函数来进行求和,但是在使用 ...