一、合成和继承
在将两个相关联的类组合到一起的方面,合成使用了“有”的关系,一个数据包有一个包头和一个数据体。而继承使用了“是”的关系,一个BadTr是一种Transaction,只不过具有了更多的信息。
二、合成的问题
信息隐藏(使用私有变量)等的概念跟创建一个测试平台是矛盾的,因为测试平台需要最大的可见性和可控制性。
使用合成来创建以太帧(不推荐)
class EthMacFrame;
typedef enum{II,IEEE} kind_e; 假设测试平台使用的是普通类型II和虚拟局域网VLAN两种帧格式
rand kind_e kind;
rand bit[47:0] da, sa;
rand bit[15:0] len;
...
rand Vlan vlan_h;
endclass
class Vlan;
rand bit[15:0] vlan;
endclass
- 使用合成的方法,它增加了一个层次,所以就必须每次引用的时候增加一个额外的名字。
- 在例化这个层次化的类结构并随机化其值得时候也会存在问题:当new函数被调用的时候,因为kind是随机取值的,所以你不知道是否要创建一个VLAN对象。而当你随机化类对象的时候,约束将根据随机的kind值同时对EthMacFrame和Vlan对象设置变量,这样就存在一种循环的依赖关系,随机化仅仅对被例化的对象起作用,然而你却要等到kind的值确定了以后才能例化这个对象。
- 创建和随机赋值问题的唯一解决方法是每次都例化EthMacFrame::new中的所有对象。
三、继承的问题
使用继承创建以太帧类(不推荐)
class EthMacFrame;
typedef enum{II,IEEE} kind_e; 假设测试平台使用的是普通类型II和虚拟局域网VLAN两种帧格式
rand kind_e kind;
rand bit[47:0] da, sa;
rand bit[15:0] len;
...
endclass
class Vlan extends EthMacFrame;
rand bit[15:0] vlan;
endclass
- 使用继承就需要考虑到基类和派生类之间的转换问题、虚方法使用的问题等等。
- 继承在初始化的时候也要考虑到约束的问题,约束要在两种帧类型中随机地取值并且给变量赋以恰当的值,不能再引用vlan域的EthMacFrame上施加约束。
- 还有就是多继承的问题。
四、其他方法
合成会导致层次结构变复杂,继承需要额外的代码和设计来处理不同的类。还有一种方法是,可以创建一个单一的不分层的类,包含所有的变量和子程序。这种方法会使得类变得很大,但是解决了上述所有问题。你必须使用判别变量来决定哪个变量是有效的。
创建一个不分层的以太帧类
class EthMacFrame;
typedef enum{II,IEEE} kind_e; 假设测试平台使用的是普通类型II和虚拟局域网VLAN两种帧格式
rand kind_e kind;
rand bit[47:0] da, sa;
rand bit[15:0] len, vlan;
...
constraint eth_mac_frame_II{
if(kind == II){
data.size() inside {[46:1500]};
len == data.size();
}
}
constraint eth_mac_frame_ieee{
if(kind == IEEE){
data.size() inside {[46:1500]};
len < 1522;
}
}
endclass