uvm register model

1.基本概念

uvm_reg_field:寄存器模型中最小单位

uvm_reg:由uvm_reg_field组成

 1 class reg_invert extends uvm_reg;
 2 
 3     rand uvm_reg_field reg_data;
 4 
 5     virtual function void build();
 6         reg_data = uvm_reg_field::type_id::create("reg_data");
 7         // parameter: parent, size, lsb_pos, access, volatile, reset value, has_reset, is_rand, individually accessible
 8         reg_data.configure(this, 1, 0, "RW", 1, 0, 1, 1, 0);
 9     endfunction
10 
11     `uvm_object_utils(reg_invert)
12 
13     function new(input string name="reg_invert");
14         //parameter: name, size, has_coverage
15         super.new(name, 16, UVM_NO_COVERAGE);
16     endfunction
17 endclass

uvm_reg_block:由uvm_reg组成,也可加入其他uvm_reg_block

uvm_reg_map:存储各个寄存器的地址映射关系

 1 class reg_model extends uvm_reg_block;
 2    rand reg_invert invert;
 3 
 4    virtual function void build();
 5       default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);//系统声明的uvm_reg_map
 6 
 7       invert = reg_invert::type_id::create("invert", , get_full_name());
 8       invert.configure(this, null, "invert");//后面两个参数是reg_file和后门访问路径
 9       invert.build();
10       default_map.add_reg(invert, 'h9, "RW");//后两个参数是地址和access方式
11    endfunction
12 
13    `uvm_object_utils(reg_model)
14 
15     function new(input string name="reg_model");
16         super.new(name, UVM_NO_COVERAGE);
17     endfunction 
18 
19 endclass

 

2.应用

 寄存器模型前门访问会通过sequence产生一个uvm_reg_bus_op的变量,此变量要经过adapter转换后交给sequencer,随后交给driver

register model --> sequence --> adapter --> sequencer --> driver

 1 class my_adapter extends uvm_reg_adapter;
 2     string tID = get_type_name();
 3 
 4     `uvm_object_utils(my_adapter)
 5 
 6    function new(string name="my_adapter");
 7       super.new(name);
 8    endfunction : new
 9 
10    function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
11       bus_transaction tr;
12       tr = new("tr"); 
13       tr.addr = rw.addr;
14       tr.bus_op = (rw.kind == UVM_READ) ? BUS_RD: BUS_WR;
15       if (tr.bus_op == BUS_WR)
16          tr.wr_data = rw.data; 
17       return tr;
18    endfunction : reg2bus
19 
20    function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
21       bus_transaction tr;
22       if(!$cast(tr, bus_item)) begin
23          `uvm_fatal(tID,
24           "Provided bus_item is not of the correct type. Expecting bus_transaction")
25           return;
26       end
27       rw.kind = (tr.bus_op == BUS_RD) ? UVM_READ : UVM_WRITE;
28       rw.addr = tr.addr;
29       rw.byte_en = 'h3;
30       rw.data = (tr.bus_op == BUS_RD) ? tr.rd_data : tr.wr_data;
31       rw.status = UVM_IS_OK;
32    endfunction : bus2reg
33 
34 endclass : my_adapter

 

在uvm test中instance和connect

 1 class base_test extends uvm_test;
 2 
 3    my_env         env;
 4    my_vsqr        v_sqr;
 5    reg_model      rm;
 6    my_adapter     reg_sqr_adapter;
 7 
...
16 endclass
17 
18 
19 function void base_test::build_phase(uvm_phase phase);
20    super.build_phase(phase);
21    env  =  my_env::type_id::create("env", this); 
22    v_sqr =  my_vsqr::type_id::create("v_sqr", this);
23    rm = reg_model::type_id::create("rm", this);
24    rm.configure(null, "");//parent和后门访问路径
25    rm.build();
26    rm.lock_model();
27    rm.reset();
rm.set_hdl_path_root("top_tb.my_dut"); //设置后门的根目录
28 reg_sqr_adapter = new("reg_sqr_adapter"); 29 env.p_rm = this.rm; 30 endfunction 31 32 function void base_test::connect_phase(uvm_phase phase); 33 super.connect_phase(phase); 34 v_sqr.p_my_sqr = env.i_agt.sqr; 35 v_sqr.p_bus_sqr = env.bus_agt.sqr; 36 v_sqr.p_rm = this.rm; 37 rm.default_map.set_sequencer(env.bus_agt.sqr, reg_sqr_adapter); 38 rm.default_map.set_auto_predict(1); 39 endfunction

 

在ref model中使用

1 class my_model extends uvm_component;
...
3    reg_model p_rm;
...
5 endclass 

 

 1 function void my_env::connect_phase(uvm_phase phase);
...
 9    mdl.p_rm = this.p_rm;
10 endfunction

 

 1 task my_model::main_phase(uvm_phase phase);
 2    my_transaction tr;
 3    my_transaction new_tr;
 4    uvm_status_e status;
 5    uvm_reg_data_t value;
 6    super.main_phase(phase);
 7    p_rm.invert.read(status, value, UVM_FRONTDOOR);
 8    while(1) begin
 9       port.get(tr);
10       new_tr = new("new_tr");
11       new_tr.copy(tr);
12       //`uvm_info("my_model", "get one transaction, copy and print it:", UVM_LOW)
13       //new_tr.print();
14       if(value)
15          invert_tr(new_tr);
16       ap.write(new_tr);
17    end
18 endtask

 

在sequence中使用

 1 class case0_cfg_vseq extends uvm_sequence;
...
10    virtual task body();
11       uvm_status_e   status;
12       uvm_reg_data_t value;
...
15       p_sequencer.p_rm.invert.read(status, value, UVM_FRONTDOOR);
16       `uvm_info("case0_cfg_vseq", $sformatf("invert's initial value is %0h", value), UVM_LOW)
17       p_sequencer.p_rm.invert.write(status, 1, UVM_FRONTDOOR);
18       p_sequencer.p_rm.invert.read(status, value, UVM_FRONTDOOR);
...
22    endtask
23 
24 endclass

 

3.register model常用api

write/read:可通过前门或后门方式读写DUT,寄存器模型会相应更新期望值和镜像值,符合寄存器读写属性要求

peek/poke:通过后门方式读写DUT,寄存器模型会相应更新期望值和镜像值,无视寄存器读写属性要求

set:更新寄存器模型期望值,镜像值不变

get:返回寄存器模型期望值

update:检查寄存器模型期望值和镜像值是否一致,如果不一致,就会将期望值写入DUT并更新镜像值

randomize:寄存器模型期望值变为随机值,镜像值不变,通常后接update操作

mirror:读取DUT中寄存器值更新到寄存器模型,如发现与镜像值不一致可选择是否报错,UVM_CHECK报错,UVM_NO_CHECK不报错

predict:更新镜像值并且不对DUT操作

uvm_reg_block::get_root_blocks(blks):blks为整个验证平台的最顶层reg_block队列句柄

uvm_reg_map的函数get_reg_by_offset(addr):可根据地址addr获得改地址所对应寄存器句柄

 

转载于:https://www.cnblogs.com/hyyu/p/10342710.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值