1、测试平台的构建

  发生器(generator):创建事务并且将它们传给下一级

  驱动器(drive):与设计进行会话

  监视器(monitor):捕获设计返回的事务

  计分板(scoreboard):将捕获的结果跟预期的结果进行对比

  测试平台应该分成若干个块(block),然后定义它们相互之间如何通信。

2、OOP(Object-Oriented Program)

  类(class)、对象(object)、句柄(object)、属性(property)、方法(method)、原型(prototype)

3、类定义的位置

  类应当在program或者module外的package中定义,将临时变量在测试平台最内部的某处定义。

4、创建对象

  方法:创建一个指向目标类对象的句柄,然后调用new()函数。

  对象和句柄:句柄可以在不同的时间指向不同的对象

5、对象的接触分配

  SV分辨对象不再被引用的最好办法就是记住指向它的句柄的数量,当最后一个句柄不再引用某个对象了,SV就释放该对象的空间。

6、使用对象

  方法:用“.”操作符

7、静态变量和全局变量

  每个对象都有自己的局部变量,这些变量不和任何其他对象共享。而使用静态变量就可以被所以对象所共享。

8、静态函数

  没有创建类对象就可以执行,不允许读写非静态变量。调用静态函数:类名::方法名

9、类的方法

  在类的作用域内定义的内部task或者function。SV会根据句柄的类型调用正确的display()方法。

10、将对象传递给方法

  如果要在任务或者函数中修改句柄,则必须将该任务或函数声明为automatic,并且对象加ref

11、对象的复制

  可以使用new操作符,但这样是简易复制(shallow copy),类似于原对象的一个影印本,原对象的值被盲目地抄写到目的对象中。如果类中包含一个指向另一个类的句柄,那么只有最高一级的对象被new操作符复制,下层的对象都不回被复制。更推荐的做法是编写自己的复制函数:为每个类构建复制函数,并在其中继续调用对象成员的复制函数。

  

SOA和面向对象的架构 sv面向对象_操作符

 

 

 

12、公有和私有

  在SV中,所以成员都是公有的,除非标记为local或者protected。应该尽量使用默认值,以保证对DUT行为的最大程度的控制

13、建立一个测试平台

SOA和面向对象的架构 sv面向对象_操作符_02

  图中的Generator、Agent、Drive、Monitor、Checker和Scoreboard都是类,被建模成事务处理器(transactor)。事务处理器由一个简单的循环构成,这个循环从前面的块接受事务对象,经过变换后送给后续块。

14、示例代码

package,包含类的定义

package class_package;
        typedef class Statistics;
        class Transaction;
                Statistics stats;  //对象成员
                bit [31:0] addr,crc,data[8];  //默认公有
                static int count = 0;  //静态变量
                int id;
                
                function new(logic [31:0] a=3,d=5);
                        addr = a;
                        foreach (data[i])
                                data[i] = d;
                        id = count++;
                        stats = new(); // 调用对象成员的构造函数

                endfunction:new

                function Transaction copy;  // 复制函数
                        copy = new();
                        copy.addr=addr;
                        copy.crc=crc;
                        copy.data=data;
                        copy.stats=stats.copy(); //调用对象成员的复制函数
                endfunction

                function void display();
                        $display("addr:%h",addr);
                endfunction:display
                
                static function void static_f();
                    $display("count:%h",count);
              endfunction:static_f

        endclass:Transaction

        class Statistics;
                time startT;
                function new();
                    startT = 1;
                endfunction:new

                function Statistics copy(); //复制函数
                    copy=new();
                    copy.startT=startT;
                endfunction
        endclass:Statistics

endpackage

program:

import class_package::*;
//将对象传递给方法
function automatic void create(ref Transaction tr); 
        //在方法中改变了句柄,因此必须加ref
        tr = new();
        tr.addr = 42;
endfunction

program test;
        initial begin
            Transaction tr1,tr2,tr3,src,dst;
            tr1 = new();
            tr2 = new();
            create(tr3); //将对象传递给方法
            tr1.display();
            tr2.display();
            tr3.display();
            $display("Second object id = %0d,count = %0d",tr2.id,Transaction::count);
            Transaction::static_f();

            //使用new复制对象
            src = new();
            src.stats.startT = 42;
            dst = new src;
            dst.stats.startT = 96;
            $display("========= dst = new src ==========");
            $display("shallow copy - src.stats.startT:%0d",src.stats.startT); //96      因为src和dst的stats都指向同一个对象

            $display("shallow copy - dst.stats.startT:%0d",dst.stats.startT); //96
            $display("shallow copy - src.id:%0d",src.id); //    3
            $display("shallow copy - dst.id:%0d",dst.id); //    3

            //使用copy函数复制对象
            dst = src.copy;
            dst.stats.startT = 48;
            $display("========= dst = src.copy ==========");
            $display("shallow copy - src.stats.startT:%0d",src.stats.startT); //96,没有被改成48
            $display("shallow copy - dst.stats.startT:%0d",dst.stats.startT); //48
            $display("shallow copy - src.id:%0d",src.id); //    3
            $display("shallow copy - dst.id:%0d",dst.id);    //    4

                 

            #50;
            $display("End of test");
        end

endprogram

输出:

# addr:00000003
# addr:00000003
# addr:0000002a
# Second object id = 1,count = 3
# count:00000003
# ========= dst = new src ==========
# shallow copy - src.stats.startT:96
# shallow copy - dst.stats.startT:96
# shallow copy - src.id:3
# shallow copy - dst.id:3
# ========= dst = src.copy ==========
# shallow copy - src.stats.startT:96
# shallow copy - dst.stats.startT:48
# shallow copy - src.id:3
# shallow copy - dst.id:4
# End of test