• 05-SV面向对象编程基础


    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操作符复制,下层的对象都不回被复制。更推荐的做法是编写自己的复制函数:为每个类构建复制函数,并在其中继续调用对象成员的复制函数。

      

    12、公有和私有

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

    13、建立一个测试平台

      图中的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

  • 相关阅读:
    Flask 中的路由系统
    Flask 中内置的 Session
    Flask中的模板语言jinja2
    Flask 中的 5种返回值
    Redis快速入门
    动态实现前后台分页、翻页按钮、上一页、下一页、首页、末页
    bus.js非父子组件之间通讯
    vue中父子组件之间相互传值
    js实现加减乘除
    禁用微信分享
  • 原文地址:https://www.cnblogs.com/wt-seu/p/12269576.html
Copyright © 2020-2023  润新知