• 对于拷贝(copy), 对象的拷贝要比其它SV的变量类型都让人“当心”。
• 因为就SV普通的变量拷贝而言,只需要通过赋值操作符”=”就足够了。
• 而对象的拷贝则无法通过“=”来实现,因为这—操作是句柄的赋值,而不是对象的拷贝。
- class basic_test;
- int fin;
- int def= 100;
- function new();
- $display{"basic_test::new");
- endfunction
- task test();
- $display ("basic_test::test");
- endtask
- endclass
-
- class test_wr extends basic_test;
- int def= 200;
- function new();
- super.new();
- $display("test_wr::new");
- endfunction
-
- test_wr h;
- initial begin
- wr = new();
- h = wr;
- $display ("wr.def = %0d", wr.def);
- $display ("h.def =%0d",h.def);
- h.def = 300;
- $display("wr.def =%0d",wr.def);
- $display ("h.def =%0d",h.def);
- end
输出结果:
# wr.def = 200
# h.def = 200
# wr.def = 300
# h.def = 300• 在h=wr之后,由于是句柄的赋值,所以h. def = 300的操作,实际上是对这两个句柄指向的共同对象做的成员变量赋值。所以,从最终打印的结果可以看出,wr.def与t.def的值相同。
• 那么如果要拷贝对象,指的是首先创建一个新的对象(开辟新的空间),再将目标对象的成员变量值拷贝给新对象的成员,这就使得新对象与目标对象的成员变量数值保持一致,即完成了对象的拷贝(成员变量的拷贝)。
• 初学者需要区别句柄拷贝与对象拷贝的区别。
- class basic test;
- ...
- virtual function void copy_data(basic_test t);
- t.def= def;
- t.fin= fin;
- endfunction
-
- virtual function basic_test;
- basic_test t= new(0);
- copy_data(t);
- return t;
- endfunction
- endclass
-
- class test_wr extends basic_test;
- ...
- function void copy_data(basic_test t);
- test_wr h;
- super.copy_data(t);
- $cast(h,t);
- h.def = def;
- endfunction
- function basic_test copy();
- test_wr t= new();
- copy_data(t);
- return t;
- endfunction
- endclass
-
- module tb;
- ...
- test_wr wr;
- test wr h;
- initial begin
- wr = new();
- $cast(h, wr.copy());
- $display("wr.def = %0d", wr.def);
- $display("h.def = %0d", h.def);
- h.def = 300;
- $display("wr.def = %0d", wr.def);
- $display("h.def = %0d", h.def);
- end
- ...
- endmodule
输出结果:
# wr.def = 200# h.def = 200
# wr.def = 200
# h.def = 300
总结:
• 将成员拷贝函数copy_data()和新对象生成函数copy()分为两个方法, 这样使得子类继承和方法复用较为容易。
• 为了保证父类和子类的成员均可以完成拷贝, 将拷贝方法声明为虚方法, 且遵循只拷贝该类的域成员的原则, 父类的成员拷贝应由父类的拷贝方法完成。
• 在实现copy data()过程中应该注意句柄的类型转换, 保证转换后的句柄可以访问类成员变量。
• 参数化的使用是为了提高代码的复用率。
• 无论是设计还是验证,如果代码会被更多的人使用或者被更多的项目所采用,那么就需要考虑使用参数来提高复用率。
• 参数的使用越合理,后期维护的成本就会相应降低。
• 在硬件设计中,参数往往是整形,例如端口数目或者位宽。• 在验证环境中,参数的使用更加灵活,可以使用各种类型来做类定义时的参数。
• 在SV中可以为类增加若干个数据类型参数,并在声明类句柄的时候指定类型。
• SV的类参数化近似于c++中的模板。
- class mailbox;
- local int queue[$];
- task put(input int i);
- queue.push_back(i);
- endtask
- task get(ref int o);
- wait(queue.size()>0) ;
- o=queue.pop_front();
- endtask
- task peek( ref int o);
- wait(queue.size()>O);
- o=queue[O];
- endtask
- endclass
• 这个简化的mailbox的问题 在于它只能用于操作整数类型。
• 如果要存储real类型,或者某一个类的句柄,那么就得复制该类,然后将数据类型由int类型转换为real类型或者某一个类的类型。• 这样将导致类的快速增长,而且是重复代码的大规模增长,代码维护将变得冗长乏味而且还容易出错。
- lass mailbox #(type T=int);
- local T queue[$];
- task put(input T i);
- queue.push_back(i);
- endtask
- task get( ref T o);
- wait (queue. size()>0);
- o=queue.pop_front();
- endtask
- task peek( ref T o);
- wait(queue.size()>0);
- o=queue[O];
- endtask
- endclass
-
- initial begin
- real o;
- mailbox #(real) mb; //创建一个存储real类型的mailbox
- mb = new();
- for(int i=O; i
- mb.put(i*2.0); //将real值存储入mb
- for(int i=O; i
- mb.get(o); //从mb取出real值
- end
• 在类定义时添加参数#(type T=int), 这表示后期类在声明变量时如果不指定参数类型则默认采用int类型。
• 将原代码int用参数T来代替。
• 参数化的类将可以在后期例化时使用不同的参数, 以此来存储不同的数据类型。
-
相关阅读:
2000-2020上市公司全要素生产率LP方法含原始数据和Stata代码
普中51单片机学习(DS1302)
Linus Torvalds 宣布:Linux 5.18 第一个候选版本 (RC)公开测试普遍可用
C语言程序-猜数字for
研报精选 | 麦肯锡《业务流程自动化成功的必要条件》精要解读
Item-Based Recommendations with Hadoop
pt29django教程
pem文件类解析
【Gopher 学个函数】边学边练,简单为 Go 上个分
Debian12系统下LAMP环境中Nubuilder4.5的安装
-
原文地址:https://blog.csdn.net/weixin_45680021/article/details/126196129