• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

SOC/IP验证工程师

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

寄存器模型的用法:多层次的block

`ifndef REG_MODEL__SV
`define REG_MODEL__SV
//first reg
class reg_invert extends uvm_reg;
    rand uvm_reg_field reg_data;
    rand uvm_reg_field reg_status;
    //如果是RO,则可以不加rand修饰符;
    //不同的reg内的field名字可以一样;
    virtual function void build();
        reg_data = uvm_reg_field::type_id::create("reg_data");
        reg_data.configure(this, 1, 0, "RW", 1, 0, 1, 1, 0);
        reg_status = uvm_reg_field::type_id::create("reg_status"); //多个field在一个reg内例化
        reg_status.configure(this, 1, 0, "RW", 1, 0, 1, 1, 0);     //多个field在一个reg内configure
    endfunction
    `uvm_object_utils(reg_invert)
    function new(input string name="reg_invert");
        super.new(name, 16, UVM_NO_COVERAGE);
    endfunction
endclass
//second reg
class reg_depth extends uvm_reg;
    rand uvm_reg_field reg_data;
    rand uvm_reg_field reg_status;
    virtual function void build();
        reg_data = uvm_reg_field::type_id::create("reg_data");
        reg_status = uvm_reg_field::type_id::create("reg_status");//多个field在上层block内例化
    endfunction
    `uvm_object_utils(reg_depth)
    function new(input string name="reg_depth");
        super.new(name, 16, UVM_NO_COVERAGE);
    endfunction
endclass
//third reg
class reg_vlan extends uvm_reg;
    rand uvm_reg_field reg_data;
    virtual function void build();
        reg_data = uvm_reg_field::type_id::create("reg_data");
        reg_data.configure(this, 10, 0, "RW", 1, 0, 1, 1, 0);
    endfunction
    `uvm_object_utils(reg_vlan)
    function new(input string name="reg_vlan");
        super.new(name, 16, UVM_NO_COVERAGE);
    endfunction
endclass
//first block
class global_blk extends uvm_reg_block;
   rand reg_invert invert;
   virtual function void build();
      default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);
      invert = reg_invert::type_id::create("invert", , get_full_name());
      invert.configure(this, null, "");
      invert.build();
      default_map.add_reg(invert, 'h9, "RW");
   endfunction
    `uvm_object_utils(global_blk)
    function new(input string name="global_blk");
        super.new(name, UVM_NO_COVERAGE);
    endfunction 
endclass
//second block
class buf_blk extends uvm_reg_block;
   rand reg_depth depth;
   rand uvm_reg_field reg_data;
   rand uvm_reg_field reg_status;
   virtual function void build();
      default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);
      depth = reg_depth::type_id::create("depth", , get_full_name());
      depth.configure(this, null, "");//在这里第三个参数原来是指定后门的访问路径,在这里应变成空的字符串
      depth.build();
      //////将field的config放在block的内部,而不是reg内
      depth.reg_data.configure(depth, 2, 0, "RW", 1, 0, 1, 1, 0);//field的configure放在了block内执行
      depth.add_hdl_path_slice("reg_data", 0, 2);//指定后门访问的路径,补充depth.configure的第三个参数
      depth.reg_status.configure(depth, 3, 2, "RW", 1, 0, 1, 1, 0);
      depth.add_hdl_path_slice("reg_status", 2, 3);
      //////要加入的路径,此路径对应的域在此寄存器中的起始位置,此路径对应的域的宽度;
      default_map.add_reg(depth, 'h3, "RW");
      this.reg_data = this.depth.reg_data;    //用指针指向reg内的field
      this.reg_status = this.depth.reg_status;//用这样的方法可以通过block直接访问field
   endfunction
    `uvm_object_utils(buf_blk)
    function new(input string name="buf_blk");
        super.new(name, UVM_NO_COVERAGE);
    endfunction 
endclass
//third block
class mac_blk extends uvm_reg_block;
   rand reg_vlan vlan;
   virtual function void build();
      default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);
      vlan = reg_vlan::type_id::create("vlan", , get_full_name());
      vlan.configure(this, null, "");
      vlan.build();
      default_map.add_reg(vlan, 'h40, "RW");
   endfunction
    `uvm_object_utils(mac_blk)
    function new(input string name="mac_blk");
        super.new(name, UVM_NO_COVERAGE);
    endfunction 
endclass

class reg_model extends uvm_reg_block;
   rand global_blk gb_ins;
   rand buf_blk    bb_ins;
   rand mac_blk    mb_ins;
   virtual function void build();
      default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);
      gb_ins = global_blk::type_id::create("gb_ins");
      gb_ins.configure(this, "");
      //此block所在的block的指针,相对于父block的用来后门访问的相对路径
      gb_ins.build();
      gb_ins.lock_model();
      default_map.add_submap(gb_ins.default_map, 16'h0);

      bb_ins = buf_blk::type_id::create("bb_ins");
      bb_ins.configure(this, "");
      bb_ins.build();
      bb_ins.lock_model();
      default_map.add_submap(bb_ins.default_map, 16'h1000);

      mb_ins = mac_blk::type_id::create("mb_ins");
      mb_ins.configure(this, "");
      mb_ins.build();
      mb_ins.lock_model();
      default_map.add_submap(mb_ins.default_map, 16'h2000);
      
      //this.lock_model();
      //上面这句话可以替代上面所有的*.lock_model();
   endfunction
   `uvm_object_utils(reg_model)
    function new(input string name="reg_model");
        super.new(name, UVM_NO_COVERAGE);
    endfunction 
endclass
`endif

后面访问需要添加的内容:

`ifndef BASE_TEST__SV
`define BASE_TEST__SV
class base_test extends uvm_test;
   my_env         env;
   my_vsqr        v_sqr;
   reg_model      rm;
   my_adapter     reg_sqr_adapter;
   function new(string name = "base_test", uvm_component parent = null);
      super.new(name,parent);
   endfunction
   extern virtual function void build_phase(uvm_phase phase);
   extern virtual function void connect_phase(uvm_phase phase);
   extern virtual function void report_phase(uvm_phase phase);
   `uvm_component_utils(base_test)
endclass
function void base_test::build_phase(uvm_phase phase);
   super.build_phase(phase);
   env  =  my_env::type_id::create("env", this); 
   v_sqr =  my_vsqr::type_id::create("v_sqr", this);
   rm = reg_model::type_id::create("rm", this);//regmodel
   rm.configure(null, "");                     //regmodel
   rm.build();                                 //regmodel
   rm.lock_model();                            //regmodel
   rm.reset();                                 //regmodel
   rm.set_hdl_path_root("top_tb.my_dut");      //regmodel:添加后门访问的路径
   reg_sqr_adapter = new("reg_sqr_adapter");   //regmodel:实例化adapter
   env.p_rm = this.rm;
endfunction

function void base_test::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   v_sqr.p_my_sqr = env.i_agt.sqr;
   v_sqr.p_bus_sqr = env.bus_agt.sqr;
   v_sqr.p_rm = this.rm;
   rm.default_map.set_sequencer(env.bus_agt.sqr, reg_sqr_adapter);//regmodel
   rm.default_map.set_auto_predict(1);                            //regmodel
endfunction

function void base_test::report_phase(uvm_phase phase);
   uvm_report_server server;
   int err_num;
   super.report_phase(phase);
   server = get_report_server();
   err_num = server.get_severity_count(UVM_ERROR);
   if (err_num != 0) begin
      $display("TEST CASE FAILED");
   end
   else begin
      $display("TEST CASE PASSED");
   end
endfunction
`endif

posted on 2022-11-05 22:58  SOC验证工程师  阅读(351)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3