[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 2021-09-01 18:33  知北游。。  阅读(3142)  评论(0)    收藏  举报

导航