关于类里的一些事项

 类型转换

  • 类型转换可以分为静态转换和动态转换。
  • 静态转换即需要在转换的表达式前加上单引号即可(int'(4.0)),该方式并不会对转换值做检查。如果发生转换失败,我们也无从得知。
  • 动态转换即需要使用系统函数$cast(tgt, src)做转换。
  • 静态转换和动态转换均需要操作符号或者系统函数介入,统称为显式转换。
  • 不需要进行转换的一些操作,我们称之为隐式转换。例如赋值语句右侧是4位的矢量,而左侧是5位的矢量,隐式转换会先做位宽扩展((隐式),然后再做赋值。

动态转换

  • 当我们使用类的时候,类句柄的向下转换,即从父类句柄转换为子类句柄时,需要使用$cast()函数进行转换,否则会出现编译错误,这一步也是编译器的保护措施,防止用户出现错误的赋值。
  • 如果将子类句柄赋值给父类句柄时,编译器则认为赋值是合法的,但分别利用子类句柄和父类句柄调相同对象的成员时,将可能有不同的表现。
  • 将一个父类句柄赋值给一个子类句柄并不总是非法的。但是SV编译器对这种直接赋值的做法是禁止的,也就是说无论父类句柄是否真正指向了一个子类对象,赋值给子类句柄时,编译((静态)都将出现错误。
  • 因此需要$cast(tgt, src)来实现句柄类型的动态转换。
  • $cast(tgt, src)会检查句柄所指向的对象类型,而不仅仅检查句柄本身。(比如父类句柄指向子类对象时,转换可以成功,注意tgt是子类句柄,此时可以访问子类)
  • —旦源对象跟目的句柄是同一类型,或者是目的句柄的扩展类,$cast()函数执行即会成功,返回1,否则返回0。

虚方法

  • 类的继承是从继承成员变量和成员方法两个方面。从例码中可以看到test_wr类和test_rd类分别继承了basic_test类的成员变量以及成员方法。(即使子类和父类有同名的变量不同值,但还是继承了,通过super可以查找父类的变量)(子类覆盖override的方法不会继承父类同名方法,只有通过super.method()的方式显式执行才会达到继承的效果)
  • 正是由于类的多态性,使得用户在设计和实现类时,不需要担心句柄指向的对象类型是父类还是子类,只要通过虚方法,就可以实现动态绑定(dynamic binding) ,或者在SV中称之为动态方法查找(dynamic method lookup) 。
  • 我们将已经在编译阶段就可以确定下来调用方法所处作用域的方式称之为静态绑定(static binding) ,而与之相对的是动态绑定。动态绑定指的是,在调用方法时,会在运行时来确定句柄指向对象的类型,再动态指向应该调用的方法。(看句柄指向的对象来调用方法)
  • 为了实现动态绑定,我们将basic_test::test定义为虚方法。
  • 由于声明了basic_test::test为虚方法,系统在执行t.test时,会检查t所指向对象的类型为test_wr类,进而调用test_wr: :test。于是,输出结果与调用wr.test—致。
  • 我们就可以通过虚方法的使用来实现类成员方法调用时的动态查找,用户无需担心使用的是父类句柄还是子类句柄,因为最终都会实现动态方法查找,执行正确的方法。
  • 在为父类定义方法时,如果该方法日后可能会被覆盖或者继承那么应该声明为虚方法
  • 虚方法如果要定义,应该尽量定义在底层父类中。这是因为如果virtual是声明在类继承关系的中间层类中,那么只有从该中间类到其子类的调用链中会遵循动态查找,而最底层类到该中间类的方法调用仍然会遵循静态查找。即使子类方法没有super继承,一样调用同名方法?
  • 虚方法通过virtual声明,只需要声明一次即可。当然再次声明来表明该方法的特性也是可以的。
  • 虚方法的继承也需要遵循相同的参数和返回类型,否则,子类定义的方法须归为同名不同参的其它方法。
  • 没有办法可以使父类句柄索引到子类对象里面的变量。(除了将其转为子类句柄)
//这里使用virtual,主要是希望通过句柄指向的对象来调用相应的函数
class basic_test;
    function new();
        ……
    endfunction
    task test();                                     //virtual task test();
        $display("basic_test::test");
    endtask
endclass
class test_wr extends basic_test; //子类会继承父类的方法变量,即使同名不同值,通过super可获得
    function new();
        ……
    endfunction
    task test();                                          
        super.test();
        $display("test_wr:test");
    endtask
endclass
basic_test t;
test_wr wr;
initial begin
    wr=new();       
    t=wr;
    wr.test();  //basic_test::test                //basic_test::test
                //test_wr::test                   //test_wr::test
    t.test();   //basic_test::test                //basic_test::test
end                                               //test_wr::test

对象拷贝

  • 声明变量和创建对象是两个过程,也可以一步完成。
Packet p1;
p1 = new ;   //new可以有参数,不能有返回值,不能带 virtual
  • 如果将p1赋值给另外一个变量p2,那么依然只有一个对象,只是指向这个对象的句柄有p1和p2。
  • 以下这种方式表示p1和p2代表两个不同的对象。在创建p2对象时,将从p1拷贝其成员变量例如integer、string和句柄等,该种拷贝方式称为浅拷贝(shallow copy)。
Packet p1;
Packet p2;
p1 = new;         //p1=new();
p2 = new pl;      //p2=new()p1;        //p1、p2指向各自对象,p1=p2则只有一个对象
//新创建一个对象,把原有对象里的变量拷贝到新对象
//句柄拷贝,p1和p2指向同一对象
  •  对于拷贝(copy) ,对象的拷贝要比其它SV的变量类型都让人"当心”。因为就SV普通的变量拷贝而言,只需要通过赋值操作符"="就足够了。
  • 而对象的拷贝则无法通过"="来实现,因为这一操作是句柄的赋值,而不是对象的拷贝。
  • 那么如果要拷贝对象,指的是首先创建一个新的对象(开辟新的空间),再将目标对象的成员变量值拷贝给新对象的成员,这就使得新对象与目标对象的成员变量数值保持一致,即完成了对象的拷贝(成员变量的拷贝)。

区别句柄拷贝与对象拷贝的区别

class basic_test;
    ……
    virtual function void copy_data(basic_test t);
      t.def=def;
      t.fin=fin;
    endfunction
    virtual function basic_test copy();
      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);  //super,所以会调用父类方法,直接执行  父类句柄到父类的copy_data
      $cast(h,t);         //父类句柄指向子类对象,要添加这个是因为让h也指向子类对象吗?
      h.def=def;         //实现子类句柄只拷贝子类成员
    endfunction
    function basic_test copy();  //函数返回类型为basic_test
      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());  //h和wr指向不同对象
      h.def=300;
    end
endmodule
  • 将成员拷贝函数copy_data()和新对象生成函数copy()分为两个方法,这样使得子类继承和方法复用较为容易。
  • 为了保证父类和子类的成员均可以完成拷贝,将拷贝方法声明为虚方法,且遵循只拷贝该类的域成员的原则,父类的成员拷贝应由父类的拷贝方法完成。
  • 在实现copy_data()过程中应该注意句柄的类型转换,保证转换后的句柄可以访问类成员变量。

回调函数

  • 理想的验证环境是在被移植做水平复用或者垂直复用时,应当尽可能少地修改模块验证环境本身,只在外部做少量的配置,或者定制化修改就可以嵌入到新的环境中。
  • 要做到这一点,一方面我们可以通过顶层环境的配置对象自顶向下进行配置参数传递,另外一方面我们可以在测试程序不修改原始类的情况下注入新的代码。
  • 例如,当我们需要修改stimulator的行为时,有两种选择,一个是修改父类,但针对父类的会传播到其它子类;另外一个选择是,在父类定义方法时,预留回调函数入口,使得在继承的子类中填充回调函数,就可以完成对父类方法的修改。
virtual class Driver_cbs; //Driver回调虚类   不能例化,可以继承,虚类是提供模板
    virtual task pre_tx(ref Transaction tr,ref bit drop);//两个ref,怎么第一个就是输入第二输出
        ……
    endtask
    virtual task post_tx(ref Transaction tr);
        ……
    endtask
endclass

class Driver;
    Driver_cbs cbs[$];  //队列,里面放着句柄
    task run();
endclass

//回调函数主要有三步
//第一预留入口
task Driver::run;
    forever begin
        ……
        <pre_callback>
        transmit(tr);
        <post_callback>
        ……
    end
endtask
//第二步,定义回调类
class Driver_cbs_drop extends Driver_cbs;  //继承自虚类
    virtual task pre_tx(ref Trsansaction tr,ref bit drop);
        drop=($urandom(0,99)==0);
    endtask
endclass
//第三步,例化以及添加回调类的实例
program automatic test;
    ……
    begin
        Driver_cbs_drop dcd=new();
        env.drv.cbs.push_back(dcd);
    end
    env.run;
    ……
endprogram

参数化的类

  • 参数化的使用是为了提高代码的复用率。
  • 无论是设计还是验证,如果代码会被更多的人使用或者被更多的项目所采用,那么就需要考虑使用参数来提高复用率。
  • 参数的使用越合理,后期维护的成本就会相应降低。
  • 在硬件设计中,参数往往是整形,例如端口数目或者位宽。在验证环境中,参数的使用更加灵活,可以使用各种类型来做类定义时的参数
  • 在SV中,可以为类增加若干个数据类型参数,并在声明类句柄的时候指定类型
  • SV的类参数化近似于C++中的模板。
//该maibox只能用于操作整数类        类定义时添加参数
class mailbox;                         //class maibox #(type T=int);  //参数名为T,值为int
    local int queue[$];                // local T queue[$];
    task put(input int i);             //task put(input T i);
        queue.push_back(i);
    endtask
    task get(ref int o);               //task get(ref T o);
        wait(queue.size()>0);
        o=queue.pop_front();
    endtask
    task peek(ref int o);              //task peek(ref T o);
        wait(queue.size()>0); 
        o=queue[0];
    endtask
endclass



//maibox #(real) mb;   //创建一个存储real类型的maibox 
//mb=new();
  • 同一个参数化类,两个指定不同类型T的句柄可以使用$cast完成句柄的类型转换
  • 一个参数类在定义时可以指定多个参数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值