IC验证学习笔记(AHB-RAM)01搭建顶层环境框架以及内部 agent完善

----------------env、virtual sequencer、scoreboard、顶层config、covergroup、subscriber

subscriber:负责从monitor测监听数据,收到master transaction。scoreboard继承于subscriber

virtual sequencer:

`ifndef RKV_AHBRAM_VIRTUAL_SEQUENCER_SV
`define RKV_AHBRAM_VIRTUAL_SEQUENCER_SV

class rkv_ahbram_virtual_sequencer extends uvm_sequencer;

  // add sub-instances' sqr handles below for routing把各个Sequencer添加在下面
  rkv_ahbram_config cfg;	//顶层的配置文件
  lvc_ahb_master_sequencer ahb_mst_sqr;

  `uvm_component_utils(rkv_ahbram_virtual_sequencer)

  function new (string name = "rkv_ahbram_virtual_sequencer", uvm_component parent);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    // Get configuration from test layer	//获取配置
    if(!uvm_config_db#(rkv_ahbram_config)::get(this,"","cfg", cfg)) begin
      `uvm_fatal("GETCFG","cannot get config object from config DB")
    end
  endfunction
endclass


`endif

顶层config:在env中set

`ifndef RKV_AHBRAM_CONFIG_SV
`define RKV_AHBRAM_CONFIG_SV

class rkv_ahbram_config extends uvm_object;

  int seq_check_count;
  int seq_check_error;

  int scb_check_count;
  int scb_check_error;

  bit enable_cov = 1;
  bit enable_scb = 1;

  lvc_ahb_agent_configuration ahb_cfg;//导入底层agent的config
  virtual rkv_ahbram_if vif;//接口
  rkv_ahbram_rgm rgm;//寄存器模型 有什么用?

  `uvm_object_utils(rkv_ahbram_config)

  // USER to specify the config items
  
  function new (string name = "rkv_ahbram_config");
    super.new(name);
    ahb_cfg = lvc_ahb_agent_configuration::type_id::create("ahb_cfg");
  endfunction : new

endclass

`endif // RKV_AHBRAM_CONFIG_SV

subscriber:

`ifndef RKV_AHBRAM_SUBSCRIBER_SV
`define RKV_AHBRAM_SUBSCRIBER_SV

class rkv_ahbram_subscriber extends uvm_component;

  // analysis import
  uvm_analysis_imp #(lvc_ahb_transaction, rkv_ahbram_subscriber) ahb_trans_observed_imp;

  // events delcared

  protected uvm_event_pool _ep;//event pool用途?
  
  rkv_ahbram_config cfg;
  virtual rkv_ahbram_if vif;

  `uvm_component_utils(rkv_ahbram_subscriber)

  function new (string name = "rkv_ahbram_subscriber", uvm_component parent);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    ahb_trans_observed_imp = new("ahb_trans_observed_imp", this);//例化import
    // Get configuration from test layer
    if(!uvm_config_db#(rkv_ahbram_config)::get(this,"","cfg", cfg)) begin
      `uvm_fatal("GETCFG","cannot get config object from config DB")
    end
    vif = cfg.vif;//目的是?
    // Local event pool and events creation
    _ep = new("_ep");
  endfunction

  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    do_events_trigger();
    do_listen_events();
  endtask

  virtual function void write(lvc_ahb_transaction tr);
  endfunction

  virtual task do_events_trigger();
  endtask

  virtual task do_listen_events();
  endtask

endclass

`endif

scoreboard:

`ifndef RKV_AHBRAM_SCOREBOARD_SV
`define RKV_AHBRAM_SCOREBOARD_SV

class rkv_ahbram_scoreboard extends rkv_ahbram_subscriber;

  // events of scoreboard

  // typedef enum {CHECK_LOADCOUNTER} check_type_e;
  `uvm_component_utils(rkv_ahbram_scoreboard)

  function new (string name = "rkv_ahbram_scoreboard", uvm_component parent);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
  endfunction

  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    do_data_check();
  endtask

  task do_listen_events();
  endtask

  virtual task do_data_check();
  endtask

endclass

`endif 

env:


`ifndef RKV_AHBRAM_ENV_SV
`define RKV_AHBRAM_ENV_SV

class rkv_ahbram_env extends uvm_env;

  lvc_ahb_master_agent ahb_mst;
  rkv_ahbram_config cfg;
  rkv_ahbram_virtual_sequencer virt_sqr;
  rkv_ahbram_rgm rgm;
  rkv_ahbram_reg_adapter adapter;
  uvm_reg_predictor #(lvc_ahb_transaction) predictor;
  rkv_ahbram_cov cov;
  rkv_ahbram_scoreboard scb;

  `uvm_component_utils(rkv_ahbram_env)

  function new (string name = "rkv_ahbram_env", uvm_component parent);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    // Get configuration from test layer
    if(!uvm_config_db#(rkv_ahbram_config)::get(this,"","cfg", cfg)) begin
      `uvm_fatal("GETCFG","cannot get config object from config DB")
    end
    uvm_config_db#(rkv_ahbram_config)::set(this, "virt_sqr", "cfg", cfg);
    uvm_config_db#(rkv_ahbram_config)::set(this, "cov", "cfg", cfg);
    uvm_config_db#(rkv_ahbram_config)::set(this, "scb", "cfg", cfg);
    uvm_config_db#(lvc_ahb_agent_configuration)::set(this, "ahb_mst", "cfg", cfg.ahb_cfg);//config的set都在env
    ahb_mst = lvc_ahb_master_agent::type_id::create("ahb_mst", this);
    virt_sqr = rkv_ahbram_virtual_sequencer::type_id::create("virt_sqr", this);
    if(!uvm_config_db#(rkv_ahbram_rgm)::get(this,"","rgm", rgm)) begin
      rgm = rkv_ahbram_rgm::type_id::create("rgm", this);
      rgm.build();
    end
    uvm_config_db#(rkv_ahbram_rgm)::set(this,"*","rgm", rgm);//set rgm?
    adapter = rkv_ahbram_reg_adapter::type_id::create("adapter", this);
    predictor = uvm_reg_predictor#(lvc_ahb_transaction)::type_id::create("predictor", this);
    cov = rkv_ahbram_cov::type_id::create("cov", this);
    scb = rkv_ahbram_scoreboard::type_id::create("scb", this);
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    virt_sqr.ahb_mst_sqr = ahb_mst.sequencer;
    rgm.map.set_sequencer(ahb_mst.sequencer, adapter);//??
    ahb_mst.monitor.item_observed_port.connect(predictor.bus_in);
    predictor.map = rgm.map;
    predictor.adapter = adapter;
    ahb_mst.monitor.item_observed_port.connect(cov.ahb_trans_observed_imp);
    ahb_mst.monitor.item_observed_port.connect(scb.ahb_trans_observed_imp);
  endfunction

  function void end_of_elaboration_phase(uvm_phase phase);
    super.end_of_elaboration_phase(phase);
  endfunction

  function void report_phase(uvm_phase phase);
    string reports = "\n";
    super.report_phase(phase);
    reports = {reports, $sformatf("=============================================== \n")};
    reports = {reports, $sformatf("CURRENT TEST SUMMARY \n")};
    reports = {reports, $sformatf("SEQUENCE CHECK COUNT : %0d \n", cfg.seq_check_count)};
    reports = {reports, $sformatf("SEQUENCE CHECK ERROR : %0d \n", cfg.seq_check_error)};
    reports = {reports, $sformatf("SCOREBOARD CHECK COUNT : %0d \n", cfg.scb_check_count)};
    reports = {reports, $sformatf("SCOREBOARD CHECK ERROR : %0d \n", cfg.scb_check_error)};
    reports = {reports, $sformatf("=============================================== \n")};
    `uvm_info("TEST_SUMMARY", reports, UVM_LOW)
  endfunction

endclass



`endif // RKV_AHBRAM_ENV_SV

rgm: object类型没有build phase 只能用build

`ifndef RKV_AHBRAM_REG_SV
`define RKV_AHBRAM_REG_SV

class rkv_ahbram_rgm extends uvm_reg_block;

  `uvm_object_utils(rkv_ahbram_rgm)

  uvm_reg_map map;
  function new(string name = "rkv_watchdog_rgm");
    super.new(name, UVM_NO_COVERAGE);
  endfunction

  virtual function build();
    map = create_map("map", 'h0, 4, UVM_LITTLE_ENDIAN);
    // TODO
  endfunction


endclass


`endif

monitor中加了个port:uvm_analysis_port #(lvc_ahb_transaction)  item_observed_port;以及new

完善agent(cfg)例化并创建driver、monitor、sequencer。 以及vif

 lvc_ahb_agent_configuration cfg;

  lvc_ahb_master_driver driver;
  
  lvc_ahb_master_monitor monitor;

  lvc_ahb_master_sequencer sequencer;

 virtual lvc_ahb_if vif;
            …………
function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if(!uvm_config_db#(lvc_ahb_agent_configuration)::get(this,"","cfg", cfg)) begin
      `uvm_fatal("GETCFG","cannot get config object from config DB")
    end
    if(!uvm_config_db#(virtual lvc_ahb_if)::get(this,"","vif", vif)) begin
      `uvm_fatal("GETVIF","cannot get vif handle from config DB")
    end

    monitor = lvc_ahb_master_monitor::type_id::create("monitor", this);

    if(cfg.is_active) begin
      driver = lvc_ahb_master_driver::type_id::create("driver", this);
      sequencer = lvc_ahb_master_sequencer::type_id::create("sequencer", this);
    end

  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    monitor.vif = vif;
    if(cfg.is_active) begin
      driver.seq_item_port.connect(sequencer.seq_item_export);
      driver.vif = vif;
      sequencer.vif = vif;
    end
  endfunction

在agent_configuration,加入is_active,如果为1则在agent创建以及连接driver、sequencer否则只有monitor。

在master_driver\monitor\sequencer里加入cfg 和vif

-----------------顶层创建rkv_ahbram_base_virtual_sequence、rkv_ahbram_smoke_virt_seq、rkv_ahbram_seq_lib

rkv_ahbram_seq_lib包含两个sequence

`ifndef RKV_AHBRAM_SEQ_LIB_SVH
`define RKV_AHBRAM_SEQ_LIB_SVH

`include "rkv_ahbram_base_virtual_sequence.sv"
`include "rkv_ahbram_smoke_virt_seq.sv"


`endif

rkv_ahbram_base_virtual_sequence: 

`ifndef RKV_AHBRAM_BASE_VIRTUAL_SEQUENCE_SV
`define RKV_AHBRAM_BASE_VIRTUAL_SEQUENCE_SV

class rkv_ahbram_base_virtual_sequence extends uvm_sequence;


  rkv_ahbram_config cfg;
  virtual rkv_ahbram_if vif;
  rkv_ahbram_rgm rgm;
  bit[31:0] wr_val, rd_val;
  uvm_status_e status;//?
  `uvm_object_utils(rkv_ahbram_base_virtual_sequence)
  `uvm_declare_p_sequencer(rkv_ahbram_virtual_sequencer)

  function new (string name = "rkv_ahbram_base_virtual_sequence");
    super.new(name);
  endfunction

  virtual task body();
    `uvm_info("body", "Entered...", UVM_LOW)
    // get cfg from p_sequencer
    cfg = p_sequencer.cfg;//?
    vif = cfg.vif;
    rgm = cfg.rgm;
    // TODO in sub-class
    `uvm_info("body", "Exiting...", UVM_LOW)
  endtask

  virtual function void compare_data(logic[31:0] val1, logic[31:0] val2);//?
    cfg.seq_check_count++;
    if(val1 === val2)
      `uvm_info("CMPSUC", $sformatf("val1 'h%0x === val2 'h%0x", val1, val2), UVM_LOW)
    else begin
      cfg.seq_check_error++;
      `uvm_error("CMPERR", $sformatf("val1 'h%0x !== val2 'h%0x", val1, val2))
    end
  endfunction


  task wait_reset_signal_assertted();
      @(posedge vif.rstn);
  endtask

  task wait_reset_signal_released();
      @(negedge vif.rstn);
  endtask

endclass

`endif  

-------------------顶层base test 和smoke test

`ifndef RKV_AHBRAM_BASE_TEST_SV
`define RKV_AHBRAM_BASE_TEST_SV

virtual class rkv_ahbram_base_test extends uvm_test;

  rkv_ahbram_config cfg;
  rkv_ahbram_env env;
  rkv_ahbram_rgm rgm;

  function new (string name = "rkv_ahbram_base_test", uvm_component parent);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    rgm = rkv_ahbram_rgm::type_id::create("rgm");//rgm的创建在test中
    rgm.build();
    uvm_config_db#(rkv_ahbram_rgm)::set(this, "env", "rgm", rgm);
    cfg = rkv_ahbram_config::type_id::create("cfg");//config的创建
    cfg.rgm = rgm;
    if(!uvm_config_db#(virtual rkv_ahbram_if)::get(this,"","vif", cfg.vif))
      `uvm_fatal("GETCFG","cannot get virtual interface from config DB")
    uvm_config_db#(rkv_ahbram_config)::set(this, "env", "cfg", cfg);
    env = rkv_ahbram_env::type_id::create("env", this);
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
  endfunction

  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    phase.phase_done.set_drain_time(this, 1us);
    phase.raise_objection(this);
    phase.drop_objection(this);
  endtask


endclass

`endif
`ifndef RKV_AHBRAM_SMOKE_TEST_SV
`define RKV_AHBRAM_SMOKE_TEST_SV

class rkv_ahbram_smoke_test extends rkv_ahbram_base_test;

  `uvm_component_utils(rkv_ahbram_smoke_test)

  function new (string name = "rkv_ahbram_smoke_test", uvm_component parent);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
  endfunction

  task run_phase(uvm_phase phase);
    rkv_ahbram_smoke_virt_seq seq = rkv_ahbram_smoke_virt_seq::type_id::create("this");//
    super.run_phase(phase);
    phase.raise_objection(this);
    seq.start(env.virt_sqr);
    phase.drop_objection(this);
  endtask

endclass

`endif

两个test文件存到tests文件里

最后文件都放package里

make elab

make run GUI=1 &

在顶层testbench:例化和set interface


module rkv_ahbram_tb;
  import uvm_pkg::*;
  `include "uvm_macros.svh"
  import rkv_ahbram_pkg::*;

  ahb_blockram_32 dut();

  lvc_ahb_if ahb_if();

  rkv_ahbram_if ahbram_if();

  initial begin
    uvm_config_db#(virtual lvc_ahb_if)::set(uvm_root::get(), "uvm_test_top.env.ahb_mst", "vif", ahb_if);
    uvm_config_db#(virtual rkv_ahbram_if)::set(uvm_root::get(), "uvm_test_top", "vif", ahbram_if);
    uvm_config_db#(virtual rkv_ahbram_if)::set(uvm_root::get(), "uvm_test_top.env", "vif", ahbram_if);
    uvm_config_db#(virtual rkv_ahbram_if)::set(uvm_root::get(), "uvm_test_top.env.virt_sqr", "vif", ahbram_if);
    run_test();
  end


endmodule

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值