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

SOC/IP验证工程师

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

公告

View Post

寄存器模型集成的写法

第一种写法:
当driver将读取值返回后,寄存器模型会更新寄存器的镜像值和期望值。这个功能被称为寄存器模型的自动预测功能auto_predict;
在建立寄存器模型时,使用如下语句打开此功能:rm.default_map.set_auto_perdict(1)

function void base_test::build_phase(uvm_phase phase);
   super.build_phase(phase);
   rm = reg_model::type_id::create("rm", this);
   rm.configure(null, "");//parent block;后门访问路径
   rm.build();//将所有的寄存器实例化
   rm.lock_model();//调用此函数后,reg_model中就不能再加入新的寄存器
   rm.reset();//不调用此函数,reg_model中所有寄存器的值都是零,调用后,所有寄存器的值为设置后的reset的值;
   rm.set_hdl_path_root("top_tb.my_dut");//后门访问路径
   //利用后门路径访问寄存器时,需要在reg_block中调用configure函数,设置好第三个路径;
   reg_sqr_adapter = new("reg_sqr_adapter");
  // Set this bit in extensions of this class if the bus driver provides separate response items.
  reg_sqr_adaper.provides_responses = 1;//put response to sequencer
endfunction

function void base_test::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   //寄存器模型的前门访问操作最终都是由uvm_reg_map完成,因此在connect_phase中,
   //需要将转换器和bus_sequencer通过set_sequencer函数告知reg_model的default_map;
   rm.default_map.set_sequencer(env.bus_agt.sqr, reg_sqr_adapter);
   rm.default_map.set_auto_predict(1);//将default_map设置为自动预测状态;
endfunction

第二种写法:
monitor从总线上收集到的transaction交给寄存器模型,后者更新相应的寄存器的值;
当总线上只有一个主设备时,两种方法完全一致。如果有多个主设备,则前一种方法会漏掉某些transaction;
此时可以关掉自动预测功能:rm.default_map.set_auto_predict(0);

function void base_test::build_phase(uvm_phase phase);
   super.build_phase(phase);
   rm = reg_model::type_id::create("rm", this);
   rm.configure(null, "");
   rm.build();
   rm.lock_model();
   rm.reset();
   reg_sqr_adapter = new("reg_sqr_adapter");

   mon_reg_adapter = new("mon_reg_adapter");////
   reg_predictor = new("reg_predictor", this);////
endfunction

function void base_test::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   rm.default_map.set_sequencer(env.bus_agt.sqr, reg_sqr_adapter);
   rm.default_map.set_auto_predict(1);////1
   //monitor->predictor->adapter->rm
   reg_predictor.map = rm.default_map;////2设置reg_predictor的map
   reg_predictor.adapter = mon_reg_adapter;////2设置reg_predictor的adapter
   env.bus_agt.ap.connect(reg_predictor.bus_in);////2把reg_predictor和bus_agt的ap口来连接在一起
endfunction

class bus_monitor extends uvm_monitor;

virtual bus_if vif;

uvm_analysis_port #(bus_transaction) ap;

`uvm_component_utils(bus_monitor)
function new(string name = "bus_monitor", uvm_component parent = null);
super.new(name, parent);
endfunction

virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual bus_if)::get(this, "", "vif", vif))
`uvm_fatal("bus_monitor", "virtual interface must be set for vif!!!")
ap = new("ap", this);
endfunction

extern task main_phase(uvm_phase phase);
extern task collect_one_pkt(bus_transaction tr);
endclass
monitor的写法

task bus_monitor::main_phase(uvm_phase phase);
   bus_transaction tr;
   while(1) begin
      tr = new("tr");
      collect_one_pkt(tr);
      ap.write(tr);
   end
endtask

task bus_monitor::collect_one_pkt(bus_transaction tr);
   
   while(1) begin
      @(posedge vif.clk);
      if(vif.bus_cmd_valid) break;
   end

   tr.bus_op = ((vif.bus_op == 0) ? BUS_RD : BUS_WR);
   tr.addr = vif.bus_addr;
   tr.wr_data = vif.bus_wr_data;
   @(posedge vif.clk);
   tr.rd_data = vif.bus_rd_data;
   `uvm_info("bus_monitor", "end collect one pkt", UVM_LOW);
endtask

posted on 2023-06-17 21:19  SOC验证工程师  阅读(203)  评论(0)    收藏  举报

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