嵌入式技术
默认情况下,类的成员和方法可从外部访问使用类的对象句柄来访问,也就是说,它们是公共的。
如果我们不希望这样怎么办,即如何组织从外部访问类成员,防止外部其他类意外修改。
在大型项目中,我们可能使用外部提供的基类库(如UVM)。
1. 第三方基类库需要确保它们的用户不能意外修改基类中的成员和方法,目的就是防止对项目的其他部分产生连锁反应。
2. 另外,数据成员仅对拥有该成员的类自身可见也隐藏了实现细节,降低程序的复杂性和提高抽象级别。
用面向对象的语言来描述,就是封装(encapsulation)。
在Systemverilog中有两种语法可以实现安全的封装:local和protected。
local成员或者方法在类外部不可见,对其扩展类也不可见。只有包含这个成员的类的方法才可以访问这些local成员。
声明一个local成员或者方法的关键词是“local”
class packet; local int addr; //local property local function void disp(input int data); //local method $display("data = %h", data); $display("addr = %h", addr); //access local property endfunction endclass module class_TOP( ); initial begin packet p1; p1 = new( ); // p1.addr = 'hf; //COMPILE ERROR - can't access 'local' property // p1.disp(20); //COMPILE ERROR - can't access 'local' method end endmodule
在上面的例子中,class “packet”中声明了“local”属性 “addr”和一个local方法“disp”。
因为“addr”是一个 local成员,所以只能够使用类自身声明的方法“disp”访问,所以下面这个访问方式会导致编译错误:
p1.addr = ‘hff;
Error-[SV-ICVA] Illegal class variable access testbench.sv, 25 Local member 'addr' of class 'packet' is not visible to scope 'class_TOP'. Please make sure that the above member is accessed only from its own class properties as it is declared as local.
同理,由于我们将函数“disp”也声明成了local,所以无法从外部访问这个函数。所以下面的访问方式同样会报编译错误:
p1.disp;
Error-[SV-ICMA] Illegal class method access testbench.sv, 26 Local method 'disp' of class 'packet' is not visible to scope 'class_TOP'. Please make sure that the above method is called only from its own class properties as it is declared as local.
再看一个例子,扩展类遇到父类中的local成员。
class packet; local int addr; local function void disp(input int data); $display("data = %h", data); $display("addr = %h", addr); //access local property endfunction endclass class eth_packet extends packet; function set_addr; //addr = 'hf; //COMPILE ERROR - //can't access 'local' property from extended class endfunction function void eth_disp; //super.disp(50);//COMPILE ERROR - //can't access 'local' method from extended class endfunction function void disp(input int data); //OK to override 'local' method in extended class $display("From eth_packet data=%d", data); endfunction endclass module class_TOP( ); initial begin eth_packet e1; e1 = new( ); e1.disp(50); end endmodule
在上面的例子中,我们扩展自父类 “packet”,声明了一个扩展类“eth_packet.”
在类“eth_packet”中直接访问local成员和local方法都会发生编译错误。但是在扩展类中覆盖local成员和方法“disp”是允许的。事实上,方法覆盖之后,访问的已经不是父类中的那个local成员了。
打印log:
From eth_packet data= 50 V C S S i m u l a t i o n R e p o r t
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !