uvm的重载机制(override机制)和 factory模式

        通常来讲,在UVM中,提到重载一般来讲就是利用uvm提供的各种方法来重载验证环境中的transaction,sequence,component等内容。对于这部分的讲解,可以参考张强的《UVM实战》中的内容,我们在这里只是简单的列结论,重点会放在这部分在UVM源码的实现上。

重载函数:

1,component中的重载函数

set_type_override替换名字相同的类型
set_inst_override替换路径下名字相同的类型
set_type_override_by_type替换类型一致的
set_inst_override_by_type替换路径下类型一致的

我们先看component的源码,这部分来源于:uvm_component.svh 即 一切component子类的基类

  // Function: set_type_override_by_type
  //
  // A convenience function for <uvm_factory::set_type_override_by_type>, this
  // method registers a factory override for components and objects created at
  // this level of hierarchy or below. This method is equivalent to:
  //
  //|  factory.set_type_override_by_type(original_type, override_type,replace);
  //
  // The ~relative_inst_path~ is relative to this component and may include
  // wildcards. The ~original_type~ represents the type that is being overridden.
  // In subsequent calls to <uvm_factory::create_object_by_type> or
  // <uvm_factory::create_component_by_type>, if the requested_type matches the
  // ~original_type~ and the instance paths match, the factory will produce
  // the ~override_type~. 
  //
  // The original and override type arguments are lightweight proxies to the
  // types they represent. See <set_inst_override_by_type> for information
  // on usage.

  extern static function void set_type_override_by_type
                                             (uvm_object_wrapper original_type, 
                                              uvm_object_wrapper override_type,
                                              bit replace=1);


// set_type_override_by_type (static)
// -------------------------

function void uvm_component::set_type_override_by_type (uvm_object_wrapper original_type,
                                                        uvm_object_wrapper override_type,
                                                        bit    replace=1);
   factory.set_type_override_by_type(original_type, override_type, replace);
endfunction 

        上面这部分是在uvm_component.svh中 component基类中的静态方法:set_type_override_by_type ,就是我们常说的,类型一致,用新的内容去替换旧的内容,把源码搬出来的原因是,这个静态方法是 component基类自带的方法,也就是说,凡是从uvm_component中扩展出来的子类,都可以使用这个方法,在基类中有如下两个方法可以直接使用:

extern static function void set_type_override_by_type(uvm_object_wrapper    original_type,  //第一个参数为原始组件类型(被替换组件)
                                                      uvm_object_wrapper     override_type,     //第二个参数为新组件类型(替换组件)
                                                      bit replace = 1);

extern static function void set_inst_override_by_type(string      relative_inst_path          //相对路径
                                                     uvm_object_wrapper     original_type,   //第一个参数为原始组件类型(被替换组件)
                                                     uvm_object_wrapper     override_type,   //第二个参数为新组件类型(替换组件)
                                                     bit replace = 1);

对于这两种方法的使用,第一个是根据类型去替换,所以一旦替换,整个验证环境就全都替换掉了。第二个是根据路径去替换,因此该方法的第一个参数是string,需要提供一个替换路径,替换这个路径下的数据,同样的这个string也支持通配符匹配。

仔细翻源码,我们能发现,其实这两个方法只是对factory中相关函数的封装,实际上没有多高大上的,只是把factory的东西拿过来用而已,而且还借用了其他两个方法。

还是先近一段源码:

   // Function: set_type_override
  //
  // A convenience function for <uvm_factory::set_type_override_by_name>,
  // this method configures the factory to create an object of type
  // ~override_type_name~ whenever the factory is asked to produce a type
  // represented by ~original_type_name~.  This method is equivalent to:
  //
  //|  factory.set_type_override_by_name(original_type_name,
  //|                                    override_type_name, replace);
  //
  // The ~original_type_name~ typically refers to a preregistered type in the
  // factory. It may, however, be any arbitrary string. Subsequent calls to
  // create_component or create_object with the same string and matching
  // instance path will produce the type represented by override_type_name.
  // The ~override_type_name~ must refer to a preregistered type in the factory. 

  extern static function void set_type_override(string original_type_name, 
                                                string override_type_name,
                                                bit    replace=1);



// set_type_override (static)
// -----------------

function void uvm_component::set_type_override (string original_type_name,
                                                string override_type_name,
                                                bit    replace=1);
   factory.set_type_override_by_name(original_type_name,
                                     override_type_name, replace);
endfunction 

set_inst_override这个方法同样也是uvm_component基类中的方法,从源码上来看:

set_type_override (string original_type_name,string override_type_name,bit replace=1)借用了factory中的方法:factory.set_type_override_by_name,

set_type_override_by_type(uvm_object_wrapper original_type , uvm_object_wrapper override_type,bit replace=1) 借用了factory中的方法:set_type_override_by_type这个方法。

这两个函数从构成到实现来看,set_type_override是根据名字去替换,替换的范围仅限于名字一致,而set_type_override_by_type ,替换的范围只要是类型一直都会被替换,因此在使用这几个函数时要格外注意。

2,factory中的重载函数

由于上面的函数统统在uvm_component中封装了factory中的方法,因此也可以直接使用factory中的方法来实现,这种办法的好处是,可以在环境的任意位置使用,甚至是在tb_top中的initial 块中,大大增加了灵活性,

  extern function
      void set_inst_override_by_type (uvm_object_wrapper original_type,
                                      uvm_object_wrapper override_type,
                                      string full_inst_path);

 extern function
      void set_type_override_by_type (uvm_object_wrapper original_type,
                                      uvm_object_wrapper override_type,
                                      bit replace=1);


 extern function
      void set_inst_override_by_name (string original_type_name,
                                      string override_type_name,
                                      string full_inst_path);

  extern function
      void set_type_override_by_name (string original_type_name,
                                      string override_type_name,
                                      bit replace=1);

使用上来讲,就如下代码说是,直接facotory 通过 “.”的方法使用。

factory.set_type_override_by_type(old_component::get_type(),new_component::get_type());

对于替换的内容,uvm并没有规定必须是什么类型,但是uvm_component和uvm_object之间肯定是无法相互替换的,毕竟他俩的血缘关系已经很远了,至于其他方面的限制,主要还是“验证环境”的限制多一些,首先你要保证替换完之后能保证你的环境能正确运行,至于orignal_type 和 override_type 之间是否必须是父与子的关系,也不一定,但是要说他们之间有什么联系,肯定是有联系的^_^ ,这句话说了什么,好像又没有说什么。。。。。。

3,重载函数的使用

3.1,重载transaction

        最常用的重载transaction,是因为我们在通过 sequence发送transaction时,可能 需要发送多种不同的transaction,如果不适用factory的重载函数,那必须得建立多个sequence,不同的sequence对应一个不同的transaction,在发包时,只需要在testcase的build_phase中,设置不同的default_sequence即可,如下图所示:

function void my_case0::build_phase(uvm_phase phase);
   super.build_phase(phase);

   factory.set_type_override_by_type(my_transaction::get_type(), crc_err_tr::get_type());
   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "env.i_agt.sqr.main_phase", 
                                           "default_sequence", 
                                           normal_sequence::type_id::get());
endfunction

        如上面代码所示,我们在build_phase中,将my_transaction通过 type一致替换为了 crc_err_tr ,达到了发送crc_err transaction的目的,进而只需要一个sequence即可完成不同transaction的发送。

3.2,重载sequence

        对于sequence的重载,其实和transaction的重载是一样的,本质上没有区别,sequencer在发送sequence时,由于验证目的的不同,可能会出现各种验证场景,需要sequence去发送各种不同组合,顺序,包类型 等等的transaction的组合或者sequence的组合,所以就需要我们提供给验证环境各种不同的sequence,而为了便于维护testcase,我们只需要将sequence进行重载就能达到目的,代码如下:

function void my_case0::build_phase(uvm_phase phase);
   super.build_phase(phase);

   factory.set_type_override_by_type(normal_sequence::get_type(), abnormal_sequence::get_type());
   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "env.i_agt.sqr.main_phase", 
                                           "default_sequence", 
                                           case_sequence::type_id::get());
endfunction

3.3,重载component

对于component的重载,其实用的也不多,我们还是沿用上面的例子,如果这次我们不改变transaction和sequence,而是直接在driver上动手脚,比如说,重写一个driver,这个driver每次都会产生一个crc校验错误的包,那么只要是通过这个driver发送的transaction,所有的crc校验和都是错误的,所以当我们需要发送错误的crc校验和的包时,我们只需要重载这个driver当作发包的driver就可以了,是不是很好理解,代码如下:

function void my_case0::build_phase(uvm_phase phase);
   super.build_phase(phase);

   factory.set_type_override_by_type(my_driver::get_type(), crc_driver::get_type());
   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "env.i_agt.sqr.main_phase", 
                                           "default_sequence", 
                                           normal_sequence::type_id::get());
endfunction

好了,关于override的内容这里就算讲完了,其实override就是利用的工厂模式来实现对相同类型,相同名称的数据,类的重载,我们甚至都可以模拟factory的工厂模式来实现自己的替换方法,最后,如果要用到override,本人还是建议直接调用factory中的重载函数,更直接,更接近于UVM源码本身,也更灵活。

  • 8
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值