SV学习笔记(五)

类的方法

        类中的程序也称为方法,也就是在类的作用域内定义的内部task或者function。

class Transaction;
	bit [31:0] addr,crc,data[8];
	function void display();
		$display("@%0t: TR addr = %h,crc = %h",$time,addr,crc);
		$write("\tdata[0-7]=");
		foreach (data[i]) $write(data[i]);
		$display();
	endfunction
endclass

class PCI_Tran;
	bit [31:0] addr,data;
	function void display();
		$display("@%0t: PCI: addr = %h,data = %h",$time,addr,data);
	endfunction
endclass

module class_tb;
	Transaction t;
	PCI_Tran pc;
	initial begin
		t = new();
		t.display();
		pc = new();
		pc.display();
	end
endmodule


# @0: TR addr = 00000000,crc = 00000000
# 	data[0-7]=         0         0         0         0         0         0         0         0 
# @0: PCI: addr = 00000000,data = 00000000

this是什么

        当你使用一个变量名的时候,SV将先在当前作用域内寻找,接着坐在上一级作用域内寻找,直到找到该变量为止。这也是Verilog所采用的算法。但是如果你在类的很深的底层作用域,却明确的引用类一级的对象呢?这个时候需要使用到this。

class Scoping;
    string oname;
    function new(string oname);
        this.oname = oname;        //类变量 oname = 局部变量 oname
    endfunction
endclass

在任务中修改句柄

        一个常见的编码错误是当你想修改参数的值的时候,忘记在方法的参数前ref关键词,尤其是句柄。参数tr没有被声明为ref,所以在方法内部对tr的修改不会被调用该方法的代码看到。参数tr默认的信号方向是input。

错误的事务生成任务,句柄前缺少关键词ref

function void creat(Transaction tr);    //错误,缺少ref
        tr = new();
        tr.addr = 42;
    ...
endfunction

Transaction t;
    initial begin
        creat(t);
        $display(t.addr);
    end

正确的事务发送器,参数是带有ref的句柄

function void creat(ref Transaction tr);
    ...
endfunction

在程序中修改对象

        在测试平台中一个常见的错误是忘记为每个事务创建一个新的对象。

错误的发生器,只创建了一个对象。

task generator_bad(int n);
        Transaction t;
        t = new();
        repeat (n) begin
            t.addr = $random();                    
            $display("sending addr = %h",t.addr);        //每次打印的addr随机
            transmit(t);                            //传输出去的addr相同
        end
endtask

正确的产生器,创建多个对象

task generator_bad(int n);
        Transaction t;
        repeat (n) begin
            t = new();
            t.addr = $random();                    
            $display("sending addr = %h",t.addr);        //每次打印的addr随机
            transmit(t);                            //传输出去的addr跟随打印的数据
        end
endtask

句柄数组

        在写测试平台的时候,可能需要保存并且引用许多对象。你可以创建句柄数组,数组的每一个元素指向一个对象。

task generator();
    transmit tarray[10];
    foreach (tarray[i])
        begin
            tarray[i] = new();        //创建每一个对象
            transmit(tarray[i]);
        end
endtask

对象的复制

        使用new复制一个简单类

class Transaction;
        bit [31:0] addr,crc,data[8];
endclass

Transaction src,dst;
initial begin
    src = new;            //创建第一个对象
    dst = new src;        //使用new操作符进行复制
end

这是一种简易复制,原对象的值被盲目地抄写到目的对象中。如果类中包含一个指向另一个类的句柄,那么只有最高一级的对象被new操作符复制,下层对象都不会被复制。

class Transaction;
		bit [31:0] addr,crc,data[8];
		static	int count = 0;
		int id;
		Statistics stats;
		
		function new;
			stats = new();
			id = count++;
		endfunction
endclass

Transaction src,dst;
	initial begin
		src = new();
		src.stats.startT = 42;
		dst = new src;
		dst.stats.startT = 96;
		$display(src.stats.startT)            //dst与src的startT值都指向96
	end

深层次复制函数是通过调用类所包含的所有对象的copy函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值