如何使用UVM寄存器模型中的callback


前言

我们在使用UVM的寄存器模型过程中,有时候需要在寄存器配置配置前准备一些数据,或者在寄存器配置之后触发一些操作,这个时候就可以用到UVM寄存器模型中自带的callback,本文主要介绍如何使用UVM中寄存器模型自带的callback。


一、底层UVM的介绍

在uvm-1.2\src\reg\uvm_reg_cbs.svh中,分别为读写提供了pre和post的回调函数,以及post_predict的回调函数等如下所示。

     // Task: pre_write
   //
   // Called before a write operation.
   //
   // All registered ~pre_write~ callback methods are invoked after the
   // invocation of the ~pre_write~ method of associated object (<uvm_reg>,
   // <uvm_reg_field>, <uvm_mem>, or <uvm_reg_backdoor>). If the element being
   // written is a <uvm_reg>, all ~pre_write~ callback methods are invoked
   // before the contained <uvm_reg_fields>. 
   //
   // Backdoor - <uvm_reg_backdoor::pre_write>,
   //            <uvm_reg_cbs::pre_write> cbs for backdoor.
   //
   // Register - <uvm_reg::pre_write>,
   //            <uvm_reg_cbs::pre_write> cbs for reg,
   //            then foreach field:
   //              <uvm_reg_field::pre_write>, 
   //              <uvm_reg_cbs::pre_write> cbs for field
   //
   // RegField - <uvm_reg_field::pre_write>,
   //            <uvm_reg_cbs::pre_write> cbs for field
   //
   // Memory   - <uvm_mem::pre_write>,
   //            <uvm_reg_cbs::pre_write> cbs for mem
   //
   // The ~rw~ argument holds information about the operation.
   //
   // - Modifying the ~value~ modifies the actual value written.
   //
   // - For memories, modifying the ~offset~ modifies the offset
   //   used in the operation.
   //
   // - For non-backdoor operations, modifying the access ~path~ or
   //   address ~map~ modifies the actual path or map used in the
   //   operation.
   //
   // If the ~rw.status~ is modified to anything other than <UVM_IS_OK>,
   // the operation is aborted.
   //
   // See <uvm_reg_item> for details on ~rw~ information.
   //
   virtual task pre_write(uvm_reg_item rw); endtask


   // Task: post_write
   //
   // Called after a write operation.
   //
   // All registered ~post_write~ callback methods are invoked before the
   // invocation of the ~post_write~ method of the associated object (<uvm_reg>,
   // <uvm_reg_field>, <uvm_mem>, or <uvm_reg_backdoor>). If the element being
   // written is a <uvm_reg>, all ~post_write~ callback methods are invoked
   // before the contained <uvm_reg_fields>. 
   //
   // Summary of callback order:
   //
   // Backdoor - <uvm_reg_cbs::post_write> cbs for backdoor,
   //            <uvm_reg_backdoor::post_write>
   //
   // Register - <uvm_reg_cbs::post_write> cbs for reg,
   //            <uvm_reg::post_write>,
   //            then foreach field:
   //              <uvm_reg_cbs::post_write> cbs for field,
   //              <uvm_reg_field::post_read>
   //
   // RegField - <uvm_reg_cbs::post_write> cbs for field,
   //            <uvm_reg_field::post_write>
   //
   // Memory   - <uvm_reg_cbs::post_write> cbs for mem,
   //            <uvm_mem::post_write>
   //
   // The ~rw~ argument holds information about the operation.
   //
   // - Modifying the ~status~ member modifies the returned status.
   //
   // - Modifying the ~value~ or ~offset~ members has no effect, as
   //   the operation has already completed.
   //
   // See <uvm_reg_item> for details on ~rw~ information.
   //
   virtual task post_write(uvm_reg_item rw); endtask


   // Task: pre_read
   //
   // Callback called before a read operation.
   //
   // All registered ~pre_read~ callback methods are invoked after the
   // invocation of the ~pre_read~ method of associated object (<uvm_reg>,
   // <uvm_reg_field>, <uvm_mem>, or <uvm_reg_backdoor>). If the element being
   // read is a <uvm_reg>, all ~pre_read~ callback methods are invoked before
   // the contained <uvm_reg_fields>. 
   //
   // Backdoor - <uvm_reg_backdoor::pre_read>,
   //            <uvm_reg_cbs::pre_read> cbs for backdoor
   //
   // Register - <uvm_reg::pre_read>,
   //            <uvm_reg_cbs::pre_read> cbs for reg,
   //            then foreach field:
   //              <uvm_reg_field::pre_read>,
   //              <uvm_reg_cbs::pre_read> cbs for field
   //
   // RegField - <uvm_reg_field::pre_read>,
   //            <uvm_reg_cbs::pre_read> cbs for field
   //
   // Memory   - <uvm_mem::pre_read>,
   //            <uvm_reg_cbs::pre_read> cbs for mem
   //
   // The ~rw~ argument holds information about the operation.
   //
   // - The ~value~ member of ~rw~ is not used has no effect if modified.
   //
   // - For memories, modifying the ~offset~ modifies the offset
   //   used in the operation.
   //
   // - For non-backdoor operations, modifying the access ~path~ or
   //   address ~map~ modifies the actual path or map used in the
   //   operation.
   //
   // If the ~rw.status~ is modified to anything other than <UVM_IS_OK>,
   // the operation is aborted.
   //
   // See <uvm_reg_item> for details on ~rw~ information.
   //
   virtual task pre_read(uvm_reg_item rw); endtask


   // Task: post_read
   //
   // Callback called after a read operation.
   //
   // All registered ~post_read~ callback methods are invoked before the
   // invocation of the ~post_read~ method of the associated object (<uvm_reg>,
   // <uvm_reg_field>, <uvm_mem>, or <uvm_reg_backdoor>). If the element being read
   // is a <uvm_reg>, all ~post_read~ callback methods are invoked before the
   // contained <uvm_reg_fields>. 
   //
   // Backdoor - <uvm_reg_cbs::post_read> cbs for backdoor,
   //            <uvm_reg_backdoor::post_read>
   //
   // Register - <uvm_reg_cbs::post_read> cbs for reg,
   //            <uvm_reg::post_read>,
   //            then foreach field:
   //              <uvm_reg_cbs::post_read> cbs for field,
   //              <uvm_reg_field::post_read>
   //
   // RegField - <uvm_reg_cbs::post_read> cbs for field,
   //            <uvm_reg_field::post_read>
   //
   // Memory   - <uvm_reg_cbs::post_read> cbs for mem,
   //            <uvm_mem::post_read>
   //
   // The ~rw~ argument holds information about the operation.
   //
   // - Modifying the readback ~value~ or ~status~ modifies the actual
   //   returned value and status.
   //
   // - Modifying the ~value~ or ~offset~ members has no effect, as
   //   the operation has already completed.
   //
   // See <uvm_reg_item> for details on ~rw~ information.
   //
   virtual task post_read(uvm_reg_item rw); endtask


   // Task: post_predict
   //
   // Called by the <uvm_reg_field::predict()> method
   // after a successful UVM_PREDICT_READ or UVM_PREDICT_WRITE prediction.
   //
   // ~previous~ is the previous value in the mirror and
   // ~value~ is the latest predicted value. Any change to ~value~ will
   // modify the predicted mirror value.
   //
   virtual function void post_predict(input uvm_reg_field  fld,
                                      input uvm_reg_data_t previous,
                                      inout uvm_reg_data_t value,
                                      input uvm_predict_e  kind,
                                      input uvm_path_e     path,
                                      input uvm_reg_map    map);
   endfunction


   // Function: encode
   //
   // Data encoder
   //
   // The registered callback methods are invoked in order of registration
   // after all the ~pre_write~ methods have been called.
   // The encoded data is passed through each invocation in sequence.
   // This allows the ~pre_write~ methods to deal with clear-text data.
   //
   // By default, the data is not modified.
   //
   virtual function void encode(ref uvm_reg_data_t data[]);
   endfunction


   // Function: decode
   //
   // Data decode
   //
   // The registered callback methods are invoked in ~reverse order~
   // of registration before all the ~post_read~ methods are called.
   // The decoded data is passed through each invocation in sequence.
   // This allows the ~post_read~ methods to deal with clear-text data.
   //
   // The reversal of the invocation order is to allow the decoding
   // of the data to be performed in the opposite order of the encoding
   // with both operations specified in the same callback extension.
   // 
   // By default, the data is not modified.
   //
   virtual function void decode(ref uvm_reg_data_t data[]);
   endfunction

在uvm-1.2\src\reg\uvm_reg_field.svh或者uvm-1.2\src\reg\uvm_reg.svh中,write和read的task会去分别调用do_write和do_read,在do_write中,写之前会去调用uvm_reg_cbs中的pre_write,写之后会去调用post_write,do_read与do_write类似。

所以,我们可以利用UVM中寄存器自带的这个callback,先基于这个uvm_reg_cbs,在其继承后子类的pre/post中,去实现我们自定义的callback功能,再将我们实现的子类加到对应寄存器的callback中。

二、UVM寄存器模型callback的使用

使用uvm寄存器模型的callback可以分为两步:
1)拓展。基于uvm_reg_cbs拓展出一个子类,在子类的pre/post中实现需要的功能;
2)绑定。将拓展出来的callback子类add到对应的寄存器上。

1、拓展

先基于uvm_reg_cbs拓展出一个子类reg0_callback,在子类pre/post中,实现我们需要的功能。

class reg0_callback extends uvm_reg_cbs;
    int a;
    `uvm_object_utils(reg0_callback)

    function new(string name = "reg0_callback");
        super.new(name);
    endfunction : new

    virtual task post_write(uvm_reg_item rw);
		// user function write here
		...
    endtask : post_write
endclass : reg0_callback

2、绑定

在环境中,首先声明并创建我们自定义的回调class,然后reg利用uvm_reg_cb::add这个静态函数,field利用uvm_reg_field_cb::add这个静态函数,将回调class绑定到对应的寄存器上,这样在这个寄存器访问的时候,就会自动触发回调class的调用,从而实现uvm寄存器模型的callback。

class top_env extends uvm_env;
    `uvm_object_utils(top_env)

    function new(string name = "top_env");
        super.new(name);
    endfunction : new

  function void connect_phase(uvm_phase phase);
       super.connect_phase(phase);
       reg0_callback reg0_cb;
       reg0_cb = reg0_callback::type_id::create("reg0_cb");
       // bind here
       uvm_reg_cb::add(reg_block.reg0, reg0_cb);
  endfunction
endclass : top_env

其中,uvm_reg_cb/uvm_reg_field_cb这两个类型的定义在uvm_reg_cbs中,实质上还是用的uvm_callback,只是传递了不同的参数类型,源码如下:

// Type: uvm_reg_cb
//
// Convenience callback type declaration for registers
//
// Use this declaration to register the register callbacks rather than
// the more verbose parameterized class
//
typedef uvm_callbacks#(uvm_reg, uvm_reg_cbs) uvm_reg_cb;

// Type: uvm_reg_field_cb
//
// Convenience callback type declaration for fields
//
// Use this declaration to register field callbacks rather than
// the more verbose parameterized class
//
typedef uvm_callbacks#(uvm_reg_field, uvm_reg_cbs) uvm_reg_field_cb;

总结

本文主要记录一下,如何利用UVM寄存器模型自带的callback,实现用户自定义的功能。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
UVM(Universal Verification Methodology)寄存器模型是一用于验证芯片寄存器功能的标准方法。它提供了一个统一的、可重用的框架,用于建立和管理寄存器模型,以及执行寄存器访问和验证。 UVM寄存器模型的主要组成部分包括寄存器模型寄存器层次结构、寄存器操作和寄存器验证环境。 1. 寄存器模型UVM寄存器模型是一个抽象的表示,用于描述芯片内部的寄存器寄存器字段。它提供了一种结构化的方式来定义寄存器的属性、寄存器字段的位宽和访问权限等。 2. 寄存器层次结构:UVM寄存器模型支持多层级的寄存器结构,可以通过层级关系来描述芯片内部的寄存器模块和子模块。这样可以更好地组织和管理寄存器模型,并提供寄存器之间的相互作用和访问。 3. 寄存器操作:UVM提供了一系列的API,用于执行寄存器读写操作。通过这些API,可以向寄存器模型发送读写请求,并获取响应。同时,还可以对寄存器的访问进行配置和控制,如重置、写入默认值等。 4. 寄存器验证环境:UVM寄存器模型可以与其他验证环境进行集成,以验证寄存器功能的正确性。通过使用事务级建模(TLM)接口,可以将寄存器操作与其他验证组件进行交互,并进行功能验证、覆盖率分析和错误注入等。 总之,UVM寄存器模型提供了一种规范化的方法来描述和验证芯片寄存器功能。它具有可重用性、灵活性和扩展性,并能与其他验证组件进行集成,从而提高验证效率和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值