UVM源码学习笔记

reset函数

目录

reset函数


 block reset:

function void uvm_reg_block::reset(string kind = "HARD");

   foreach (regs[rg_]) begin
     uvm_reg rg = rg_;
     rg.reset(kind);
   end

   foreach (blks[blk_]) begin
     uvm_reg_block blk = blk_;
     blk.reset(kind);
   end
endfunction

 调用get_registers将regs从关联数组中拿到


function void uvm_reg_block::get_registers(ref uvm_reg regs[$],
                                           input uvm_hier_e hier=UVM_HIER);
   foreach (this.regs[rg])
     regs.push_back(rg);

   if (hier == UVM_HIER)
     foreach (blks[blk_]) begin
       uvm_reg_block blk = blk_;
       blk.get_registers(regs);
     end
endfunction: get_registers

 regs关联数组由add_reg填充,blk的该函数由uvm_reg的configure调用,

function void uvm_reg_block::add_reg(uvm_reg rg);
   if (this.is_locked()) begin
      `uvm_error("RegModel", "Cannot add register to locked block model");
      return;
   end

   if (this.regs.exists(rg)) begin
      `uvm_error("RegModel", {"Register '",rg.get_name(),
         "' has already been registered with block '",get_name(),"'"})
       return;
   end

   regs[rg] = id++;
endfunction: add_reg
function void uvm_reg::configure (uvm_reg_block blk_parent,
                                  uvm_reg_file regfile_parent=null,
                                  string hdl_path = "");
   m_parent = blk_parent;
   m_parent.add_reg(this);
   m_regfile_parent = regfile_parent;
   if (hdl_path != "")
     add_hdl_path_slice(hdl_path, -1, -1);
endfunction: configure

如果block已经通调用过lock函数那么则不能再add_reg,也不能对吧blk进行其余改变的操作

其中regs是关联数组,索引是rg(索引是句柄吗?),存放的是int类型数据

 local int unsigned   regs[uvm_reg];

reg reset

function void uvm_reg::reset(string kind = "HARD");
   foreach (m_fields[i])
      m_fields[i].reset(kind);
   // Put back a key in the semaphore if it is checked out
   // in case a thread was killed during an operation
   void'(m_atomic.try_get(1));
   m_atomic.put(1);
   m_process = null;
   Xset_busyX(0);
endfunction: reset

field reset

function void uvm_reg_field::reset(string kind = "HARD");

   if (!m_reset.exists(kind))
      return;
   
   m_mirrored = m_reset[kind];
   m_desired  = m_mirrored;
   value      = m_mirrored;

   if (kind == "HARD")
      m_written  = 0;

endfunction: reset

对于上面所说的string我们先看一下reset值是如何来的,对于field来说,reset值在configure时会进行传参,一般都会将has_reset配置为1,

function void uvm_reg_field::configure(uvm_reg        parent,
                                       int unsigned   size,
                                       int unsigned   lsb_pos,
                                       string         access,
                                       bit            volatile,
                                       uvm_reg_data_t reset,
                                       bit            has_reset,
                                       bit            is_rand,
                                       bit            individually_accessible); 
   if (has_reset)
      set_reset(reset);
   else
      uvm_resource_db#(bit)::set({"REG::", get_full_name()},
                                 "NO_REG_HW_RESET_TEST", 1);

那么m_reset关联数组索引默认情况下都为HARD,索引值为配置的reset值

function void uvm_reg_field::set_reset(uvm_reg_data_t value,
                                       string kind = "HARD");
   m_reset[kind] = value & ((1<<m_size) - 1);
endfunction: set_reset

现在在回头看reset函数,m_reset只有has_reset的情况下才会有值,否则会return,为该field的镜像值设置为reset值,期望值设置为镜像值,value也为镜像值,也就是说复位后,寄存器域的三个值都是复位值。对于非RW寄存器也会有复位值

uvm_resource_db

uvm_resource_db是一个参数化类,内建一个资源池,类型来自于uvm_resource_db的参数

typedef uvm_resource #(T) rsrc_t;

先看一下使用最频繁的set函数

  static function void set(input string scope, input string name,
                           T val, input uvm_object accessor = null);

    rsrc_t rsrc = new(name, scope);
    rsrc.write(val, accessor);
    rsrc.set();

    if(uvm_resource_db_options::is_tracing())
      m_show_msg("RSRCDB/SET", "Resource","set", scope, name, accessor, rsrc);
  endfunction

set是静态函数,所以使用::可以直接调用

  function void write(T t, uvm_object accessor = null);

    if(is_read_only()) begin
      uvm_report_error("resource", $sformatf("resource %s is read only -- cannot modify", get_name()));
      return;
    end

    // Set the modified bit and record the transaction only if the value
    // has actually changed.
    if(val == t)
      return;

    record_write_access(accessor);

    // set the value and set the dirty bit
    val = t;
    modified = 1;
  endfunction

函数is_read_only来获得当前resource状态,read_only返回1,read_write返回0,该属性可以通过函数来配置。

如果写入的值没有发生改变return

record_write_access下次再看

set函数会继续调用rp的set

  function void set();
    uvm_resource_pool rp = uvm_resource_pool::get();
    rp.set(this);
  endfunction

rp的set

  function void set (uvm_resource_base rsrc, 
                     uvm_resource_types::override_t override = 0);

    uvm_resource_types::rsrc_q_t rq;
    string name;
    uvm_resource_base type_handle;

    // If resource handle is ~null~ then there is nothing to do.
    if(rsrc == null)
      return;

    // insert into the name map.  Resources with empty names are
    // anonymous resources and are not entered into the name map
    name = rsrc.get_name();
    if(name != "") begin
      if(rtab.exists(name))
        rq = rtab[name];
      else
        rq = new();

      // Insert the resource into the queue associated with its name.
      // If we are doing a name override then insert it in the front of
      // the queue, otherwise insert it in the back.
      if(override & uvm_resource_types::NAME_OVERRIDE)
        rq.push_front(rsrc);
      else
        rq.push_back(rsrc);

      rtab[name] = rq;
    end

    // insert into the type map
    type_handle = rsrc.get_type_handle();
    if(ttab.exists(type_handle))
      rq = ttab[type_handle];
    else
      rq = new();

    // insert the resource into the queue associated with its type.  If
    // we are doing a type override then insert it in the front of the
    // queue, otherwise insert it in the back of the queue.
    if(override & uvm_resource_types::TYPE_OVERRIDE)
      rq.push_front(rsrc);
    else
      rq.push_back(rsrc);
    ttab[type_handle] = rq;

  endfunction

对于rp来说内建了两个关联数组,rtab是以name索引,ttab是以类型索引

uvm_resource_types::rsrc_q_t rtab [string];
uvm_resource_types::rsrc_q_t ttab [uvm_resource_base];

以类型索引时,索引为type_handle,type_handle通过下面函数获得type

  function uvm_resource_base get_type_handle();
    return get_type();
  endfunction
  static function this_type get_type();
    if(my_type == null)
      my_type = new();
    return my_type;
  endfunction

学习一下get_by_name的实现,调用uvm_resource #(T) rsrc_t的get_by_name

  static function rsrc_t get_by_name(string scope,
                                     string name,
                                     bit rpterr=1);

    return rsrc_t::get_by_name(scope, name, rpterr);
  endfunction

 调用rp的get_by_name,应该是要在rp里找到对应的uvm_resource_base

  static function this_type get_by_name(string scope,
                                        string name,
                                        bit rpterr = 1);

    uvm_resource_pool rp = uvm_resource_pool::get();
    uvm_resource_base rsrc_base;
    this_type rsrc;
    string msg;

    rsrc_base = rp.get_by_name(scope, name, my_type, rpterr);
    if(rsrc_base == null)
      return null;

    if(!$cast(rsrc, rsrc_base)) begin
      if(rpterr) begin
        $sformat(msg, "Resource with name %s in scope %s has incorrect type", name, scope);
        `uvm_warning("RSRCTYPE", msg);
      end
      return null;
    end

    return rsrc;
    
  endfunction
  function uvm_resource_base get_by_name(string scope = "",
                                         string name,
                                         uvm_resource_base type_handle,
                                         bit rpterr = 1);

    uvm_resource_types::rsrc_q_t q;
    uvm_resource_base rsrc;

    q = lookup_name(scope, name, type_handle, rpterr);

    if(q.size() == 0) begin
      push_get_record(name, scope, null);
      return null;
    end

    rsrc = get_highest_precedence(q);
    push_get_record(name, scope, rsrc);
    return rsrc;
    
  endfunction

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值