[CU]reg model使用篇-uvm_reg_block常用操作

1. 寄存器模型的reset

(1) 每一个register model被继承到验证平台后,都必须进行reset操作,这样才能保证每个寄存器的值等于我们设置的初始值.

(2) register model并不会自动的进行reset操作,必须显式的调用reset函数进行复位操作.

1.1 uvm_reg_block的reset函数

复制代码
 1 function void uvm_reg_block::reset(string kind = "HARD");
 2 
 3    foreach (regs[rg_]) begin
 4      uvm_reg rg = rg_;
 5      rg.reset(kind);
 6    end
 7 
 8    foreach (blks[blk_]) begin
 9      uvm_reg_block blk = blk_;
10      blk.reset(kind);
11    end
12 endfunction
复制代码

1.2 uvm_reg的reset

(1) m_atomic本质上是一个semaphore,用于实现进程的同步; uvm_reg的new函数中会为其分配一个key;

复制代码
 1 function void uvm_reg::reset(string kind = "HARD");
 2    foreach (m_fields[i])
 3       m_fields[i].reset(kind);
 4    // Put back a key in the semaphore if it is checked out
 5    // in case a thread was killed during an operation
 6    void'(m_atomic.try_get(1));
 7    m_atomic.put(1);
 8    m_process = null;
 9    Xset_busyX(0);
10 endfunction: reset
复制代码

1.3 uvm_reg_field的reset

(1) m_reset中的记录是在uvm_reg_field的configure函数中通过调用set_reset函数插入的;

复制代码
 1 function void uvm_reg_field::reset(string kind = "HARD");
 2 
 3    if (!m_reset.exists(kind))
 4       return;
 5    
 6    m_mirrored = m_reset[kind];
 7    m_desired  = m_mirrored;
 8    value      = m_mirrored;
 9 
10    if (kind == "HARD")
11       m_written  = 0;
12 
13 endfunction: reset
复制代码
1 function void uvm_reg_field::set_reset(uvm_reg_data_t value,
2                                        string kind = "HARD");
3    m_reset[kind] = value & ((1<<m_size) - 1);
4 endfunction: set_reset
复制代码
 1 function void uvm_reg_field::configure(uvm_reg        parent,
 2                                        int unsigned   size,
 3                                        int unsigned   lsb_pos,
 4                                        string         access,
 5                                        bit            volatile,
 6                                        uvm_reg_data_t reset,
 7                                        bit            has_reset,
 8                                        bit            is_rand,
 9                                        bit            individually_accessible); 
10    m_parent = parent;
11    if (size == 0) begin
12       `uvm_error("RegModel",
13          $sformatf("Field \"%s\" cannot have 0 bits", get_full_name()));
14       size = 1;
15    end
16 
17    m_size      = size;
18    m_volatile  = volatile;
19    m_access    = access.toupper();
20    m_lsb       = lsb_pos;
21    m_cover_on  = UVM_NO_COVERAGE;
22    m_written   = 0;
23    m_check     = volatile ? UVM_NO_CHECK : UVM_CHECK;
24    m_individually_accessible = individually_accessible;
25 
26    if (has_reset)
27       set_reset(reset);
28    else
29       uvm_resource_db#(bit)::set({"REG::", get_full_name()},
30                                  "NO_REG_HW_RESET_TEST", 1);
31 
32    m_parent.add_field(this);
33 
34    if (!m_policy_names.exists(m_access)) begin
35       `uvm_error("RegModel", {"Access policy '",access,
36        "' for field '",get_full_name(),"' is not defined. Setting to RW"})
37       m_access = "RW";
38    end
39 
40    if (size > m_max_size)
41       m_max_size = size;
42    
43    // Ignore is_rand if the field is known not to be writeable
44    // i.e. not "RW", "WRC", "WRS", "WO", "W1", "WO1"
45    case (access)
46     "RO", "RC", "RS", "WC", "WS",
47       "W1C", "W1S", "W1T", "W0C", "W0S", "W0T",
48       "W1SRC", "W1CRS", "W0SRC", "W0CRS", "WSRC", "WCRS",
49       "WOC", "WOS": is_rand = 0;
50    endcase
51 
52    if (!is_rand)
53      value.rand_mode(0);
54 
55    m_field_registry[get_full_name()] = this;
56 endfunction: configure
复制代码

2. get_root_blocks

(1) 得到所有的root blocks;

(2) 在使用get_root_blocks函数得到reg_block的指针后,使用cast将其转化为目标reg_block形式;

1 extern static  function void get_root_blocks(ref uvm_reg_block blks[$]);
2 function void uvm_reg_block::get_root_blocks(ref uvm_reg_block blks[$]);
3 
4    foreach (m_roots[blk]) begin
5       blks.push_back(blk);
6    end
7 
8 endfunction: get_root_blocks
复制代码
 1 //示例
 2 class case0_cfg_vseq extends uvm_sequence;
 3     ...
 4     virtual task body();
 5         uvm_status_e   status;
 6         uvm_reg_data_t value;
 7         bit[31:0]      counter;
 8         uvm_reg_block  blks[$];
 9         reg_model      p_rm;
10         ...
11         
12         uvm_reg_block::get_root_blocks(blks);
13         if(blks.size()==0) begin
14             `uvm_fatal(**)
15         end
16         else begin
17             if(!$cast(p_rm,blks[0])) begin
18                 **
19             end
20             p_rm.invert.read(status,value,UVM_FRONTDOOR);
21             ...
22         end
23     endtask
24 
25 endclass
复制代码

3. get_registers

(1) 得到在当前register_block里面例化的registers;

(2) 注意: register可能位于不同或多个address maps中,为了获取特定address map中的registers,需要使用uvm_reg_map::get_registers();

复制代码
 1 function void uvm_reg_block::get_registers(ref uvm_reg regs[$],
 2                                            input uvm_hier_e hier=UVM_HIER);
 3    foreach (this.regs[rg])
 4      regs.push_back(rg);
 5 
 6    if (hier == UVM_HIER)
 7      foreach (blks[blk_]) begin
 8        uvm_reg_block blk = blk_;
 9        blk.get_registers(regs);
10      end
11 endfunction: get_registers
复制代码
复制代码
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
复制代码

4. add_hdl_path

复制代码
1 function void uvm_reg_block::add_hdl_path(string path, string kind = "RTL");
2 
3   uvm_queue #(string) paths;
4 
5   paths = hdl_paths_pool.get(kind);
6 
7   paths.push_back(path);
8 
9 endfunction
复制代码
复制代码
 1 local uvm_object_string_pool #(uvm_queue #(string)) hdl_paths_pool; //uvm_reg_block内变量
 2 //uvm_pool.svh
 3 class uvm_pool #(type KEY=int, T=uvm_void) extends uvm_object;
 4   ...
 5   protected T pool[KEY];
 6   ...
 7 endclass
 8 
 9 class uvm_object_string_pool #(type T=uvm_object) extends uvm_pool #(string,T);
10 
11   ...
12   virtual function T get (string key);
13     if (!pool.exists(key))
14       pool[key] = new (key);
15     return pool[key];
16   endfunction
17   ...
18 
19 endclass
复制代码

5. configure

1 function void uvm_reg_block::configure(uvm_reg_block parent=null, string hdl_path="");
2   this.parent = parent; 
3   if (parent != null)
4     this.parent.add_block(this);
5   add_hdl_path(hdl_path);
6 
7   uvm_resource_db#(uvm_reg_block)::set("uvm_reg::*", get_full_name(), this);
8 endfunction

6. get_reg_by_name

复制代码
 1 function uvm_reg uvm_reg_block::get_reg_by_name(string name);
 2 
 3    foreach (regs[rg_]) begin
 4      uvm_reg rg = rg_;
 5      if (rg.get_name() == name)
 6        return rg;
 7    end
 8 
 9    foreach (blks[blk_]) begin
10       uvm_reg_block blk = blk_;
11       uvm_reg subregs[$];
12       blk_.get_registers(subregs, UVM_HIER);
13 
14       foreach (subregs[j])
15          if (subregs[j].get_name() == name)
16             return subregs[j];
17    end
18 
19    `uvm_warning("RegModel", {"Unable to locate register '",name,
20                 "' in block '",get_full_name(),"'"})
21    return null;
22 
23 endfunction: get_reg_by_name
复制代码

7.get_parent

复制代码
 1 function void uvm_reg_block::configure(uvm_reg_block parent=null, string hdl_path="");
 2   this.parent = parent; 
 3   if (parent != null)
 4     this.parent.add_block(this);
 5   add_hdl_path(hdl_path);
 6 
 7   uvm_resource_db#(uvm_reg_block)::set("uvm_reg::*", get_full_name(), this);
 8 endfunction
 9 
10 function uvm_reg_block uvm_reg_block::get_parent();
11    get_parent = this.parent;
12 endfunction: get_parent
复制代码

8.update

复制代码
 1 task uvm_reg_block::update(output uvm_status_e  status,
 2                            input  uvm_path_e    path = UVM_DEFAULT_PATH,
 3                            input  uvm_sequence_base  parent = null,
 4                            input  int                prior = -1,
 5                            input  uvm_object         extension = null,
 6                            input  string             fname = "",
 7                            input  int                lineno = 0);
 8    status = UVM_IS_OK;
 9 
10    if (!needs_update()) begin
11      `uvm_info("RegModel", $sformatf("%s:%0d - RegModel block %s does not need updating",
12                     fname, lineno, this.get_name()), UVM_HIGH);
13       return;
14    end
15    
16    `uvm_info("RegModel", $sformatf("%s:%0d - Updating model block %s with %s path",
17                     fname, lineno, this.get_name(), path.name ), UVM_HIGH);
18 
19    foreach (regs[rg_]) begin
20       uvm_reg rg = rg_;
21       if (rg.needs_update()) begin
22          rg.update(status, path, null, parent, prior, extension);
23          if (status != UVM_IS_OK && status != UVM_HAS_X) begin;
24            `uvm_error("RegModel", $sformatf("Register \"%s\" could not be updated",
25                                         rg.get_full_name()));
26            return;
27          end
28       end
29    end
30 
31    foreach (blks[blk_]) begin
32      uvm_reg_block blk = blk_;
33      blk.update(status,path,parent,prior,extension,fname,lineno);
34    end
35 endtask: update
复制代码

9.write_reg_by_name

复制代码
 1 task uvm_reg_block::write_reg_by_name(output uvm_status_e   status,
 2                                       input  string              name,
 3                                       input  uvm_reg_data_t      data,
 4                                       input  uvm_path_e     path = UVM_DEFAULT_PATH,
 5                                       input  uvm_reg_map      map = null,
 6                                       input  uvm_sequence_base   parent = null,
 7                                       input  int                 prior = -1,
 8                                       input  uvm_object          extension = null,
 9                                       input  string              fname = "",
10                                       input  int                 lineno = 0);
11    uvm_reg rg;
12    this.fname = fname;
13    this.lineno = lineno;
14 
15    status = UVM_NOT_OK;
16    rg = this.get_reg_by_name(name);
17    if (rg != null)
18      rg.write(status, data, path, map, parent, prior, extension);
19 
20 endtask: write_reg_by_name
复制代码

10.read_reg_by_name

复制代码
 1 task uvm_reg_block::read_reg_by_name(output uvm_status_e  status,
 2                                      input  string             name,
 3                                      output uvm_reg_data_t     data,
 4                                      input  uvm_path_e    path = UVM_DEFAULT_PATH,
 5                                      input  uvm_reg_map     map = null,
 6                                      input  uvm_sequence_base  parent = null,
 7                                      input  int                prior = -1,
 8                                      input  uvm_object         extension = null,
 9                                      input  string             fname = "",
10                                      input  int                lineno = 0);
11    uvm_reg rg;
12    this.fname = fname;
13    this.lineno = lineno;
14 
15    status = UVM_NOT_OK;
16    rg = this.get_reg_by_name(name);
17    if (rg != null)
18      rg.read(status, data, path, map, parent, prior, extension);
19 endtask: read_reg_by_name
复制代码

 

 

 

posted on   知北游。。  阅读(2780)  评论(0编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示